steep 0.48.0 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/Gemfile +3 -1
  4. data/Gemfile.lock +3 -3
  5. data/lib/steep/ast/types/any.rb +2 -0
  6. data/lib/steep/ast/types/boolean.rb +2 -0
  7. data/lib/steep/ast/types/bot.rb +2 -0
  8. data/lib/steep/ast/types/class.rb +2 -0
  9. data/lib/steep/ast/types/factory.rb +1 -1
  10. data/lib/steep/ast/types/helper.rb +8 -0
  11. data/lib/steep/ast/types/instance.rb +2 -0
  12. data/lib/steep/ast/types/intersection.rb +4 -0
  13. data/lib/steep/ast/types/literal.rb +2 -0
  14. data/lib/steep/ast/types/logic.rb +2 -0
  15. data/lib/steep/ast/types/name.rb +6 -0
  16. data/lib/steep/ast/types/nil.rb +2 -0
  17. data/lib/steep/ast/types/proc.rb +9 -0
  18. data/lib/steep/ast/types/record.rb +4 -0
  19. data/lib/steep/ast/types/self.rb +2 -0
  20. data/lib/steep/ast/types/top.rb +2 -0
  21. data/lib/steep/ast/types/tuple.rb +4 -0
  22. data/lib/steep/ast/types/union.rb +4 -0
  23. data/lib/steep/ast/types/var.rb +2 -0
  24. data/lib/steep/ast/types/void.rb +2 -0
  25. data/lib/steep/cli.rb +5 -0
  26. data/lib/steep/diagnostic/ruby.rb +13 -0
  27. data/lib/steep/drivers/check.rb +3 -2
  28. data/lib/steep/drivers/langserver.rb +2 -2
  29. data/lib/steep/drivers/stats.rb +1 -0
  30. data/lib/steep/drivers/utils/jobs_count.rb +1 -1
  31. data/lib/steep/drivers/watch.rb +1 -1
  32. data/lib/steep/interface/function.rb +9 -0
  33. data/lib/steep/project.rb +15 -1
  34. data/lib/steep/server/interaction_worker.rb +2 -2
  35. data/lib/steep/server/master.rb +9 -4
  36. data/lib/steep/server/type_check_worker.rb +19 -4
  37. data/lib/steep/server/worker_process.rb +15 -6
  38. data/lib/steep/services/goto_service.rb +19 -4
  39. data/lib/steep/services/type_check_service.rb +2 -0
  40. data/lib/steep/signature/validator.rb +12 -5
  41. data/lib/steep/subtyping/check.rb +23 -2
  42. data/lib/steep/type_construction.rb +116 -39
  43. data/lib/steep/type_inference/block_params.rb +31 -3
  44. data/lib/steep/version.rb +1 -1
  45. data/smoke/diagnostics/proc_type_expected.rb +3 -0
  46. data/smoke/diagnostics/test_expectations.yml +12 -0
  47. data/smoke/tsort/a.rb +1 -1
  48. data/smoke/tsort/test_expectations.yml +1 -63
  49. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72c3b61eccfe6a3f2cf2da22293bd7b50a001c25e82197b3efea52753857ff78
4
- data.tar.gz: '08786e3140b0bbf10f79c5395a7026062abef6a690a9fefdf6ca464fbf13e92d'
3
+ metadata.gz: 6ff552f6d8f112693dc9969f20d851ddbc6d7d2f16cebd45f802a5d703618b58
4
+ data.tar.gz: 723464fe34c81c3e83b66338dfc6fd3e7c3da2aaf30c1fc48116c7de794ca961
5
5
  SHA512:
6
- metadata.gz: d3abc0d6f64deffebf187428be69cec72dc5c887e0ecb2fbc407c20e2dde66bae8ce3bdf5f7f8a43ccaa90c562fa9c178bb9cc93a3d3d5b7fa99d5e7344fbfdd
7
- data.tar.gz: df16f83cf33224f0442124546d3406313dff27bd472fc60978864c40cdffcbb9aa8013bb049c940021ccb6e76c7a1338d9d30fc0fb07f71e306e7dae21885ad7
6
+ metadata.gz: bf9f83791cfb636c65a26f404fb164fa7fc3906376e36a79a1ca4ae7eeab8020e23c5b9ce5e649a38ed79080d0aa2c00fe53a5cce8a1c76c259237f38880bbf2
7
+ data.tar.gz: 25bd9e11db283acdfc957682860e674d544b82be1b5a68bc87ca96888907966b721301c937cdaa3e06bf0226ec82fa8c78eacfaf4987637a601f75ca8d8e950c
data/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  ## master
4
4
 
5
+ # 0.50.0 (2022-03-22)
6
+
7
+ * CLI option for override steep command at spawn worker ([\#511](https://github.com/soutaro/steep/pull/511))
8
+ * LSP related improvements for Sublime LSP ([\#513](https://github.com/soutaro/steep/pull/513))
9
+ * Support Windows environment ([\#514](https://github.com/soutaro/steep/pull/514))
10
+ * Let `&:foo` proc work with methods with optional parameters ([\#516](https://github.com/soutaro/steep/pull/516))
11
+ * Fix unexpected error when or-asgn/and-asgn ([\#517](https://github.com/soutaro/steep/pull/517))
12
+ * Fix goto-definition from method call inside block ([\#518](https://github.com/soutaro/steep/pull/518))
13
+ * Better splat in array typing ([\#519](https://github.com/soutaro/steep/pull/519))
14
+
15
+ ## 0.49.1 (2022-03-11)
16
+
17
+ * Fix lambda typing ([\#506](https://github.com/soutaro/steep/pull/506))
18
+ * Validate type descendants ([\#507](https://github.com/soutaro/steep/pull/507))
19
+ * Fix print error with absolute path ([\#508](https://github.com/soutaro/steep/pull/508))
20
+ * Skip non-target ruby code on `steep stats` ([\#509](https://github.com/soutaro/steep/pull/509))
21
+
22
+ ## 0.49.0 (2022-03-08)
23
+
24
+ * Better typing for `#flat_map` ([\#504](https://github.com/soutaro/steep/pull/504))
25
+ * Support lambdas (`->`) with block ([\#503](https://github.com/soutaro/steep/pull/503))
26
+ * Let proc type be `::Proc` class instance ([\#502](https://github.com/soutaro/steep/pull/502))
27
+ * Disable contextual typing on `bool` type ([\#501](https://github.com/soutaro/steep/pull/501))
28
+ * Type check `return` without value ([\#500](https://github.com/soutaro/steep/pull/500))
29
+
5
30
  ## 0.48.0 (2022-03-07)
6
31
 
7
32
  Steep supports all of the new features of RBS 2. 🎉
data/Gemfile CHANGED
@@ -9,4 +9,6 @@ gem "without_steep_types", path: "test/gems/without_steep_types"
9
9
  gem "rake"
10
10
  gem "minitest", "~> 5.15"
11
11
  gem "minitest-hooks"
12
- gem "stackprof"
12
+ group :stackprof, optional: true do
13
+ gem "stackprof"
14
+ end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steep (0.48.0)
4
+ steep (0.50.0)
5
5
  activesupport (>= 5.1)
6
6
  language_server-protocol (>= 3.15, < 4.0)
7
7
  listen (~> 3.0)
@@ -24,7 +24,7 @@ PATH
24
24
  GEM
25
25
  remote: https://rubygems.org/
26
26
  specs:
27
- activesupport (7.0.2.2)
27
+ activesupport (7.0.2.3)
28
28
  concurrent-ruby (~> 1.0, >= 1.0.2)
29
29
  i18n (>= 1.6, < 2)
30
30
  minitest (>= 5.1)
@@ -41,7 +41,7 @@ GEM
41
41
  minitest (5.15.0)
42
42
  minitest-hooks (1.5.0)
43
43
  minitest (> 5.3)
44
- parallel (1.21.0)
44
+ parallel (1.22.0)
45
45
  parser (3.1.1.0)
46
46
  ast (~> 2.4.1)
47
47
  rainbow (3.1.1)
@@ -28,6 +28,8 @@ module Steep
28
28
 
29
29
  include Helper::NoFreeVariables
30
30
 
31
+ include Helper::NoChild
32
+
31
33
  def level
32
34
  [1]
33
35
  end
@@ -28,6 +28,8 @@ module Steep
28
28
 
29
29
  include Helper::NoFreeVariables
30
30
 
31
+ include Helper::NoChild
32
+
31
33
  def level
32
34
  [0]
33
35
  end
@@ -28,6 +28,8 @@ module Steep
28
28
 
29
29
  include Helper::NoFreeVariables
30
30
 
31
+ include Helper::NoChild
32
+
31
33
  def level
32
34
  [2]
33
35
  end
@@ -30,6 +30,8 @@ module Steep
30
30
  @fvs = Set.new([self])
31
31
  end
32
32
 
33
+ include Helper::NoChild
34
+
33
35
  def level
34
36
  [0]
35
37
  end
@@ -393,7 +393,7 @@ module Steep
393
393
  when AST::Types::Name::Alias
394
394
  unwrap_optional(expand_alias(type))
395
395
  when AST::Types::Boolean
396
- [AST::Builtin.true_type, AST::Builtin.false_type]
396
+ [type, type]
397
397
  else
398
398
  [type, nil]
399
399
  end
@@ -21,6 +21,14 @@ module Steep
21
21
  @fvs ||= Set.new
22
22
  end
23
23
  end
24
+
25
+ module NoChild
26
+ def each_child(&block)
27
+ unless block
28
+ enum_for :each_child
29
+ end
30
+ end
31
+ end
24
32
  end
25
33
  end
26
34
  end
@@ -26,6 +26,8 @@ module Steep
26
26
  @fvs = Set.new([self])
27
27
  end
28
28
 
29
+ include Helper::NoChild
30
+
29
31
  def to_s
30
32
  "instance"
31
33
  end
@@ -72,6 +72,10 @@ module Steep
72
72
 
73
73
  include Helper::ChildrenLevel
74
74
 
75
+ def each_child(&block)
76
+ types.each(&block)
77
+ end
78
+
75
79
  def level
76
80
  [0] + level_of_children(types)
77
81
  end
@@ -31,6 +31,8 @@ module Steep
31
31
 
32
32
  include Helper::NoFreeVariables
33
33
 
34
+ include Helper::NoChild
35
+
34
36
  def level
35
37
  [0]
36
38
  end
@@ -13,6 +13,8 @@ module Steep
13
13
  @fvs ||= Set[]
14
14
  end
15
15
 
16
+ include Helper::NoChild
17
+
16
18
  def hash
17
19
  self.class.hash
18
20
  end
@@ -72,6 +72,10 @@ module Steep
72
72
  end
73
73
  end
74
74
 
75
+ def each_child(&block)
76
+ args.each(&block)
77
+ end
78
+
75
79
  include Helper::ChildrenLevel
76
80
 
77
81
  def level
@@ -98,6 +102,8 @@ module Steep
98
102
  def with_location(new_location)
99
103
  self.class.new(name: name, location: new_location)
100
104
  end
105
+
106
+ include Helper::NoChild
101
107
  end
102
108
 
103
109
  class Instance < Applying
@@ -28,6 +28,8 @@ module Steep
28
28
 
29
29
  include Helper::NoFreeVariables
30
30
 
31
+ include Helper::NoChild
32
+
31
33
  def level
32
34
  [0]
33
35
  end
@@ -90,6 +90,15 @@ module Steep
90
90
  def block_required?
91
91
  block && !block.optional?
92
92
  end
93
+
94
+ def each_child(&block)
95
+ if block_given?
96
+ type.each_child(&block)
97
+ self.block&.type&.each_child(&block)
98
+ else
99
+ enum_for :each_child
100
+ end
101
+ end
93
102
  end
94
103
  end
95
104
  end
@@ -42,6 +42,10 @@ module Steep
42
42
 
43
43
  include Helper::ChildrenLevel
44
44
 
45
+ def each_child(&block)
46
+ elements.each_value(&block)
47
+ end
48
+
45
49
  def level
46
50
  [0] + level_of_children(elements.values)
47
51
  end
@@ -22,6 +22,8 @@ module Steep
22
22
  "self"
23
23
  end
24
24
 
25
+ include Helper::NoChild
26
+
25
27
  def subst(s)
26
28
  s.self_type or raise "Unexpected substitution: #{inspect}"
27
29
  end
@@ -28,6 +28,8 @@ module Steep
28
28
 
29
29
  include Helper::NoFreeVariables
30
30
 
31
+ include Helper::NoChild
32
+
31
33
  def level
32
34
  [2]
33
35
  end
@@ -40,6 +40,10 @@ module Steep
40
40
 
41
41
  include Helper::ChildrenLevel
42
42
 
43
+ def each_child(&block)
44
+ types.each(&block)
45
+ end
46
+
43
47
  def level
44
48
  [0] + level_of_children(types)
45
49
  end
@@ -70,6 +70,10 @@ module Steep
70
70
  end
71
71
  end
72
72
 
73
+ def each_child(&block)
74
+ types.each(&block)
75
+ end
76
+
73
77
  include Helper::ChildrenLevel
74
78
 
75
79
  def level
@@ -52,6 +52,8 @@ module Steep
52
52
  @fvs ||= Set.new([name])
53
53
  end
54
54
 
55
+ include Helper::NoChild
56
+
55
57
  def level
56
58
  [0]
57
59
  end
@@ -28,6 +28,8 @@ module Steep
28
28
 
29
29
  include Helper::NoFreeVariables
30
30
 
31
+ include Helper::NoChild
32
+
31
33
  def level
32
34
  [0]
33
35
  end
data/lib/steep/cli.rb CHANGED
@@ -72,6 +72,11 @@ module Steep
72
72
  opts.on("-j N", "--jobs=N", "Specify the number of type check workers (defaults: #{default})") do |count|
73
73
  command.jobs_count = Integer(count) if Integer(count) > 0
74
74
  end
75
+
76
+ command.steep_command = "steep"
77
+ opts.on("--steep-command=COMMAND", "Specify command to exec Steep CLI for worker (defaults: steep)") do |cmd|
78
+ command.steep_command = cmd
79
+ end
75
80
  end
76
81
 
77
82
  def process_init
@@ -669,6 +669,19 @@ module Steep
669
669
  end
670
670
  end
671
671
 
672
+ class ProcTypeExpected < Base
673
+ attr_reader :type
674
+
675
+ def initialize(node:, type:)
676
+ super(node: node)
677
+ @type = type
678
+ end
679
+
680
+ def header_line
681
+ "Proc type is expected but `#{type.to_s}` is specified"
682
+ end
683
+ end
684
+
672
685
  class UnsupportedSyntax < Base
673
686
  attr_reader :message
674
687
 
@@ -39,6 +39,7 @@ module Steep
39
39
  steepfile: project.steepfile_path,
40
40
  args: command_line_patterns,
41
41
  delay_shutdown: true,
42
+ steep_command: steep_command,
42
43
  count: jobs_count
43
44
  )
44
45
 
@@ -214,8 +215,8 @@ module Steep
214
215
  total = errors.sum {|notification| notification[:diagnostics].size }
215
216
 
216
217
  errors.each do |notification|
217
- path = project.relative_path(Pathname(URI.parse(notification[:uri]).path))
218
- buffer = RBS::Buffer.new(name: path, content: path.read)
218
+ path = Pathname(URI.parse(notification[:uri]).path)
219
+ buffer = RBS::Buffer.new(name: project.relative_path(path), content: path.read)
219
220
  printer = DiagnosticPrinter.new(buffer: buffer, stdout: stdout)
220
221
 
221
222
  notification[:diagnostics].each do |diag|
@@ -37,8 +37,8 @@ module Steep
37
37
  def run
38
38
  @project = load_config()
39
39
 
40
- interaction_worker = Server::WorkerProcess.spawn_worker(:interaction, name: "interaction", steepfile: project.steepfile_path)
41
- typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: [], count: jobs_count)
40
+ interaction_worker = Server::WorkerProcess.spawn_worker(:interaction, name: "interaction", steepfile: project.steepfile_path, steep_command: steep_command)
41
+ typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: [], steep_command: steep_command, count: jobs_count)
42
42
 
43
43
  master = Server::Master.new(
44
44
  project: project,
@@ -129,6 +129,7 @@ module Steep
129
129
  steepfile: project.steepfile_path,
130
130
  delay_shutdown: true,
131
131
  args: command_line_patterns,
132
+ steep_command: steep_command,
132
133
  count: jobs_count
133
134
  )
134
135
 
@@ -2,7 +2,7 @@ module Steep
2
2
  module Drivers
3
3
  module Utils
4
4
  module JobsCount
5
- attr_accessor :jobs_count
5
+ attr_accessor :jobs_count, :steep_command
6
6
  end
7
7
  end
8
8
  end
@@ -41,7 +41,7 @@ module Steep
41
41
  server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
42
42
  server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
43
43
 
44
- typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: dirs.map(&:to_s), count: jobs_count)
44
+ typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: dirs.map(&:to_s), steep_command: steep_command, count: jobs_count)
45
45
 
46
46
  master = Server::Master.new(
47
47
  project: project,
@@ -879,6 +879,11 @@ module Steep
879
879
  !has_positional? && !has_keywords?
880
880
  end
881
881
 
882
+ # Returns true if all arguments are non-required.
883
+ def optional?
884
+ required.empty? && required_keywords.empty?
885
+ end
886
+
882
887
  # self + params returns a new params for overloading.
883
888
  #
884
889
  def +(other)
@@ -952,6 +957,10 @@ module Steep
952
957
  )
953
958
  end
954
959
 
960
+ def each_child(&block)
961
+ each_type(&block)
962
+ end
963
+
955
964
  def each_type(&block)
956
965
  if block_given?
957
966
  params.each_type(&block)
data/lib/steep/project.rb CHANGED
@@ -16,7 +16,21 @@ module Steep
16
16
  steepfile_path.parent
17
17
  end
18
18
 
19
- def relative_path(path)
19
+ def relative_path(orig_path)
20
+ path = if Gem.win_platform?
21
+ path_str = URI.decode_www_form_component(
22
+ orig_path.to_s.delete_prefix("/")
23
+ )
24
+ unless path_str.start_with?(%r{[a-z]:/}i)
25
+ # FIXME: Sometimes drive letter is missing, taking from base_dir
26
+ path_str = base_dir.to_s.split("/")[0] + "/" + path_str
27
+ end
28
+ Pathname.new(
29
+ path_str
30
+ )
31
+ else
32
+ orig_path
33
+ end
20
34
  path.relative_path_from(base_dir)
21
35
  end
22
36
 
@@ -89,7 +89,7 @@ module Steep
89
89
  end
90
90
 
91
91
  LSP::Interface::Hover.new(
92
- contents: { kind: "markdown", value: format_hover(content) },
92
+ contents: { kind: "markdown", value: format_hover(content)&.gsub(/<!--(?~-->)-->/, "") },
93
93
  range: range
94
94
  )
95
95
  end
@@ -271,7 +271,7 @@ HOVER
271
271
  ),
272
272
  end: LanguageServer::Protocol::Interface::Position.new(
273
273
  line: job.line - 1,
274
- character: job.column - prefix.size
274
+ character: job.column
275
275
  )
276
276
  )
277
277
 
@@ -49,9 +49,14 @@ module Steep
49
49
  end
50
50
 
51
51
  def checking_path?(path)
52
- library_paths.include?(path) ||
53
- signature_paths.include?(path) ||
54
- code_paths.include?(path)
52
+ [library_paths, signature_paths, code_paths].any? do |paths|
53
+ if Gem.win_platform?
54
+ # FIXME: Sometimes drive letter is missing, so comparing without drive letter.
55
+ paths.any? {|p| p.to_s.split("/", 2)[1] == path.to_s.split("/", 2)[1]}
56
+ else
57
+ paths.include?(path)
58
+ end
59
+ end
55
60
  end
56
61
 
57
62
  def checked(path)
@@ -739,7 +744,7 @@ module Steep
739
744
  { kind: "end" }
740
745
  else
741
746
  progress_string = ("▮"*(percentage/5)) + ("▯"*(20 - percentage/5))
742
- { kind: "report", percentage: percentage, message: "#{progress_string} (#{percentage}%)" }
747
+ { kind: "report", percentage: percentage, message: "#{progress_string}" }
743
748
  end
744
749
 
745
750
  job_queue << SendMessageJob.to_client(
@@ -135,6 +135,21 @@ module Steep
135
135
  end
136
136
 
137
137
  def handle_job(job)
138
+ job_path = if job.respond_to?(:path)
139
+ if Gem.win_platform?
140
+ # FIXME: Sometimes drive letter is missing, using base_dir
141
+ if job.path.to_s.start_with?(%r{/[a-z](:|%3A)/}i)
142
+ job.path.to_s
143
+ else
144
+ "/#{project.base_dir.to_s.split("/").first}/#{job.path}"
145
+ end
146
+ else
147
+ job.path.to_s
148
+ end
149
+ else
150
+ nil
151
+ end
152
+
138
153
  case job
139
154
  when StartTypeCheckJob
140
155
  Steep.logger.info { "Processing StartTypeCheckJob for guid=#{job.guid}" }
@@ -149,7 +164,7 @@ module Steep
149
164
  writer.write(
150
165
  method: :"textDocument/publishDiagnostics",
151
166
  params: LSP::Interface::PublishDiagnosticsParams.new(
152
- uri: URI.parse(job.path.to_s).tap {|uri| uri.scheme = "file"},
167
+ uri: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
153
168
  diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
154
169
  )
155
170
  )
@@ -167,7 +182,7 @@ module Steep
167
182
  writer.write(
168
183
  method: :"textDocument/publishDiagnostics",
169
184
  params: LSP::Interface::PublishDiagnosticsParams.new(
170
- uri: URI.parse(job.path.to_s).tap {|uri| uri.scheme = "file"},
185
+ uri: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
171
186
  diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
172
187
  )
173
188
  )
@@ -186,7 +201,7 @@ module Steep
186
201
  writer.write(
187
202
  method: :"textDocument/publishDiagnostics",
188
203
  params: LSP::Interface::PublishDiagnosticsParams.new(
189
- uri: URI.parse(job.path.to_s).tap {|uri| uri.scheme = "file"},
204
+ uri: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
190
205
  diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
191
206
  )
192
207
  )
@@ -268,7 +283,7 @@ module Steep
268
283
  line = job.params[:position][:line] + 1
269
284
  column = job.params[:position][:character]
270
285
 
271
- goto_service = Services::GotoService.new(type_check: service)
286
+ goto_service = Services::GotoService.new(type_check: service, assignment: assignment)
272
287
  locations =
273
288
  case
274
289
  when job.definition?
@@ -18,13 +18,17 @@ module Steep
18
18
  @index = index
19
19
  end
20
20
 
21
- def self.spawn_worker(type, name:, steepfile:, options: [], delay_shutdown: false, index: nil)
22
- log_level = %w(debug info warn error fatal unknown)[Steep.logger.level]
21
+ def self.spawn_worker(type, name:, steepfile:, steep_command: "steep", options: [], delay_shutdown: false, index: nil)
22
+ args = ["--name=#{name}", "--steepfile=#{steepfile}"]
23
+ args << (%w(debug info warn error fatal unknown)[Steep.logger.level].yield_self {|log_level| "--log-level=#{log_level}" })
24
+ if Steep.log_output.is_a?(String)
25
+ args << "--log-output=#{Steep.log_output}"
26
+ end
23
27
  command = case type
24
28
  when :interaction
25
- ["steep", "worker", "--interaction", "--name=#{name}", "--log-level=#{log_level}", "--steepfile=#{steepfile}", *options]
29
+ [steep_command, "worker", "--interaction", *args, *options]
26
30
  when :typecheck
27
- ["steep", "worker", "--typecheck", "--name=#{name}", "--log-level=#{log_level}", "--steepfile=#{steepfile}", *options]
31
+ [steep_command, "worker", "--typecheck", *args, *options]
28
32
  else
29
33
  raise "Unknown type: #{type}"
30
34
  end
@@ -33,7 +37,11 @@ module Steep
33
37
  command << "--delay-shutdown"
34
38
  end
35
39
 
36
- stdin, stdout, thread = Open3.popen2(*command, pgroup: true)
40
+ stdin, stdout, thread = if Gem.win_platform?
41
+ Open3.popen2(*command, new_pgroup: true)
42
+ else
43
+ Open3.popen2(*command, pgroup: true)
44
+ end
37
45
  stderr = nil
38
46
 
39
47
  writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin)
@@ -42,11 +50,12 @@ module Steep
42
50
  new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index)
43
51
  end
44
52
 
45
- def self.spawn_typecheck_workers(steepfile:, args:, count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
53
+ def self.spawn_typecheck_workers(steepfile:, args:, steep_command: "steep", count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
46
54
  count.times.map do |i|
47
55
  spawn_worker(:typecheck,
48
56
  name: "typecheck@#{i}",
49
57
  steepfile: steepfile,
58
+ steep_command: steep_command,
50
59
  options: ["--max-index=#{count}", "--index=#{i}", *args],
51
60
  delay_shutdown: delay_shutdown,
52
61
  index: i)
@@ -21,10 +21,11 @@ module Steep
21
21
  end
22
22
  TypeNameQuery = Struct.new(:name, keyword_init: true)
23
23
 
24
- attr_reader :type_check
24
+ attr_reader :type_check, :assignment
25
25
 
26
- def initialize(type_check:)
26
+ def initialize(type_check:, assignment:)
27
27
  @type_check = type_check
28
+ @assignment = assignment
28
29
  end
29
30
 
30
31
  def project
@@ -78,7 +79,17 @@ module Steep
78
79
  end
79
80
  end
80
81
 
81
- locations.uniq
82
+ # Drop un-assigned paths here.
83
+ # The path assignment makes sense only for `.rbs` files, because un-assigned `.rb` files are already skipped since they are not type checked.
84
+ #
85
+ locations.uniq.select do |loc|
86
+ case loc
87
+ when RBS::Location
88
+ assignment =~ loc.name
89
+ else
90
+ true
91
+ end
92
+ end
82
93
  end
83
94
 
84
95
  def test_ast_location(loc, line:, column:)
@@ -100,6 +111,7 @@ module Steep
100
111
  typing, signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
101
112
  if typing
102
113
  node, *parents = typing.source.find_nodes(line: line, column: column)
114
+
103
115
  if node
104
116
  case node.type
105
117
  when :const, :casgn
@@ -125,7 +137,10 @@ module Steep
125
137
  end
126
138
  when :send
127
139
  if test_ast_location(node.location.selector, line: line, column: column)
128
- node = parents[0] if parents[0]&.type == :block
140
+ if (parent = parents[0]) && parent.type == :block && parent.children[0] == node
141
+ node = parents[0]
142
+ end
143
+
129
144
  case call = typing.call_of(node: node)
130
145
  when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
131
146
  call.method_decls.each do |decl|
@@ -269,6 +269,8 @@ module Steep
269
269
  end
270
270
 
271
271
  def typecheck_source(path:, target: project.target_for_source_path(path), &block)
272
+ return unless target
273
+
272
274
  Steep.logger.tagged "#typecheck_source(path=#{path})" do
273
275
  Steep.measure "typecheck" do
274
276
  signature_service = signature_services[target.name]
@@ -89,11 +89,7 @@ module Steep
89
89
  end
90
90
  end
91
91
 
92
- def validate_type(type)
93
- Steep.logger.debug "#{Location.to_string type.location}: Validating #{type}..."
94
-
95
- validator.validate_type type, context: [RBS::Namespace.root]
96
-
92
+ def validate_type_application(type)
97
93
  name, type_params, type_args =
98
94
  case type
99
95
  when RBS::Types::ClassInstance
@@ -123,6 +119,17 @@ module Steep
123
119
  validate_type_application_constraints(type.name, type_params, type_args, location: type.location)
124
120
  end
125
121
  end
122
+
123
+ type.each_type do |child|
124
+ validate_type_application(child)
125
+ end
126
+ end
127
+
128
+ def validate_type(type)
129
+ Steep.logger.debug "#{Location.to_string type.location}: Validating #{type}..."
130
+
131
+ validator.validate_type type, context: [RBS::Namespace.root]
132
+ validate_type_application(type)
126
133
  end
127
134
 
128
135
  def ancestor_to_type(ancestor)
@@ -347,7 +347,7 @@ module Steep
347
347
 
348
348
  when relation.super_type.is_a?(AST::Types::Union)
349
349
  Any(relation) do |result|
350
- relation.super_type.types.each do |super_type|
350
+ relation.super_type.types.sort_by {|ty| (path = hole_path(ty)) ? -path.size : 1 }.each do |super_type|
351
351
  rel = Relation.new(sub_type: relation.sub_type, super_type: super_type)
352
352
  result.add(rel) do
353
353
  check_type(rel)
@@ -357,7 +357,7 @@ module Steep
357
357
 
358
358
  when relation.sub_type.is_a?(AST::Types::Intersection)
359
359
  Any(relation) do |result|
360
- relation.sub_type.types.each do |sub_type|
360
+ relation.sub_type.types.sort_by {|ty| (path = hole_path(ty)) ? -path.size : 1 }.each do |sub_type|
361
361
  rel = Relation.new(sub_type: sub_type, super_type: relation.super_type)
362
362
  result.add(rel) do
363
363
  check_type(rel)
@@ -483,6 +483,9 @@ module Steep
483
483
  check_interface(relation.map {|type| factory.interface(type, private: false) })
484
484
  end
485
485
 
486
+ when relation.sub_type.is_a?(AST::Types::Proc) && AST::Builtin::Proc.instance_type?(relation.super_type)
487
+ Success(relation)
488
+
486
489
  when relation.super_type.is_a?(AST::Types::Literal)
487
490
  case
488
491
  when relation.super_type.value == true && AST::Builtin::TrueClass.instance_type?(relation.sub_type)
@@ -971,6 +974,24 @@ module Steep
971
974
  def expand_alias(type, &block)
972
975
  factory.expand_alias(type, &block)
973
976
  end
977
+
978
+ # Returns the shortest type paths for one of the _unknown_ type variables.
979
+ # Returns nil if there is no path.
980
+ def hole_path(type, path = [])
981
+ case type
982
+ when AST::Types::Var
983
+ if constraints.unknown?(type.name)
984
+ [type]
985
+ else
986
+ nil
987
+ end
988
+ else
989
+ paths = type.each_child.map do |ty|
990
+ hole_path(ty, path)&.unshift(ty)
991
+ end
992
+ paths.compact.min_by(&:size)
993
+ end
994
+ end
974
995
  end
975
996
  end
976
997
  end
@@ -1005,7 +1005,7 @@ module Steep
1005
1005
  yield_self do
1006
1006
  send_node, params, body = node.children
1007
1007
  if send_node.type == :lambda
1008
- type_lambda(node, block_params: params, block_body: body, type_hint: hint)
1008
+ type_lambda(node, params_node: params, body_node: body, type_hint: hint)
1009
1009
  else
1010
1010
  type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend)
1011
1011
  end
@@ -1024,7 +1024,7 @@ module Steep
1024
1024
  params = Parser::AST::Node.new(:args, arg_nodes)
1025
1025
 
1026
1026
  if send_node.type == :lambda
1027
- type_lambda(node, block_params: params, block_body: body, type_hint: hint)
1027
+ type_lambda(node, params_node: params, body_node: body, type_hint: hint)
1028
1028
  else
1029
1029
  type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend)
1030
1030
  end
@@ -1181,9 +1181,9 @@ module Steep
1181
1181
 
1182
1182
  when :return
1183
1183
  yield_self do
1184
- if node.children.size > 0
1185
- method_return_type = expand_alias(method_context&.return_type)
1184
+ method_return_type = expand_alias(method_context&.return_type)
1186
1185
 
1186
+ if node.children.size > 0
1187
1187
  return_types = node.children.map do |value|
1188
1188
  synthesize(
1189
1189
  value,
@@ -1201,20 +1201,23 @@ module Steep
1201
1201
  AST::Builtin::Array.instance_type(union_type(*return_types))
1202
1202
  end
1203
1203
 
1204
- if method_return_type
1205
- unless method_return_type.is_a?(AST::Types::Void)
1206
- result = check_relation(sub_type: value_type, super_type: method_return_type)
1204
+ else
1205
+ value_type = AST::Builtin.nil_type
1206
+ end
1207
1207
 
1208
- if result.failure?
1209
- typing.add_error(
1210
- Diagnostic::Ruby::ReturnTypeMismatch.new(
1211
- node: node,
1212
- expected: method_context&.return_type,
1213
- actual: value_type,
1214
- result: result
1215
- )
1208
+ if method_return_type
1209
+ unless method_return_type.is_a?(AST::Types::Void)
1210
+ result = check_relation(sub_type: value_type, super_type: method_return_type)
1211
+
1212
+ if result.failure?
1213
+ typing.add_error(
1214
+ Diagnostic::Ruby::ReturnTypeMismatch.new(
1215
+ node: node,
1216
+ expected: method_context&.return_type,
1217
+ actual: value_type,
1218
+ result: result
1216
1219
  )
1217
- end
1220
+ )
1218
1221
  end
1219
1222
  end
1220
1223
  end
@@ -2272,13 +2275,10 @@ module Steep
2272
2275
  type, constr = synthesize(rhs, hint: hint)
2273
2276
  constr.ivasgn(asgn, type)
2274
2277
  when :send
2275
- rhs_ = node.updated(:send,
2276
- [
2277
- asgn.children[0],
2278
- :"#{asgn.children[1]}=",
2279
- asgn.children[2],
2280
- rhs
2281
- ])
2278
+ children = asgn.children.dup
2279
+ children[1] = :"#{children[1]}="
2280
+ send_arg_nodes = [*children, rhs]
2281
+ rhs_ = node.updated(:send, send_arg_nodes)
2282
2282
  node_type = case node.type
2283
2283
  when :or_asgn
2284
2284
  :or
@@ -2345,11 +2345,11 @@ module Steep
2345
2345
  interface = calculate_interface(param_type, private: true)
2346
2346
  method = interface.methods[value.children[0]]
2347
2347
  if method
2348
- return_types = method.method_types.select {|method_type|
2349
- method_type.type.params.empty?
2350
- }.map {|method_type|
2351
- method_type.type.return_type
2352
- }
2348
+ return_types = method.method_types.filter_map do |method_type|
2349
+ if method_type.type.params.optional?
2350
+ method_type.type.return_type
2351
+ end
2352
+ end
2353
2353
 
2354
2354
  unless return_types.empty?
2355
2355
  type = AST::Types::Proc.new(
@@ -2357,7 +2357,7 @@ module Steep
2357
2357
  params: Interface::Function::Params.empty.with_first_param(
2358
2358
  Interface::Function::Params::PositionalParams::Required.new(param_type)
2359
2359
  ),
2360
- return_type: AST::Types::Union.build(types: return_types),
2360
+ return_type: return_types[0],
2361
2361
  location: nil
2362
2362
  ),
2363
2363
  block: nil
@@ -2724,34 +2724,89 @@ module Steep
2724
2724
  end
2725
2725
  end
2726
2726
 
2727
- def type_lambda(node, block_params:, block_body:, type_hint:)
2727
+ def optional_proc?(type)
2728
+ if type.is_a?(AST::Types::Union)
2729
+ if type.types.size == 2
2730
+ if type.types.find {|t| t.is_a?(AST::Types::Nil) }
2731
+ if proc_type = type.types.find {|t| t.is_a?(AST::Types::Proc) }
2732
+ proc_type
2733
+ end
2734
+ end
2735
+ end
2736
+ end
2737
+ end
2738
+
2739
+ def type_lambda(node, params_node:, body_node:, type_hint:)
2728
2740
  block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2729
- params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
2741
+ params = TypeInference::BlockParams.from_node(params_node, annotations: block_annotations)
2742
+
2743
+ type_hint = deep_expand_alias(type_hint) if type_hint
2730
2744
 
2731
2745
  case type_hint
2732
2746
  when AST::Types::Proc
2733
2747
  params_hint = type_hint.type.params
2734
2748
  return_hint = type_hint.type.return_type
2749
+ block_hint = type_hint.block
2735
2750
  end
2736
2751
 
2737
2752
  block_constr = for_block(
2738
2753
  block_params: params,
2739
2754
  block_param_hint: params_hint,
2740
2755
  block_type_hint: return_hint,
2756
+ block_block_hint: block_hint,
2741
2757
  block_annotations: block_annotations,
2742
2758
  node_type_hint: nil
2743
2759
  )
2744
2760
 
2745
2761
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
2746
2762
 
2763
+ default_proc_function =
2764
+ Interface::Function.new(
2765
+ params: Interface::Function::Params.empty,
2766
+ return_type: AST::Builtin.any_type,
2767
+ location: nil
2768
+ )
2769
+
2747
2770
  params.params.each do |param|
2748
2771
  _, block_constr = block_constr.synthesize(param.node, hint: param.type)
2749
2772
  end
2750
2773
 
2751
- if block_body
2774
+ block =
2775
+ if block_param = params.block_param
2776
+ if block_param_type = block_param.type
2777
+ case block_param_type
2778
+ when AST::Types::Proc
2779
+ Interface::Block.new(type: block_param_type.type, optional: false)
2780
+ else
2781
+ if proc_type = optional_proc?(block_param_type)
2782
+ Interface::Block.new(type: proc_type.type, optional: true)
2783
+ else
2784
+ block_constr.typing.add_error(
2785
+ Diagnostic::Ruby::ProcTypeExpected.new(
2786
+ node: block_param.node,
2787
+ type: block_param_type
2788
+ )
2789
+ )
2790
+
2791
+ Interface::Block.new(
2792
+ type: Interface::Function.new(
2793
+ params: Interface::Function::Params.empty,
2794
+ return_type: AST::Builtin.any_type,
2795
+ location: nil
2796
+ ),
2797
+ optional: false
2798
+ )
2799
+ end
2800
+ end
2801
+ else
2802
+ block_hint
2803
+ end
2804
+ end
2805
+
2806
+ if body_node
2752
2807
  return_type = block_constr.synthesize_block(
2753
2808
  node: node,
2754
- block_body: block_body,
2809
+ block_body: body_node,
2755
2810
  block_type_hint: return_hint
2756
2811
  )
2757
2812
 
@@ -2779,7 +2834,7 @@ module Steep
2779
2834
  return_type: return_type,
2780
2835
  location: nil
2781
2836
  ),
2782
- block: nil
2837
+ block: block
2783
2838
  )
2784
2839
 
2785
2840
  add_typing node, type: block_type
@@ -3246,7 +3301,7 @@ module Steep
3246
3301
 
3247
3302
  if method_type.block
3248
3303
  # Method accepts block
3249
- pairs = method_type.block && block_params_&.zip(method_type.block.type.params)
3304
+ pairs = method_type.block && block_params_&.zip(method_type.block.type.params, nil)
3250
3305
 
3251
3306
  if pairs
3252
3307
  # Block parameters are compatible with the block type
@@ -3254,6 +3309,7 @@ module Steep
3254
3309
  block_params: block_params_,
3255
3310
  block_param_hint: method_type.block.type.params,
3256
3311
  block_type_hint: method_type.block.type.return_type,
3312
+ block_block_hint: nil,
3257
3313
  block_annotations: block_annotations,
3258
3314
  node_type_hint: method_type.type.return_type
3259
3315
  )
@@ -3503,13 +3559,14 @@ module Steep
3503
3559
  message: "Unsupported block params pattern, probably masgn?"
3504
3560
  )
3505
3561
  )
3506
- block_params = TypeInference::BlockParams.new(leading_params: [], optional_params: [], rest_param: nil, trailing_params: [])
3562
+ block_params = TypeInference::BlockParams.new(leading_params: [], optional_params: [], rest_param: nil, trailing_params: [], block_param: nil)
3507
3563
  end
3508
3564
 
3509
3565
  block_constr = for_block(
3510
3566
  block_params: block_params,
3511
3567
  block_param_hint: nil,
3512
3568
  block_type_hint: AST::Builtin.any_type,
3569
+ block_block_hint: nil,
3513
3570
  block_annotations: block_annotations,
3514
3571
  node_type_hint: AST::Builtin.any_type
3515
3572
  )
@@ -3536,8 +3593,8 @@ module Steep
3536
3593
  end
3537
3594
  end
3538
3595
 
3539
- def for_block(block_params:, block_param_hint:, block_type_hint:, block_annotations:, node_type_hint:)
3540
- block_param_pairs = block_param_hint && block_params.zip(block_param_hint)
3596
+ def for_block(block_params:, block_param_hint:, block_type_hint:, block_block_hint:, block_annotations:, node_type_hint:)
3597
+ block_param_pairs = block_param_hint && block_params.zip(block_param_hint, block_block_hint)
3541
3598
 
3542
3599
  param_types_hash = {}
3543
3600
  if block_param_pairs
@@ -3888,6 +3945,20 @@ module Steep
3888
3945
  constr.add_typing(node, type: AST::Types::Tuple.new(types: element_types))
3889
3946
  end
3890
3947
 
3948
+ def try_convert(type, method)
3949
+ interface = checker.factory.interface(type, private: false)
3950
+ if entry = interface.methods[method]
3951
+ method_type = entry.method_types.find do |method_type|
3952
+ method_type.type.params.optional?
3953
+ end
3954
+
3955
+ method_type.type.return_type
3956
+ end
3957
+ rescue => exn
3958
+ Steep.log_error(exn, message: "Unexpected error when converting #{type.to_s} with #{method}")
3959
+ nil
3960
+ end
3961
+
3891
3962
  def try_array_type(node, hint)
3892
3963
  element_hint = hint ? hint.args[0] : nil
3893
3964
 
@@ -3898,8 +3969,14 @@ module Steep
3898
3969
  case child.type
3899
3970
  when :splat
3900
3971
  type, constr = constr.synthesize(child.children[0], hint: hint)
3901
- if AST::Builtin::Array.instance_type?(type)
3972
+
3973
+ type = try_convert(type, :to_a) || type
3974
+
3975
+ case
3976
+ when AST::Builtin::Array.instance_type?(type)
3902
3977
  element_types << type.args[0]
3978
+ when type.is_a?(AST::Types::Tuple)
3979
+ element_types.push(*type.types)
3903
3980
  else
3904
3981
  element_types.push(*flatten_array_elements(type))
3905
3982
  end
@@ -29,12 +29,14 @@ module Steep
29
29
  attr_reader :optional_params
30
30
  attr_reader :rest_param
31
31
  attr_reader :trailing_params
32
+ attr_reader :block_param
32
33
 
33
- def initialize(leading_params:, optional_params:, rest_param:, trailing_params:)
34
+ def initialize(leading_params:, optional_params:, rest_param:, trailing_params:, block_param:)
34
35
  @leading_params = leading_params
35
36
  @optional_params = optional_params
36
37
  @rest_param = rest_param
37
38
  @trailing_params = trailing_params
39
+ @block_param = block_param
38
40
  end
39
41
 
40
42
  def params
@@ -43,6 +45,7 @@ module Steep
43
45
  params.push(*optional_params)
44
46
  params.push rest_param if rest_param
45
47
  params.push(*trailing_params)
48
+ params.push(block_param) if block_param
46
49
  end
47
50
  end
48
51
 
@@ -51,6 +54,7 @@ module Steep
51
54
  optional_params = []
52
55
  rest_param = nil
53
56
  trailing_params = []
57
+ block_param = nil
54
58
 
55
59
  default_params = leading_params
56
60
 
@@ -72,6 +76,9 @@ module Steep
72
76
  when :restarg
73
77
  default_params = trailing_params
74
78
  rest_param = Param.new(var: var, type: type, value: nil, node: arg)
79
+ when :blockarg
80
+ block_param = Param.new(var: var, type: type, value: nil, node: arg)
81
+ break
75
82
  end
76
83
  end
77
84
 
@@ -79,7 +86,8 @@ module Steep
79
86
  leading_params: leading_params,
80
87
  optional_params: optional_params,
81
88
  rest_param: rest_param,
82
- trailing_params: trailing_params
89
+ trailing_params: trailing_params,
90
+ block_param: block_param
83
91
  )
84
92
  end
85
93
 
@@ -141,7 +149,7 @@ module Steep
141
149
  )
142
150
  end
143
151
 
144
- def zip(params_type)
152
+ def zip(params_type, block)
145
153
  if trailing_params.any?
146
154
  Steep.logger.error "Block definition with trailing required parameters are not supported yet"
147
155
  end
@@ -204,6 +212,26 @@ module Steep
204
212
  end
205
213
  end
206
214
  end
215
+
216
+ if block_param
217
+ if block
218
+ proc_type =
219
+ if block.optional?
220
+ AST::Types::Union.build(
221
+ types: [
222
+ AST::Types::Proc.new(type: block.type, block: nil),
223
+ AST::Builtin.nil_type
224
+ ]
225
+ )
226
+ else
227
+ AST::Types::Proc.new(type: block.type, block: nil)
228
+ end
229
+
230
+ zip << [block_param, proc_type]
231
+ else
232
+ zip << [block_param, AST::Builtin.nil_type]
233
+ end
234
+ end
207
235
  end
208
236
  end
209
237
 
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.48.0"
2
+ VERSION = "0.50.0"
3
3
  end
@@ -0,0 +1,3 @@
1
+ -> (&block) do
2
+ # @type var block: Integer
3
+ end
@@ -332,6 +332,18 @@
332
332
  severity: ERROR
333
333
  message: Type `::Integer` does not have method `foo`
334
334
  code: Ruby::NoMethod
335
+ - file: proc_type_expected.rb
336
+ diagnostics:
337
+ - range:
338
+ start:
339
+ line: 1
340
+ character: 4
341
+ end:
342
+ line: 1
343
+ character: 10
344
+ severity: ERROR
345
+ message: Proc type is expected but `::Integer` is specified
346
+ code: Ruby::ProcTypeExpected
335
347
  - file: required_block_missing.rb
336
348
  diagnostics:
337
349
  - range:
data/smoke/tsort/a.rb CHANGED
@@ -8,5 +8,5 @@ each_node = -> (&b) { g.each_key(&b) }
8
8
  # @type var each_child: ^(Integer) { (Integer) -> void } -> void
9
9
  each_child = -> (n, &b) { g[n].each(&b) }
10
10
 
11
- # @type var xs: Array[String]
11
+ # @type var xs: Array[Integer]
12
12
  xs = TSort.tsort(each_node, each_child)
@@ -1,63 +1 @@
1
- ---
2
- - file: a.rb
3
- diagnostics:
4
- - range:
5
- start:
6
- line: 7
7
- character: 0
8
- end:
9
- line: 7
10
- character: 38
11
- severity: ERROR
12
- message: |-
13
- Cannot assign a value of type `^() -> ::Hash[::Integer, ::Array[::Integer]]` to a variable of type `^() { (::Integer) -> void } -> void`
14
- ^() -> ::Hash[::Integer, ::Array[::Integer]] <: ^() { (::Integer) -> void } -> void
15
- code: Ruby::IncompatibleAssignment
16
- - range:
17
- start:
18
- line: 7
19
- character: 34
20
- end:
21
- line: 7
22
- character: 35
23
- severity: ERROR
24
- message: Cannot detect the type of the expression
25
- code: Ruby::FallbackAny
26
- - range:
27
- start:
28
- line: 9
29
- character: 0
30
- end:
31
- line: 9
32
- character: 41
33
- severity: ERROR
34
- message: |-
35
- Cannot assign a value of type `^(::Integer) -> ::Enumerator[::Integer, ::Array[::Integer]]` to a variable of type `^(::Integer) { (::Integer) -> void } -> void`
36
- ^(::Integer) -> ::Enumerator[::Integer, ::Array[::Integer]] <: ^(::Integer) { (::Integer) -> void } -> void
37
- code: Ruby::IncompatibleAssignment
38
- - range:
39
- start:
40
- line: 9
41
- character: 37
42
- end:
43
- line: 9
44
- character: 38
45
- severity: ERROR
46
- message: Cannot detect the type of the expression
47
- code: Ruby::FallbackAny
48
- - range:
49
- start:
50
- line: 12
51
- character: 0
52
- end:
53
- line: 12
54
- character: 39
55
- severity: ERROR
56
- message: |-
57
- Cannot assign a value of type `::Array[::Integer]` to a variable of type `::Array[::String]`
58
- ::Array[::Integer] <: ::Array[::String]
59
- ::Integer <: ::String
60
- ::Numeric <: ::String
61
- ::Object <: ::String
62
- ::BasicObject <: ::String
63
- code: Ruby::IncompatibleAssignment
1
+ --- []
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: steep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.48.0
4
+ version: 0.50.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-07 00:00:00.000000000 Z
11
+ date: 2022-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -356,6 +356,7 @@ files:
356
356
  - smoke/diagnostics/method_return_type_annotation_mismatch.rb
357
357
  - smoke/diagnostics/missing_keyword.rb
358
358
  - smoke/diagnostics/no_method.rb
359
+ - smoke/diagnostics/proc_type_expected.rb
359
360
  - smoke/diagnostics/required_block_missing.rb
360
361
  - smoke/diagnostics/return_type_mismatch.rb
361
362
  - smoke/diagnostics/test_expectations.yml