steep 1.2.1 → 1.3.0.pre.1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -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/lib/steep/annotation_parser.rb +34 -28
  8. data/lib/steep/ast/annotation.rb +16 -5
  9. data/lib/steep/ast/node/type_application.rb +74 -0
  10. data/lib/steep/ast/node/type_assertion.rb +56 -0
  11. data/lib/steep/ast/types/factory.rb +5 -1
  12. data/lib/steep/diagnostic/helper.rb +2 -1
  13. data/lib/steep/diagnostic/lsp_formatter.rb +3 -1
  14. data/lib/steep/diagnostic/ruby.rb +70 -5
  15. data/lib/steep/diagnostic/signature.rb +21 -8
  16. data/lib/steep/drivers/check.rb +1 -1
  17. data/lib/steep/drivers/checkfile.rb +1 -1
  18. data/lib/steep/drivers/langserver.rb +2 -2
  19. data/lib/steep/drivers/stats.rb +1 -1
  20. data/lib/steep/drivers/watch.rb +1 -1
  21. data/lib/steep/drivers/worker.rb +0 -1
  22. data/lib/steep/server/lsp_formatter.rb +13 -3
  23. data/lib/steep/server/master.rb +4 -1
  24. data/lib/steep/server/worker_process.rb +86 -14
  25. data/lib/steep/services/hover_provider/rbs.rb +7 -7
  26. data/lib/steep/services/hover_provider/ruby.rb +19 -4
  27. data/lib/steep/services/signature_service.rb +7 -4
  28. data/lib/steep/signature/validator.rb +36 -13
  29. data/lib/steep/source.rb +189 -71
  30. data/lib/steep/type_construction.rb +232 -126
  31. data/lib/steep/type_inference/logic_type_interpreter.rb +3 -1
  32. data/lib/steep/version.rb +1 -1
  33. data/lib/steep.rb +2 -0
  34. data/rbs_collection.steep.lock.yaml +27 -10
  35. data/rbs_collection.steep.yaml +0 -1
  36. data/sig/shims/exception.rbs +4 -0
  37. data/sig/shims/parser/comment.rbs +33 -0
  38. data/sig/shims/parser.rbs +30 -2
  39. data/sig/steep/annotation_parser.rbs +59 -0
  40. data/sig/steep/ast/annotation.rbs +21 -26
  41. data/sig/steep/ast/node/type_application.rbs +31 -0
  42. data/sig/steep/ast/node/type_assertion.rbs +26 -0
  43. data/sig/steep/ast/types/factory.rbs +0 -2
  44. data/sig/steep/diagnostic/helper.rbs +9 -3
  45. data/sig/steep/diagnostic/lsp_formatter.rbs +12 -8
  46. data/sig/steep/diagnostic/ruby.rbs +62 -8
  47. data/sig/steep/diagnostic/signature.rbs +118 -85
  48. data/sig/steep/drivers/worker.rbs +11 -13
  49. data/sig/steep/range_extension.rbs +7 -0
  50. data/sig/steep/server/lsp_formatter.rbs +14 -7
  51. data/sig/steep/server/worker_process.rbs +74 -12
  52. data/sig/steep/services/hover_provider/rbs.rbs +27 -7
  53. data/sig/steep/services/hover_provider/ruby.rbs +18 -4
  54. data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
  55. data/sig/steep/signature/validator.rbs +76 -0
  56. data/sig/steep/source.rbs +54 -30
  57. data/sig/steep/type_construction.rbs +85 -27
  58. data/sig/steep/type_inference/method_call.rbs +1 -1
  59. data/smoke/diagnostics-rbs/inherit-module.rbs +2 -0
  60. data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
  61. data/steep.gemspec +1 -1
  62. 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,7 +36,7 @@ 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,
@@ -101,7 +101,7 @@ 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,
@@ -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_value)
39
+ typecheck_workers = Server::WorkerProcess.start_typecheck_workers(steepfile: project.steepfile_path, args: [], steep_command: jobs_option.steep_command_value, count: jobs_option.jobs_count_value)
40
40
 
41
41
  master = Server::Master.new(
42
42
  project: project,
@@ -126,7 +126,7 @@ 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,
@@ -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_value, 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,120 @@ 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: "steep", index: nil, delay_shutdown: false, patterns: [])
22
+ begin
23
+ fork_worker(
24
+ type,
25
+ name: name,
26
+ steepfile: steepfile,
27
+ index: index,
28
+ delay_shutdown: delay_shutdown,
29
+ patterns: patterns
30
+ )
31
+ rescue NotImplementedError
32
+ spawn_worker(
33
+ type,
34
+ name: name,
35
+ steepfile: steepfile,
36
+ steep_command: steep_command,
37
+ index: index,
38
+ delay_shutdown: delay_shutdown,
39
+ patterns: patterns
40
+ )
41
+ end
42
+ end
43
+
44
+ def self.fork_worker(type, name:, steepfile:, index:, delay_shutdown:, patterns:)
45
+ stdin_in, stdin_out = IO.pipe
46
+ stdout_in, stdout_out = IO.pipe
47
+
48
+ worker = Drivers::Worker.new(stdout: stdout_out, stdin: stdin_in, stderr: STDERR)
49
+
50
+ worker.steepfile = steepfile
51
+ worker.worker_type = type
52
+ worker.worker_name = name
53
+ worker.delay_shutdown = delay_shutdown
54
+ if (max, this = index)
55
+ worker.max_index = max
56
+ worker.index = this
57
+ end
58
+ worker.commandline_args = patterns
59
+
60
+ pid = fork do
61
+ worker.run()
62
+ end
63
+
64
+ pid or raise
65
+
66
+ writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin_out)
67
+ reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdout_in)
68
+
69
+ # @type var wait_thread: Thread & _ProcessWaitThread
70
+ wait_thread = _ = Thread.new { Process.waitpid(pid) }
71
+ wait_thread.define_singleton_method(:pid) { pid }
72
+
73
+ stdin_in.close
74
+ stdout_out.close
75
+
76
+ new(
77
+ reader: reader,
78
+ writer: writer,
79
+ stderr: STDERR,
80
+ wait_thread: wait_thread,
81
+ name: name,
82
+ index: index&.[](1)
83
+ )
84
+ end
85
+
86
+ def self.spawn_worker(type, name:, steepfile:, steep_command:, index:, delay_shutdown:, patterns:)
22
87
  args = ["--name=#{name}", "--steepfile=#{steepfile}"]
23
88
  args << (%w(debug info warn error fatal unknown)[Steep.logger.level].yield_self {|log_level| "--log-level=#{log_level}" })
89
+
24
90
  if Steep.log_output.is_a?(String)
25
91
  args << "--log-output=#{Steep.log_output}"
26
92
  end
93
+
94
+ if (max, this = index)
95
+ args << "--max-index=#{max}"
96
+ args << "--index=#{this}"
97
+ end
98
+
99
+ if delay_shutdown
100
+ args << "--delay-shutdown"
101
+ end
102
+
27
103
  command = case type
28
104
  when :interaction
29
- [steep_command, "worker", "--interaction", *args, *options]
105
+ [steep_command, "worker", "--interaction", *args, *patterns]
30
106
  when :typecheck
31
- [steep_command, "worker", "--typecheck", *args, *options]
107
+ [steep_command, "worker", "--typecheck", *args, *patterns]
32
108
  else
33
109
  raise "Unknown type: #{type}"
34
110
  end
35
111
 
36
- if delay_shutdown
37
- command << "--delay-shutdown"
38
- end
39
-
40
112
  stdin, stdout, thread = if Gem.win_platform?
41
- Open3.popen2(*command, new_pgroup: true)
113
+ __skip__ = Open3.popen2(*command, new_pgroup: true)
42
114
  else
43
- Open3.popen2(*command, pgroup: true)
115
+ __skip__ = Open3.popen2(*command, pgroup: true)
44
116
  end
45
117
  stderr = nil
46
118
 
47
119
  writer = LanguageServer::Protocol::Transport::Io::Writer.new(stdin)
48
120
  reader = LanguageServer::Protocol::Transport::Io::Reader.new(stdout)
49
121
 
50
- new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index)
122
+ new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index&.[](1))
51
123
  end
52
124
 
53
- def self.spawn_typecheck_workers(steepfile:, args:, steep_command: "steep", count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
125
+ def self.start_typecheck_workers(steepfile:, args:, steep_command: "steep", count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
54
126
  count.times.map do |i|
55
- spawn_worker(
127
+ start_worker(
56
128
  :typecheck,
57
129
  name: "typecheck@#{i}",
58
130
  steepfile: steepfile,
59
131
  steep_command: steep_command,
60
- options: ["--max-index=#{count}", "--index=#{i}", *args],
132
+ index: [count, i],
133
+ patterns: args,
61
134
  delay_shutdown: delay_shutdown,
62
- index: i
63
135
  )
64
136
  end
65
137
  end
@@ -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
 
@@ -78,8 +83,9 @@ module Steep
78
83
  end
79
84
 
80
85
  def method_name_from_method(context, builder:)
81
- defined_in = context.method.defined_in
82
- method_name = context.name
86
+ context.method or raise
87
+ defined_in = context.method.defined_in or raise
88
+ method_name = context.name or raise
83
89
 
84
90
  case
85
91
  when defined_in.class?
@@ -171,6 +177,15 @@ module Steep
171
177
  decl: decl
172
178
  )
173
179
  end
180
+ when :assertion
181
+ original_node, _ = node.children
182
+
183
+ original_type = typing.type_of(node: original_node)
184
+ asserted_type = typing.type_of(node: node)
185
+
186
+ if original_type != asserted_type
187
+ return TypeAssertionContent.new(node: node, original_type: original_type, asserted_type: asserted_type, location: node.location.expression)
188
+ end
174
189
  end
175
190
 
176
191
  TypeContent.new(
@@ -174,7 +174,7 @@ module Steep
174
174
  file.decls
175
175
  else
176
176
  # factory is not used here because the error is a syntax error.
177
- Diagnostic::Signature.from_rbs_error(file.decls, factory: nil)
177
+ Diagnostic::Signature.from_rbs_error(file.decls, factory: _ = nil)
178
178
  end
179
179
  diagnostics << diagnostic
180
180
  end
@@ -214,6 +214,7 @@ module Steep
214
214
 
215
215
  def update_env(updated_files, paths:)
216
216
  Steep.logger.tagged "#update_env" do
217
+ # @type var errors: Array[RBS::BaseError]
217
218
  errors = []
218
219
  new_decls = Set[].compare_by_identity
219
220
 
@@ -230,7 +231,9 @@ module Steep
230
231
  updated_files.each_value do |content|
231
232
  case decls = content.decls
232
233
  when RBS::BaseError
233
- errors << content.decls
234
+ errors << decls
235
+ when Diagnostic::Signature::UnexpectedError
236
+ return [decls]
234
237
  else
235
238
  begin
236
239
  decls.each do |decl|
@@ -255,7 +258,7 @@ module Steep
255
258
  unless errors.empty?
256
259
  return errors.map {|error|
257
260
  # Factory will not be used because of the possible error types.
258
- Diagnostic::Signature.from_rbs_error(error, factory: nil)
261
+ Diagnostic::Signature.from_rbs_error(error, factory: _ = nil)
259
262
  }
260
263
  end
261
264
 
@@ -277,7 +280,7 @@ module Steep
277
280
 
278
281
  unless errors.empty?
279
282
  # Builder won't be used.
280
- factory = AST::Types::Factory.new(builder: nil)
283
+ factory = AST::Types::Factory.new(builder: _ = nil)
281
284
  return errors.map {|error| Diagnostic::Signature.from_rbs_error(error, factory: factory) }
282
285
  end
283
286
 
@@ -20,7 +20,7 @@ module Steep
20
20
  end
21
21
 
22
22
  def each_error(&block)
23
- if block_given?
23
+ if block
24
24
  @errors.each(&block)
25
25
  else
26
26
  enum_for :each_error
@@ -64,6 +64,8 @@ module Steep
64
64
  )
65
65
 
66
66
  type_params.zip(type_args).each do |param, arg|
67
+ arg or raise
68
+
67
69
  if param.upper_bound
68
70
  upper_bound_type = factory.type(param.upper_bound).subst(subst)
69
71
  arg_type = factory.type(arg)
@@ -121,7 +123,7 @@ module Steep
121
123
 
122
124
  if name && type_params && type_args
123
125
  if !type_params.empty? && !type_args.empty?
124
- validate_type_application_constraints(type.name, type_params, type_args, location: type.location)
126
+ validate_type_application_constraints(name, type_params, type_args, location: type.location)
125
127
  end
126
128
  end
127
129
 
@@ -156,19 +158,21 @@ module Steep
156
158
  end
157
159
 
158
160
  def mixin_constraints(definition, mixin_ancestors, immediate_self_types:)
161
+ # @type var relations: Array[[Subtyping::Relation[AST::Types::t], RBS::Definition::Ancestor::Instance]]
159
162
  relations = []
160
163
 
161
164
  self_type = checker.factory.type(definition.self_type)
162
165
  if immediate_self_types && !immediate_self_types.empty?
163
- self_type = AST::Types::Intersection.build(
164
- types: immediate_self_types.map {|st| ancestor_to_type(st) }.push(self_type),
165
- location: nil
166
- )
166
+ # @type var sts: Array[AST::Types::t]
167
+ sts = immediate_self_types.map {|st| ancestor_to_type(st) }
168
+ self_type = AST::Types::Intersection.build(types: sts.push(self_type), location: nil)
167
169
  end
168
170
 
169
171
  mixin_ancestors.each do |ancestor|
170
172
  args = ancestor.args.map {|type| checker.factory.type(type) }
171
173
  ancestor_ancestors = builder.ancestor_builder.one_instance_ancestors(ancestor.name)
174
+ ancestor_ancestors.self_types or raise
175
+ ancestor_ancestors.params or raise
172
176
  self_constraints = ancestor_ancestors.self_types.map do |self_ancestor|
173
177
  s = Interface::Substitution.build(ancestor_ancestors.params, args)
174
178
  ancestor_to_type(self_ancestor).subst(s)
@@ -263,7 +267,7 @@ module Steep
263
267
  end
264
268
 
265
269
  ancestors = builder.ancestor_builder.one_instance_ancestors(name)
266
- mixin_constraints(definition, ancestors.included_modules, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
270
+ mixin_constraints(definition, ancestors.included_modules || raise, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
267
271
  checker.check(
268
272
  relation,
269
273
  self_type: AST::Types::Self.new,
@@ -271,6 +275,8 @@ module Steep
271
275
  class_type: AST::Types::Class.new,
272
276
  constraints: Subtyping::Constraints.empty
273
277
  ).else do
278
+ raise if ancestor.source.is_a?(Symbol)
279
+
274
280
  @errors << Diagnostic::Signature::ModuleSelfTypeError.new(
275
281
  name: name,
276
282
  location: ancestor.source&.location || raise,
@@ -292,6 +298,14 @@ module Steep
292
298
  end
293
299
 
294
300
  builder.build_singleton(name).tap do |definition|
301
+ entry =
302
+ case definition.entry
303
+ when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
304
+ definition.entry
305
+ else
306
+ raise
307
+ end
308
+
295
309
  definition.instance_variables.each do |name, var|
296
310
  if parent = var.parent_variable
297
311
  var_type = checker.factory.type(var.type)
@@ -327,7 +341,7 @@ module Steep
327
341
  definition.class_variables.each do |name, var|
328
342
  if var.declared_in == definition.type_name
329
343
  if (parent = var.parent_variable) && var.declared_in != parent.declared_in
330
- class_var = definition.entry.decls.flat_map {|decl| decl.decl.members }.find do |member|
344
+ class_var = entry.decls.flat_map {|decl| decl.decl.members }.find do |member|
331
345
  member.is_a?(RBS::AST::Members::ClassVariable) && member.name == name
332
346
  end
333
347
 
@@ -336,7 +350,7 @@ module Steep
336
350
  class_name: definition.type_name,
337
351
  other_class_name: parent.declared_in,
338
352
  variable_name: name,
339
- location: class_var.location[:name]
353
+ location: class_var.location&.[](:name)
340
354
  )
341
355
  end
342
356
  end
@@ -344,6 +358,7 @@ module Steep
344
358
  end
345
359
 
346
360
  ancestors = builder.ancestor_builder.one_singleton_ancestors(name)
361
+ ancestors.extended_modules or raise
347
362
  mixin_constraints(definition, ancestors.extended_modules, immediate_self_types: ancestors.self_types).each do |relation, ancestor|
348
363
  checker.check(
349
364
  relation,
@@ -352,6 +367,8 @@ module Steep
352
367
  class_type: AST::Types::Class.new,
353
368
  constraints: Subtyping::Constraints.empty
354
369
  ).else do
370
+ raise if ancestor.source.is_a?(Symbol)
371
+
355
372
  @errors << Diagnostic::Signature::ModuleSelfTypeError.new(
356
373
  name: name,
357
374
  location: ancestor.source&.location || raise,
@@ -381,19 +398,23 @@ module Steep
381
398
  builder.build_instance(ancestor.name)
382
399
  when ancestor.name.interface?
383
400
  builder.build_interface(ancestor.name)
401
+ else
402
+ raise
384
403
  end
385
404
 
386
405
  location =
387
- if ancestor.source == :super
406
+ case ancestor.source
407
+ when :super
388
408
  primary_decl = env.class_decls[name].primary.decl
409
+ primary_decl.is_a?(RBS::AST::Declarations::Class) or raise
389
410
  if super_class = primary_decl.super_class
390
411
  super_class.location
391
412
  else
392
413
  # Implicit super class (Object): this can be skipped in fact...
393
- primary_decl.location[:name]
414
+ primary_decl.location&.aref(:name)
394
415
  end
395
416
  else
396
- ancestor.source.location
417
+ ancestor.source&.location
397
418
  end
398
419
 
399
420
  validate_type_application_constraints(
@@ -423,12 +444,14 @@ module Steep
423
444
  case ancestor
424
445
  when RBS::Definition::Ancestor::Instance
425
446
  # Interface ancestor cannot be other than Interface
447
+ ancestor.source.is_a?(Symbol) and raise
448
+
426
449
  defn = builder.build_interface(ancestor.name)
427
450
  validate_type_application_constraints(
428
451
  ancestor.name,
429
452
  defn.type_params_decl,
430
453
  ancestor.args,
431
- location: ancestor.source.location || raise
454
+ location: ancestor.source&.location || raise
432
455
  )
433
456
  end
434
457
  end