steep 1.2.1 → 1.3.0.pre.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/Gemfile.lock +4 -4
  4. data/Gemfile.steep +1 -1
  5. data/Gemfile.steep.lock +13 -3
  6. data/Steepfile +0 -1
  7. data/bin/steep-prof +1 -1
  8. data/lib/steep/annotation_parser.rb +34 -28
  9. data/lib/steep/ast/annotation.rb +16 -5
  10. data/lib/steep/ast/node/type_application.rb +74 -0
  11. data/lib/steep/ast/node/type_assertion.rb +56 -0
  12. data/lib/steep/ast/types/factory.rb +5 -1
  13. data/lib/steep/ast/types/helper.rb +4 -3
  14. data/lib/steep/ast/types/logic.rb +4 -0
  15. data/lib/steep/diagnostic/helper.rb +2 -1
  16. data/lib/steep/diagnostic/lsp_formatter.rb +3 -1
  17. data/lib/steep/diagnostic/ruby.rb +70 -5
  18. data/lib/steep/diagnostic/signature.rb +21 -8
  19. data/lib/steep/drivers/check.rb +2 -2
  20. data/lib/steep/drivers/checkfile.rb +2 -2
  21. data/lib/steep/drivers/langserver.rb +2 -2
  22. data/lib/steep/drivers/stats.rb +2 -2
  23. data/lib/steep/drivers/utils/jobs_option.rb +0 -4
  24. data/lib/steep/drivers/watch.rb +1 -1
  25. data/lib/steep/drivers/worker.rb +0 -1
  26. data/lib/steep/server/lsp_formatter.rb +13 -3
  27. data/lib/steep/server/master.rb +4 -1
  28. data/lib/steep/server/worker_process.rb +91 -14
  29. data/lib/steep/services/completion_provider.rb +2 -1
  30. data/lib/steep/services/goto_service.rb +2 -1
  31. data/lib/steep/services/hover_provider/rbs.rb +7 -7
  32. data/lib/steep/services/hover_provider/ruby.rb +21 -5
  33. data/lib/steep/services/signature_service.rb +23 -4
  34. data/lib/steep/services/type_check_service.rb +4 -4
  35. data/lib/steep/signature/validator.rb +36 -13
  36. data/lib/steep/source.rb +189 -71
  37. data/lib/steep/type_construction.rb +246 -135
  38. data/lib/steep/type_inference/logic_type_interpreter.rb +3 -1
  39. data/lib/steep/version.rb +1 -1
  40. data/lib/steep.rb +2 -0
  41. data/rbs_collection.steep.lock.yaml +27 -10
  42. data/rbs_collection.steep.yaml +0 -1
  43. data/sig/shims/exception.rbs +4 -0
  44. data/sig/shims/parser/comment.rbs +33 -0
  45. data/sig/shims/parser.rbs +30 -2
  46. data/sig/steep/annotation_parser.rbs +59 -0
  47. data/sig/steep/ast/annotation.rbs +21 -26
  48. data/sig/steep/ast/node/type_application.rbs +31 -0
  49. data/sig/steep/ast/node/type_assertion.rbs +26 -0
  50. data/sig/steep/ast/types/any.rbs +1 -1
  51. data/sig/steep/ast/types/boolean.rbs +1 -1
  52. data/sig/steep/ast/types/bot.rbs +1 -1
  53. data/sig/steep/ast/types/class.rbs +1 -1
  54. data/sig/steep/ast/types/factory.rbs +0 -2
  55. data/sig/steep/ast/types/helper.rbs +6 -3
  56. data/sig/steep/ast/types/instance.rbs +1 -1
  57. data/sig/steep/ast/types/intersection.rbs +1 -1
  58. data/sig/steep/ast/types/logic.rbs +2 -0
  59. data/sig/steep/ast/types/name.rbs +2 -2
  60. data/sig/steep/ast/types/nil.rbs +1 -1
  61. data/sig/steep/ast/types/record.rbs +1 -1
  62. data/sig/steep/ast/types/self.rbs +1 -1
  63. data/sig/steep/ast/types/top.rbs +2 -2
  64. data/sig/steep/ast/types/tuple.rbs +1 -1
  65. data/sig/steep/ast/types/union.rbs +1 -1
  66. data/sig/steep/ast/types/var.rbs +2 -2
  67. data/sig/steep/ast/types/void.rbs +1 -1
  68. data/sig/steep/diagnostic/helper.rbs +9 -3
  69. data/sig/steep/diagnostic/lsp_formatter.rbs +12 -8
  70. data/sig/steep/diagnostic/ruby.rbs +62 -8
  71. data/sig/steep/diagnostic/signature.rbs +118 -85
  72. data/sig/steep/drivers/utils/jobs_option.rbs +0 -2
  73. data/sig/steep/drivers/worker.rbs +11 -13
  74. data/sig/steep/range_extension.rbs +7 -0
  75. data/sig/steep/server/lsp_formatter.rbs +14 -7
  76. data/sig/steep/server/worker_process.rbs +74 -12
  77. data/sig/steep/services/hover_provider/rbs.rbs +27 -7
  78. data/sig/steep/services/hover_provider/ruby.rbs +18 -4
  79. data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
  80. data/sig/steep/services/signature_service.rbs +14 -0
  81. data/sig/steep/services/type_check_service.rbs +2 -2
  82. data/sig/steep/signature/validator.rbs +76 -0
  83. data/sig/steep/source.rbs +54 -30
  84. data/sig/steep/type_construction.rbs +85 -27
  85. data/sig/steep/type_inference/method_call.rbs +1 -1
  86. data/sig/steep.rbs +2 -0
  87. data/smoke/diagnostics-rbs/inherit-module.rbs +2 -0
  88. data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
  89. data/steep.gemspec +1 -1
  90. metadata +16 -6
@@ -11,9 +11,7 @@ module Steep
11
11
  end
12
12
 
13
13
  def header_line
14
- StringIO.new.tap do |io|
15
- puts io
16
- end.string
14
+ raise
17
15
  end
18
16
 
19
17
  def detail_lines
@@ -25,7 +23,9 @@ module Steep
25
23
  end
26
24
 
27
25
  def path
28
- location.buffer.name
26
+ if location
27
+ Pathname(location.buffer.name)
28
+ end
29
29
  end
30
30
  end
31
31
 
@@ -166,7 +166,6 @@ module Steep
166
166
  class RecursiveAlias < Base
167
167
  attr_reader :class_name
168
168
  attr_reader :names
169
- attr_reader :location
170
169
 
171
170
  def initialize(class_name:, names:, location:)
172
171
  super(location: location)
@@ -284,7 +283,6 @@ module Steep
284
283
 
285
284
  class InstanceVariableTypeError < Base
286
285
  attr_reader :name
287
- attr_reader :variable
288
286
  attr_reader :var_type
289
287
  attr_reader :parent_type
290
288
 
@@ -318,7 +316,7 @@ module Steep
318
316
  private
319
317
 
320
318
  def mixin_name
321
- case member
319
+ case mem = member
322
320
  when RBS::AST::Members::Prepend
323
321
  "prepend"
324
322
  when RBS::AST::Members::Include
@@ -329,6 +327,19 @@ module Steep
329
327
  end
330
328
  end
331
329
 
330
+ class InheritModuleError < Base
331
+ attr_reader :super_class
332
+
333
+ def initialize(super_class)
334
+ super(location: super_class.location)
335
+ @super_class = super_class
336
+ end
337
+
338
+ def header_line
339
+ "Cannot inherit from a module `#{super_class.name}`"
340
+ end
341
+ end
342
+
332
343
  class UnexpectedError < Base
333
344
  attr_reader :message
334
345
 
@@ -427,7 +438,7 @@ module Steep
427
438
  Diagnostic::Signature::RecursiveAlias.new(
428
439
  class_name: error.type.name,
429
440
  names: error.defs.map(&:name),
430
- location: error.defs[0].original.location
441
+ location: error.defs[0].original&.location
431
442
  )
432
443
  when RBS::RecursiveAncestorError
433
444
  Diagnostic::Signature::RecursiveAncestor.new(
@@ -462,6 +473,8 @@ module Steep
462
473
  nonregular_type: factory.type(error.diagnostic.nonregular_type),
463
474
  location: error.location
464
475
  )
476
+ when RBS::InheritModuleError
477
+ Diagnostic::Signature::InheritModuleError.new(error.super_decl)
465
478
  else
466
479
  raise error
467
480
  end
@@ -36,11 +36,11 @@ module Steep
36
36
  server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
37
37
  server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
38
38
 
39
- typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(
39
+ typecheck_workers = Server::WorkerProcess.start_typecheck_workers(
40
40
  steepfile: project.steepfile_path,
41
41
  args: command_line_patterns,
42
42
  delay_shutdown: true,
43
- steep_command: jobs_option.steep_command_value,
43
+ steep_command: jobs_option.steep_command,
44
44
  count: jobs_option.jobs_count_value
45
45
  )
46
46
 
@@ -101,11 +101,11 @@ module Steep
101
101
 
102
102
  Steep.logger.info { "Starting #{count} workers for #{files.size} files..." }
103
103
 
104
- typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(
104
+ typecheck_workers = Server::WorkerProcess.start_typecheck_workers(
105
105
  steepfile: project.steepfile_path,
106
106
  args: [],
107
107
  delay_shutdown: true,
108
- steep_command: jobs_option.steep_command_value,
108
+ steep_command: jobs_option.steep_command,
109
109
  count: count
110
110
  )
111
111
 
@@ -35,8 +35,8 @@ module Steep
35
35
  def run
36
36
  @project = load_config()
37
37
 
38
- interaction_worker = Server::WorkerProcess.spawn_worker(:interaction, name: "interaction", steepfile: project.steepfile_path, steep_command: jobs_option.steep_command_value)
39
- typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: [], steep_command: jobs_option.steep_command_value, count: jobs_option.jobs_count_value)
38
+ interaction_worker = Server::WorkerProcess.start_worker(:interaction, name: "interaction", steepfile: project.steepfile_path, steep_command: jobs_option.steep_command)
39
+ typecheck_workers = Server::WorkerProcess.start_typecheck_workers(steepfile: project.steepfile_path, args: [], steep_command: jobs_option.steep_command, count: jobs_option.jobs_count_value)
40
40
 
41
41
  master = Server::Master.new(
42
42
  project: project,
@@ -126,11 +126,11 @@ module Steep
126
126
  server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
127
127
  server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
128
128
 
129
- typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(
129
+ typecheck_workers = Server::WorkerProcess.start_typecheck_workers(
130
130
  steepfile: project.steepfile_path,
131
131
  delay_shutdown: true,
132
132
  args: command_line_patterns,
133
- steep_command: jobs_option.steep_command_value,
133
+ steep_command: jobs_option.steep_command,
134
134
  count: jobs_option.jobs_count_value
135
135
  )
136
136
 
@@ -17,10 +17,6 @@ module Steep
17
17
  def jobs_count_value
18
18
  jobs_count || default_jobs_count
19
19
  end
20
-
21
- def steep_command_value
22
- steep_command || "steep"
23
- end
24
20
  end
25
21
  end
26
22
  end
@@ -42,7 +42,7 @@ module Steep
42
42
  server_reader = LanguageServer::Protocol::Transport::Io::Reader.new(server_read)
43
43
  server_writer = LanguageServer::Protocol::Transport::Io::Writer.new(server_write)
44
44
 
45
- typecheck_workers = Server::WorkerProcess.spawn_typecheck_workers(steepfile: project.steepfile_path, args: dirs.map(&:to_s), steep_command: jobs_option.steep_command_value, count: jobs_option.jobs_count_value)
45
+ typecheck_workers = Server::WorkerProcess.start_typecheck_workers(steepfile: project.steepfile_path, args: dirs.map(&:to_s), steep_command: jobs_option.steep_command, count: jobs_option.jobs_count_value)
46
46
 
47
47
  master = Server::Master.new(
48
48
  project: project,
@@ -3,7 +3,6 @@ module Steep
3
3
  class Worker
4
4
  attr_reader :stdout, :stderr, :stdin
5
5
 
6
- attr_accessor :steepfile_path
7
6
  attr_accessor :worker_type
8
7
  attr_accessor :worker_name
9
8
  attr_accessor :delay_shutdown
@@ -17,6 +17,8 @@ module Steep
17
17
  def to_s
18
18
  unless @array.empty?
19
19
  @array.join("\n\n----\n\n")
20
+ else
21
+ ""
20
22
  end
21
23
  end
22
24
 
@@ -83,7 +85,7 @@ module Steep
83
85
  #{decl.method_type}
84
86
  ```
85
87
 
86
- #{decl.method_def.comment.string.gsub(/\A([ \t]*\n)+/, "")}
88
+ #{comment.string.gsub(/\A([ \t]*\n)+/, "")}
87
89
  EOM
88
90
  end
89
91
  end
@@ -108,10 +110,10 @@ EOM
108
110
  end
109
111
  when HoverProvider::Ruby::ConstantContent
110
112
  CommentBuilder.build do |builder|
111
- if content.class_or_module?
113
+ if decl = content.class_or_module?
112
114
  builder << <<EOM
113
115
  ```rbs
114
- #{declaration_summary(content.decl.primary.decl)}
116
+ #{declaration_summary(decl.primary.decl)}
115
117
  ```
116
118
  EOM
117
119
  end
@@ -141,6 +143,14 @@ EOM
141
143
  builder << comment.string
142
144
  end
143
145
  end
146
+ when HoverProvider::Ruby::TypeAssertionContent
147
+ CommentBuilder.build do |builder|
148
+ builder << <<-EOM
149
+ `#{content.asserted_type.to_s}`
150
+
151
+ ↑ Converted from `#{content.original_type.to_s}`
152
+ EOM
153
+ end
144
154
  when HoverProvider::RBS::ClassContent
145
155
  CommentBuilder.build do |builder|
146
156
  builder << <<EOM
@@ -796,7 +796,10 @@ module Steep
796
796
 
797
797
  Steep.logger.info "Sending $/typecheck/start notifications"
798
798
  typecheck_workers.each do |worker|
799
- assignment = Services::PathAssignment.new(max_index: typecheck_workers.size, index: worker.index)
799
+ assignment = Services::PathAssignment.new(
800
+ max_index: typecheck_workers.size,
801
+ index: worker.index || raise
802
+ )
800
803
 
801
804
  job_queue << SendMessageJob.to_worker(
802
805
  worker,
@@ -18,48 +18,125 @@ module Steep
18
18
  @index = index
19
19
  end
20
20
 
21
- def self.spawn_worker(type, name:, steepfile:, steep_command: "steep", options: [], delay_shutdown: false, index: nil)
21
+ def self.start_worker(type, name:, steepfile:, steep_command:, index: nil, delay_shutdown: false, patterns: [])
22
+ begin
23
+ unless steep_command
24
+ fork_worker(
25
+ type,
26
+ name: name,
27
+ steepfile: steepfile,
28
+ index: index,
29
+ delay_shutdown: delay_shutdown,
30
+ patterns: patterns
31
+ )
32
+ else
33
+ # Use `#spawn_worker`
34
+ raise NotImplementedError
35
+ end
36
+ rescue NotImplementedError
37
+ spawn_worker(
38
+ type,
39
+ name: name,
40
+ steepfile: steepfile,
41
+ steep_command: steep_command || "steep",
42
+ index: index,
43
+ delay_shutdown: delay_shutdown,
44
+ patterns: patterns
45
+ )
46
+ end
47
+ end
48
+
49
+ def self.fork_worker(type, name:, steepfile:, index:, delay_shutdown:, patterns:)
50
+ stdin_in, stdin_out = IO.pipe
51
+ stdout_in, stdout_out = IO.pipe
52
+
53
+ worker = Drivers::Worker.new(stdout: stdout_out, stdin: stdin_in, stderr: STDERR)
54
+
55
+ worker.steepfile = steepfile
56
+ worker.worker_type = type
57
+ worker.worker_name = name
58
+ worker.delay_shutdown = delay_shutdown
59
+ if (max, this = index)
60
+ worker.max_index = max
61
+ worker.index = this
62
+ end
63
+ worker.commandline_args = patterns
64
+
65
+ pid = fork do
66
+ worker.run()
67
+ end
68
+
69
+ pid or raise
70
+
71
+ writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin_out)
72
+ reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdout_in)
73
+
74
+ # @type var wait_thread: Thread & _ProcessWaitThread
75
+ wait_thread = _ = Thread.new { Process.waitpid(pid) }
76
+ wait_thread.define_singleton_method(:pid) { pid }
77
+
78
+ stdin_in.close
79
+ stdout_out.close
80
+
81
+ new(
82
+ reader: reader,
83
+ writer: writer,
84
+ stderr: STDERR,
85
+ wait_thread: wait_thread,
86
+ name: name,
87
+ index: index&.[](1)
88
+ )
89
+ end
90
+
91
+ def self.spawn_worker(type, name:, steepfile:, steep_command:, index:, delay_shutdown:, patterns:)
22
92
  args = ["--name=#{name}", "--steepfile=#{steepfile}"]
23
93
  args << (%w(debug info warn error fatal unknown)[Steep.logger.level].yield_self {|log_level| "--log-level=#{log_level}" })
94
+
24
95
  if Steep.log_output.is_a?(String)
25
96
  args << "--log-output=#{Steep.log_output}"
26
97
  end
98
+
99
+ if (max, this = index)
100
+ args << "--max-index=#{max}"
101
+ args << "--index=#{this}"
102
+ end
103
+
104
+ if delay_shutdown
105
+ args << "--delay-shutdown"
106
+ end
107
+
27
108
  command = case type
28
109
  when :interaction
29
- [steep_command, "worker", "--interaction", *args, *options]
110
+ [steep_command, "worker", "--interaction", *args, *patterns]
30
111
  when :typecheck
31
- [steep_command, "worker", "--typecheck", *args, *options]
112
+ [steep_command, "worker", "--typecheck", *args, *patterns]
32
113
  else
33
114
  raise "Unknown type: #{type}"
34
115
  end
35
116
 
36
- if delay_shutdown
37
- command << "--delay-shutdown"
38
- end
39
-
40
117
  stdin, stdout, thread = if Gem.win_platform?
41
- Open3.popen2(*command, new_pgroup: true)
118
+ __skip__ = Open3.popen2(*command, new_pgroup: true)
42
119
  else
43
- Open3.popen2(*command, pgroup: true)
120
+ __skip__ = Open3.popen2(*command, pgroup: true)
44
121
  end
45
122
  stderr = nil
46
123
 
47
124
  writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin)
48
125
  reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdout)
49
126
 
50
- new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index)
127
+ new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index&.[](1))
51
128
  end
52
129
 
53
- def self.spawn_typecheck_workers(steepfile:, args:, steep_command: "steep", count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
130
+ def self.start_typecheck_workers(steepfile:, args:, steep_command:, count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
54
131
  count.times.map do |i|
55
- spawn_worker(
132
+ start_worker(
56
133
  :typecheck,
57
134
  name: "typecheck@#{i}",
58
135
  steepfile: steepfile,
59
136
  steep_command: steep_command,
60
- options: ["--max-index=#{count}", "--index=#{i}", *args],
137
+ index: [count, i],
138
+ patterns: args,
61
139
  delay_shutdown: delay_shutdown,
62
- index: i
63
140
  )
64
141
  end
65
142
  end
@@ -88,7 +88,8 @@ module Steep
88
88
  end
89
89
 
90
90
  Steep.measure "typechecking" do
91
- @typing = TypeCheckService.type_check(source: source, subtyping: subtyping)
91
+ resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
92
+ @typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
92
93
  end
93
94
  end
94
95
 
@@ -211,8 +211,9 @@ module Steep
211
211
  subtyping = signature_service.current_subtyping or return
212
212
  source = Source.parse(content, path: path, factory: subtyping.factory)
213
213
  source = source.without_unrelated_defs(line: line, column: column)
214
+ resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
214
215
  [
215
- Services::TypeCheckService.type_check(source: source, subtyping: subtyping),
216
+ Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver),
216
217
  signature_service
217
218
  ]
218
219
  rescue
@@ -2,9 +2,9 @@ module Steep
2
2
  module Services
3
3
  module HoverProvider
4
4
  class RBS
5
- TypeAliasContent = Struct.new(:location, :decl, keyword_init: true)
6
- ClassContent = Struct.new(:location, :decl, keyword_init: true)
7
- InterfaceContent = Struct.new(:location, :decl, keyword_init: true)
5
+ TypeAliasContent = _ = Struct.new(:location, :decl, keyword_init: true)
6
+ ClassContent = _ = Struct.new(:location, :decl, keyword_init: true)
7
+ InterfaceContent = _ = Struct.new(:location, :decl, keyword_init: true)
8
8
 
9
9
  attr_reader :service
10
10
 
@@ -33,14 +33,14 @@ module Steep
33
33
  alias_decl = service.latest_env.alias_decls[head.name]&.decl or raise
34
34
 
35
35
  TypeAliasContent.new(
36
- location: head.location,
36
+ location: head.location || raise,
37
37
  decl: alias_decl
38
38
  )
39
39
  when ::RBS::Types::ClassInstance, ::RBS::Types::ClassSingleton
40
40
  if loc_key == :name
41
41
  env = service.latest_env
42
- class_decl = env.class_decls[head.name]&.decls[0]&.decl or raise
43
- location = head.location[:name]
42
+ class_decl = env.class_decls[head.name]&.decls&.[](0)&.decl or raise
43
+ location = head.location&.[](:name) or raise
44
44
  ClassContent.new(
45
45
  location: location,
46
46
  decl: class_decl
@@ -49,7 +49,7 @@ module Steep
49
49
  when ::RBS::Types::Interface
50
50
  env = service.latest_env
51
51
  interface_decl = env.interface_decls[head.name]&.decl or raise
52
- location = head.location[:name]
52
+ location = head.location&.[](:name) or raise
53
53
 
54
54
  InterfaceContent.new(
55
55
  location: location,
@@ -4,6 +4,7 @@ module Steep
4
4
  class Ruby
5
5
  TypeContent = _ = Struct.new(:node, :type, :location, keyword_init: true)
6
6
  VariableContent = _ = Struct.new(:node, :name, :type, :location, keyword_init: true)
7
+ TypeAssertionContent = _ = Struct.new(:node, :original_type, :asserted_type, :location, keyword_init: true)
7
8
  MethodCallContent = _ = Struct.new(:node, :method_call, :location, keyword_init: true)
8
9
  DefinitionContent = _ = Struct.new(:node, :method_name, :method_type, :definition, :location, keyword_init: true)
9
10
  ConstantContent = _ = Struct.new(:location, :full_name, :type, :decl, keyword_init: true) do
@@ -33,11 +34,15 @@ module Steep
33
34
  end
34
35
 
35
36
  def constant?
36
- decl.is_a?(::RBS::Environment::SingleEntry)
37
+ if decl.is_a?(::RBS::Environment::SingleEntry)
38
+ decl
39
+ end
37
40
  end
38
41
 
39
42
  def class_or_module?
40
- decl.is_a?(::RBS::Environment::MultiEntry)
43
+ if decl.is_a?(::RBS::Environment::MultiEntry)
44
+ decl
45
+ end
41
46
  end
42
47
  end
43
48
 
@@ -72,14 +77,16 @@ module Steep
72
77
  subtyping = service.signature_services[target.name].current_subtyping or return
73
78
  source = Source.parse(content, path: path, factory: subtyping.factory)
74
79
  source = source.without_unrelated_defs(line: line, column: column)
75
- Services::TypeCheckService.type_check(source: source, subtyping: subtyping)
80
+ resolver = ::RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
81
+ Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
76
82
  rescue
77
83
  nil
78
84
  end
79
85
 
80
86
  def method_name_from_method(context, builder:)
81
- defined_in = context.method.defined_in
82
- method_name = context.name
87
+ context.method or raise
88
+ defined_in = context.method.defined_in or raise
89
+ method_name = context.name or raise
83
90
 
84
91
  case
85
92
  when defined_in.class?
@@ -171,6 +178,15 @@ module Steep
171
178
  decl: decl
172
179
  )
173
180
  end
181
+ when :assertion
182
+ original_node, _ = node.children
183
+
184
+ original_type = typing.type_of(node: original_node)
185
+ asserted_type = typing.type_of(node: node)
186
+
187
+ if original_type != asserted_type
188
+ return TypeAssertionContent.new(node: node, original_type: original_type, asserted_type: asserted_type, location: node.location.expression)
189
+ end
174
190
  end
175
191
 
176
192
  TypeContent.new(
@@ -19,6 +19,10 @@ module Steep
19
19
  builder.env(last_builder.env)
20
20
  end
21
21
  end
22
+
23
+ def constant_resolver
24
+ @constant_resolver ||= RBS::Resolver::ConstantResolver.new(builder: last_builder)
25
+ end
22
26
  end
23
27
 
24
28
  class AncestorErrorStatus
@@ -37,6 +41,10 @@ module Steep
37
41
  builder.env(last_builder.env)
38
42
  end
39
43
  end
44
+
45
+ def constant_resolver
46
+ @constant_resolver ||= RBS::Resolver::ConstantResolver.new(builder: last_builder)
47
+ end
40
48
  end
41
49
 
42
50
  class LoadedStatus
@@ -61,6 +69,10 @@ module Steep
61
69
  builder.env(self.builder.env)
62
70
  end
63
71
  end
72
+
73
+ def constant_resolver
74
+ @constant_resolver ||= RBS::Resolver::ConstantResolver.new(builder: builder)
75
+ end
64
76
  end
65
77
 
66
78
  FileStatus = _ = Struct.new(:path, :content, :decls, keyword_init: true)
@@ -125,6 +137,10 @@ module Steep
125
137
  status.rbs_index
126
138
  end
127
139
 
140
+ def latest_constant_resolver
141
+ status.constant_resolver
142
+ end
143
+
128
144
  def current_subtyping
129
145
  if status.is_a?(LoadedStatus)
130
146
  status.subtyping
@@ -174,7 +190,7 @@ module Steep
174
190
  file.decls
175
191
  else
176
192
  # factory is not used here because the error is a syntax error.
177
- Diagnostic::Signature.from_rbs_error(file.decls, factory: nil)
193
+ Diagnostic::Signature.from_rbs_error(file.decls, factory: _ = nil)
178
194
  end
179
195
  diagnostics << diagnostic
180
196
  end
@@ -214,6 +230,7 @@ module Steep
214
230
 
215
231
  def update_env(updated_files, paths:)
216
232
  Steep.logger.tagged "#update_env" do
233
+ # @type var errors: Array[RBS::BaseError]
217
234
  errors = []
218
235
  new_decls = Set[].compare_by_identity
219
236
 
@@ -230,7 +247,9 @@ module Steep
230
247
  updated_files.each_value do |content|
231
248
  case decls = content.decls
232
249
  when RBS::BaseError
233
- errors << content.decls
250
+ errors << decls
251
+ when Diagnostic::Signature::UnexpectedError
252
+ return [decls]
234
253
  else
235
254
  begin
236
255
  decls.each do |decl|
@@ -255,7 +274,7 @@ module Steep
255
274
  unless errors.empty?
256
275
  return errors.map {|error|
257
276
  # Factory will not be used because of the possible error types.
258
- Diagnostic::Signature.from_rbs_error(error, factory: nil)
277
+ Diagnostic::Signature.from_rbs_error(error, factory: _ = nil)
259
278
  }
260
279
  end
261
280
 
@@ -277,7 +296,7 @@ module Steep
277
296
 
278
297
  unless errors.empty?
279
298
  # Builder won't be used.
280
- factory = AST::Types::Factory.new(builder: nil)
299
+ factory = AST::Types::Factory.new(builder: _ = nil)
281
300
  return errors.map {|error| Diagnostic::Signature.from_rbs_error(error, factory: factory) }
282
301
  end
283
302
 
@@ -280,7 +280,7 @@ module Steep
280
280
 
281
281
  if subtyping
282
282
  text = source_files[path].content
283
- file = type_check_file(target: target, subtyping: subtyping, path: path, text: text)
283
+ file = type_check_file(target: target, subtyping: subtyping, path: path, text: text) { signature_service.latest_constant_resolver }
284
284
  yield [file.path, file.diagnostics]
285
285
  source_files[path] = file
286
286
  end
@@ -326,7 +326,7 @@ module Steep
326
326
  def type_check_file(target:, subtyping:, path:, text:)
327
327
  Steep.logger.tagged "#type_check_file(#{path}@#{target.name})" do
328
328
  source = Source.parse(text, path: path, factory: subtyping.factory)
329
- typing = TypeCheckService.type_check(source: source, subtyping: subtyping)
329
+ typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: yield)
330
330
  SourceFile.with_typing(path: path, content: text, node: source.node, typing: typing)
331
331
  end
332
332
  rescue AnnotationParser::SyntaxError => exn
@@ -342,7 +342,7 @@ module Steep
342
342
  SourceFile.no_data(path: path, content: text)
343
343
  end
344
344
 
345
- def self.type_check(source:, subtyping:)
345
+ def self.type_check(source:, subtyping:, constant_resolver:)
346
346
  annotations = source.annotations(block: source.node, factory: subtyping.factory, context: nil)
347
347
 
348
348
  definition = subtyping.factory.definition_builder.build_instance(AST::Builtin::Object.module_name)
@@ -350,7 +350,7 @@ module Steep
350
350
  const_env = TypeInference::ConstantEnv.new(
351
351
  factory: subtyping.factory,
352
352
  context: nil,
353
- resolver: RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
353
+ resolver: constant_resolver
354
354
  )
355
355
  type_env = TypeInference::TypeEnv.new(const_env)
356
356
  type_env = TypeInference::TypeEnvBuilder.new(