steep 0.48.0 → 0.50.0

Sign up to get free protection for your applications and to get access to all the features.
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