steep 1.2.1 → 1.3.0.pre.2

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 (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(