steep 1.8.0.dev.1 → 1.8.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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.md +3 -2
  4. data/bin/mem_graph.rb +67 -0
  5. data/bin/mem_prof.rb +102 -0
  6. data/bin/stackprof_test.rb +19 -0
  7. data/bin/steep-check.rb +251 -0
  8. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +1 -1
  9. data/lib/steep/annotation_parser.rb +1 -1
  10. data/lib/steep/ast/builtin.rb +5 -5
  11. data/lib/steep/ast/node/type_application.rb +7 -6
  12. data/lib/steep/ast/types/any.rb +1 -9
  13. data/lib/steep/ast/types/boolean.rb +8 -16
  14. data/lib/steep/ast/types/bot.rb +2 -10
  15. data/lib/steep/ast/types/class.rb +1 -13
  16. data/lib/steep/ast/types/factory.rb +101 -85
  17. data/lib/steep/ast/types/instance.rb +1 -13
  18. data/lib/steep/ast/types/intersection.rb +8 -15
  19. data/lib/steep/ast/types/literal.rb +2 -8
  20. data/lib/steep/ast/types/logic.rb +3 -24
  21. data/lib/steep/ast/types/name.rb +5 -16
  22. data/lib/steep/ast/types/nil.rb +3 -12
  23. data/lib/steep/ast/types/proc.rb +4 -13
  24. data/lib/steep/ast/types/record.rb +21 -12
  25. data/lib/steep/ast/types/self.rb +1 -13
  26. data/lib/steep/ast/types/shared_instance.rb +11 -0
  27. data/lib/steep/ast/types/top.rb +1 -9
  28. data/lib/steep/ast/types/tuple.rb +4 -10
  29. data/lib/steep/ast/types/union.rb +10 -15
  30. data/lib/steep/ast/types/var.rb +4 -13
  31. data/lib/steep/ast/types/void.rb +2 -10
  32. data/lib/steep/diagnostic/ruby.rb +10 -10
  33. data/lib/steep/drivers/check.rb +11 -14
  34. data/lib/steep/drivers/checkfile.rb +8 -10
  35. data/lib/steep/drivers/stats.rb +17 -13
  36. data/lib/steep/drivers/utils/driver_helper.rb +24 -3
  37. data/lib/steep/drivers/watch.rb +3 -3
  38. data/lib/steep/interface/builder.rb +162 -138
  39. data/lib/steep/interface/method_type.rb +12 -20
  40. data/lib/steep/interface/shape.rb +66 -10
  41. data/lib/steep/interface/substitution.rb +2 -0
  42. data/lib/steep/interface/type_param.rb +20 -7
  43. data/lib/steep/located_value.rb +20 -0
  44. data/lib/steep/server/change_buffer.rb +5 -7
  45. data/lib/steep/server/custom_methods.rb +61 -0
  46. data/lib/steep/server/delay_queue.rb +8 -1
  47. data/lib/steep/server/interaction_worker.rb +13 -6
  48. data/lib/steep/server/lsp_formatter.rb +8 -6
  49. data/lib/steep/server/master.rb +195 -142
  50. data/lib/steep/server/type_check_worker.rb +25 -22
  51. data/lib/steep/server/work_done_progress.rb +64 -0
  52. data/lib/steep/server/worker_process.rb +1 -1
  53. data/lib/steep/services/completion_provider.rb +32 -24
  54. data/lib/steep/services/goto_service.rb +3 -2
  55. data/lib/steep/services/hover_provider/ruby.rb +30 -17
  56. data/lib/steep/services/signature_help_provider.rb +9 -7
  57. data/lib/steep/services/signature_service.rb +1 -1
  58. data/lib/steep/services/type_check_service.rb +19 -9
  59. data/lib/steep/signature/validator.rb +17 -20
  60. data/lib/steep/source.rb +47 -1
  61. data/lib/steep/subtyping/check.rb +105 -55
  62. data/lib/steep/subtyping/constraints.rb +13 -17
  63. data/lib/steep/type_construction.rb +106 -100
  64. data/lib/steep/type_inference/block_params.rb +8 -5
  65. data/lib/steep/type_inference/logic_type_interpreter.rb +11 -7
  66. data/lib/steep/type_inference/method_call.rb +3 -3
  67. data/lib/steep/type_inference/method_params.rb +1 -1
  68. data/lib/steep/type_inference/send_args.rb +1 -1
  69. data/lib/steep/typing.rb +164 -106
  70. data/lib/steep/version.rb +1 -1
  71. data/lib/steep.rb +29 -4
  72. data/steep.gemspec +2 -2
  73. metadata +16 -9
  74. data/lib/steep/type_inference/context_array.rb +0 -112
@@ -11,9 +11,7 @@ module Steep
11
11
  TypeCheckCodeJob = _ = Struct.new(:guid, :path, keyword_init: true)
12
12
  ValidateAppSignatureJob = _ = Struct.new(:guid, :path, keyword_init: true)
13
13
  ValidateLibrarySignatureJob = _ = Struct.new(:guid, :path, keyword_init: true)
14
- GotoJob = _ = Struct.new(:id, :kind, :params, keyword_init: true) do
15
- # @implements GotoJob
16
-
14
+ class GotoJob < Struct.new(:id, :kind, :params, keyword_init: true)
17
15
  def self.implementation(id:, params:)
18
16
  new(
19
17
  kind: :implementation,
@@ -57,7 +55,6 @@ module Steep
57
55
  super(project: project, reader: reader, writer: writer)
58
56
 
59
57
  @assignment = assignment
60
- @service = Services::TypeCheckService.new(project: project)
61
58
  @buffered_changes = {}
62
59
  @mutex = Mutex.new()
63
60
  @queue = Queue.new
@@ -65,30 +62,35 @@ module Steep
65
62
  @current_type_check_guid = nil
66
63
  end
67
64
 
65
+ def service
66
+ @service ||= Services::TypeCheckService.new(project: project)
67
+ end
68
+
68
69
  def handle_request(request)
69
70
  case request[:method]
70
71
  when "initialize"
71
- load_files(project: project, commandline_args: commandline_args)
72
72
  writer.write({ id: request[:id], result: nil})
73
73
 
74
74
  when "textDocument/didChange"
75
75
  collect_changes(request)
76
76
 
77
- when "$/file/reset"
78
- uri = request[:params][:uri]
79
- text = request[:params][:content]
77
+ when CustomMethods::FileLoad::METHOD
78
+ input = request[:params][:content]
79
+ load_files(input)
80
+
81
+ when CustomMethods::FileReset::METHOD
82
+ params = request[:params] #: CustomMethods::FileReset::params
83
+ uri = params[:uri]
84
+ text = params[:content]
80
85
  reset_change(uri: uri, text: text)
81
86
 
82
87
  when "workspace/symbol"
83
88
  query = request[:params][:query]
84
89
  queue << WorkspaceSymbolJob.new(id: request[:id], query: query)
85
- when "workspace/executeCommand"
86
- case request[:params][:command]
87
- when "steep/stats"
88
- queue << StatsJob.new(id: request[:id])
89
- end
90
- when "$/typecheck/start"
91
- params = request[:params]
90
+ when CustomMethods::Stats::METHOD
91
+ queue << StatsJob.new(id: request[:id])
92
+ when CustomMethods::TypeCheck__Start::METHOD
93
+ params = request[:params] #: CustomMethods::TypeCheck__Start::params
92
94
  enqueue_typecheck_jobs(params)
93
95
  when "textDocument/definition"
94
96
  queue << GotoJob.definition(id: request[:id], params: request[:params])
@@ -173,7 +175,9 @@ module Steep
173
175
  method: :"textDocument/publishDiagnostics",
174
176
  params: LSP::Interface::PublishDiagnosticsParams.new(
175
177
  uri: Steep::PathHelper.to_uri(job.path).to_s,
176
- diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
178
+ diagnostics: diagnostics.map {|diagnostic|
179
+ _ = formatter.format(diagnostic)
180
+ }.uniq
177
181
  )
178
182
  )
179
183
  end
@@ -191,7 +195,7 @@ module Steep
191
195
  method: :"textDocument/publishDiagnostics",
192
196
  params: LSP::Interface::PublishDiagnosticsParams.new(
193
197
  uri: Steep::PathHelper.to_uri(job.path).to_s,
194
- diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
198
+ diagnostics: diagnostics.map {|diagnostic| _ = formatter.format(diagnostic) }.uniq.compact
195
199
  )
196
200
  )
197
201
  end
@@ -210,7 +214,9 @@ module Steep
210
214
  method: :"textDocument/publishDiagnostics",
211
215
  params: LSP::Interface::PublishDiagnosticsParams.new(
212
216
  uri: Steep::PathHelper.to_uri(job.path).to_s,
213
- diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
217
+ diagnostics: diagnostics.map {|diagnostic|
218
+ _ = formatter.format(diagnostic)
219
+ }.uniq.compact
214
220
  )
215
221
  )
216
222
  end
@@ -237,10 +243,7 @@ module Steep
237
243
  end
238
244
 
239
245
  def typecheck_progress(guid:, path:)
240
- writer.write(
241
- method: "$/typecheck/progress",
242
- params: { guid: guid, path: path }
243
- )
246
+ writer.write(CustomMethods::TypeCheck__Progress.notification({ guid: guid, path: path.to_s }))
244
247
  end
245
248
 
246
249
  def workspace_symbol_result(query)
@@ -0,0 +1,64 @@
1
+ module Steep
2
+ module Server
3
+ class WorkDoneProgress
4
+ attr_reader :sender, :guid, :percentage
5
+
6
+ def initialize(guid, &block)
7
+ @sender = block
8
+ @guid = guid
9
+ @percentage = 0
10
+ end
11
+
12
+ def begin(title, message = nil, request_id:)
13
+ sender.call(
14
+ {
15
+ id: request_id,
16
+ method: "window/workDoneProgress/create",
17
+ params: { token: guid }
18
+ }
19
+ )
20
+
21
+ value = { kind: "begin", cancellable: false, title: title, percentage: percentage }
22
+ value[:message] = message if message
23
+
24
+ sender.call(
25
+ {
26
+ method: "$/progress",
27
+ params: { token: guid, value: value }
28
+ }
29
+ )
30
+
31
+ self
32
+ end
33
+
34
+ def report(percentage, message = nil)
35
+ @percentage = percentage
36
+ value = { kind: "report", percentage: percentage }
37
+ value[:message] = message if message
38
+
39
+ sender.call(
40
+ {
41
+ method: "$/progress",
42
+ params: { token: guid, value: value }
43
+ }
44
+ )
45
+
46
+ self
47
+ end
48
+
49
+ def end(message = nil)
50
+ value = { kind: "end" }
51
+ value[:message] = message if message
52
+
53
+ sender.call(
54
+ {
55
+ method: "$/progress",
56
+ params: { token: guid, value: value }
57
+ }
58
+ )
59
+
60
+ self
61
+ end
62
+ end
63
+ end
64
+ end
@@ -132,7 +132,7 @@ module Steep
132
132
  new(reader: reader, writer: writer, stderr: stderr, wait_thread: thread, name: name, index: index&.[](1))
133
133
  end
134
134
 
135
- def self.start_typecheck_workers(steepfile:, args:, steep_command:, count: [Etc.nprocessors - 1, 1].max, delay_shutdown: false)
135
+ def self.start_typecheck_workers(steepfile:, args:, steep_command:, count: [Etc.nprocessors - 1, 1].max || raise, delay_shutdown: false)
136
136
  count.times.map do |i|
137
137
  start_worker(
138
138
  :typecheck,
@@ -183,8 +183,9 @@ module Steep
183
183
  end
184
184
 
185
185
  Steep.measure "typechecking" do
186
+ location = source.buffer.loc_to_pos([line, column])
186
187
  resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
187
- @typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
188
+ @typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: location)
188
189
  end
189
190
  end
190
191
 
@@ -348,7 +349,7 @@ module Steep
348
349
 
349
350
  items = [] #: Array[item]
350
351
 
351
- context = typing.context_at(line: position.line, column: position.column)
352
+ context = typing.cursor_context.context or raise
352
353
 
353
354
  case
354
355
  when node.type == :send && node.children[0] == nil && at_end?(position, of: (_ = node.loc).selector)
@@ -469,7 +470,7 @@ module Steep
469
470
 
470
471
  if at_end?(shift_pos, of: node.loc)
471
472
  begin
472
- context = typing.context_at(line: position.line, column: position.column)
473
+ context = typing.cursor_context.context or raise
473
474
  receiver_type =
474
475
  case (type = typing.type_of(node: node))
475
476
  when AST::Types::Self
@@ -499,7 +500,7 @@ module Steep
499
500
 
500
501
  if at_end?(shift_pos, of: node.loc)
501
502
  begin
502
- context = typing.context_at(line: position.line, column: position.column)
503
+ context = typing.cursor_context.context or raise
503
504
  receiver_type =
504
505
  case (type = typing.type_of(node: node))
505
506
  when AST::Types::Self
@@ -529,11 +530,11 @@ module Steep
529
530
  case node&.type
530
531
  when :const
531
532
  # Constant:: ←
532
- context = typing.context_at(line: position.line, column: position.column)
533
+ context = typing.cursor_context.context or raise
533
534
  constant_items_for_context(context, parent: node, position: position, items: items, prefix: "")
534
535
  when nil
535
536
  # :: ←
536
- context = typing.context_at(line: position.line, column: position.column)
537
+ context = typing.cursor_context.context or raise
537
538
  constant_items_for_context(context, parent: nil, position: position, items: items, prefix: "")
538
539
  end
539
540
 
@@ -552,7 +553,7 @@ module Steep
552
553
 
553
554
  return [] unless node
554
555
 
555
- context = typing.context_at(line: position.line, column: position.column)
556
+ context = typing.cursor_context.context or raise
556
557
  items = [] #: Array[item]
557
558
  instance_variable_items_for_context(context, prefix: "@", position: position, items: items)
558
559
  items
@@ -561,7 +562,7 @@ module Steep
561
562
  def items_for_rbs(position:, buffer:)
562
563
  items = [] #: Array[item]
563
564
 
564
- context = typing.context_at(line: position.line, column: position.column)
565
+ context = typing.cursor_context.context or raise
565
566
  completion = TypeNameCompletion.new(env: context.env, context: context.module_context.nesting, dirs: [])
566
567
  prefix = TypeNameCompletion::Prefix.parse(buffer, line: position.line, column: position.column)
567
568
 
@@ -609,7 +610,7 @@ module Steep
609
610
 
610
611
  def method_items_for_receiver_type(type, include_private:, prefix:, position:, items:)
611
612
  range = range_for(position, prefix: prefix)
612
- context = typing.context_at(line: position.line, column: position.column)
613
+ context = typing.cursor_context.context or raise
613
614
 
614
615
  config =
615
616
  if (module_type = context.module_context&.module_type) && (instance_type = context.module_context&.instance_type)
@@ -634,39 +635,40 @@ module Steep
634
635
  case type
635
636
  when AST::Types::Name::Instance, AST::Types::Name::Interface, AST::Types::Name::Singleton
636
637
  # Simple method type
637
- all_decls = Set.new(method_entry.method_types.flat_map {|method_type| method_type.method_decls.to_a }).sort_by {|decl| decl.method_name.to_s }
638
+ all_decls = Set.new(method_entry.overloads.flat_map {|overload| overload.method_decls(name) }).sort_by {|decl| decl.method_name.to_s }
638
639
  all_members = Set.new(all_decls.flat_map {|decl| decl.method_def.member })
639
640
  all_members.each do |member|
640
641
  associated_decl = all_decls.find {|decl| decl.method_def.member == member } or next
641
- method_types = method_entry.method_types.select {|method_type| method_type.method_decls.any? {|decl| decl.method_def.member == member }}
642
+ overloads = method_entry.overloads.select {|overload| overload.method_defs.any? {|defn| defn.member == member }}
642
643
  items << SimpleMethodNameItem.new(
643
644
  identifier: name,
644
645
  range: range,
645
646
  receiver_type: type,
646
647
  method_name: associated_decl.method_name,
647
- method_types: method_types.map {|type| subtyping.factory.method_type_1(type) },
648
+ method_types: overloads.map {|overload| subtyping.factory.method_type_1(overload.method_type) },
648
649
  method_member: member
649
650
  )
650
651
  end
651
652
  else
652
- generated_method_types, defined_method_types = method_entry.method_types.partition {|method_type| method_type.method_decls.empty? }
653
+ generated_overloads, defined_overloads =
654
+ method_entry.overloads.partition {|overload| overload.method_defs.empty? }
653
655
 
654
- unless defined_method_types.empty?
656
+ unless defined_overloads.empty?
655
657
  items << ComplexMethodNameItem.new(
656
658
  identifier: name,
657
659
  range: range,
658
660
  receiver_type: type,
659
- method_types: defined_method_types.map {|type| subtyping.factory.method_type_1(type) },
660
- method_decls: defined_method_types.flat_map {|type| type.method_decls.to_a }.sort_by {|decl| decl.method_name.to_s }
661
+ method_types: defined_overloads.map { subtyping.factory.method_type_1(_1.method_type) },
662
+ method_decls: defined_overloads.flat_map { _1.method_decls(name).to_a }.sort_by {|decl| decl.method_name.to_s }
661
663
  )
662
664
  end
663
665
 
664
- unless generated_method_types.empty?
666
+ unless generated_overloads.empty?
665
667
  items << GeneratedMethodNameItem.new(
666
668
  identifier: name,
667
669
  range: range,
668
670
  receiver_type: type,
669
- method_types: generated_method_types.map {|type| subtyping.factory.method_type_1(type) }
671
+ method_types: generated_overloads.map { subtyping.factory.method_type_1(_1.method_type) }
670
672
  )
671
673
  end
672
674
  end
@@ -725,27 +727,33 @@ module Steep
725
727
  end
726
728
 
727
729
  def keyword_argument_items_for_method(call_node:, send_node:, position:, prefix:, items:)
728
- receiver_node, method_name, argument_nodes = deconstruct_send_node!(send_node)
730
+ _receiver_node, _method_name, argument_nodes = deconstruct_send_node!(send_node)
729
731
 
730
732
  call = typing.call_of(node: call_node)
731
733
 
732
734
  case call
733
735
  when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
734
- context = typing.context_at(line: position.line, column: position.column)
736
+ context = typing.cursor_context.context or raise
735
737
  type = call.receiver_type
738
+ type = type.subst(Interface::Substitution.build([], self_type: context.self_type, module_type: context.module_context&.module_type, instance_type: context.module_context&.instance_type))
736
739
 
737
740
  config = Interface::Builder::Config.new(self_type: type, variable_bounds: context.variable_context.upper_bounds)
738
741
  if shape = subtyping.builder.shape(type, config)
739
742
  shape = shape.public_shape if private_send?(call_node)
740
743
  if method = shape.methods[call.method_name]
741
- method.method_types.each.with_index do |method_type, i|
742
- defn = method_type.method_decls.to_a[0]&.method_def
744
+ method.overloads.each.with_index do |overload, i|
745
+ defn = overload.method_decls(call.method_name).to_a[0]&.method_def
743
746
  if defn && defn.type.type
744
747
  range = range_for(position, prefix: prefix)
745
748
  kwargs = argument_nodes.find { |arg| arg.type == :kwargs }&.children || []
746
749
  used_kwargs = kwargs.filter_map { |arg| arg.type == :pair && arg.children.first.children.first }
747
750
 
748
- kwargs = defn.type.type.required_keywords.keys + defn.type.type.optional_keywords.keys
751
+ if defn.type.type.is_a?(RBS::Types::UntypedFunction)
752
+ kwargs = [] #: Array[Symbol]
753
+ else
754
+ kwargs = defn.type.type.required_keywords.keys + defn.type.type.optional_keywords.keys
755
+ end
756
+
749
757
  kwargs.each do |name|
750
758
  if name.to_s.start_with?(prefix) && !used_kwargs.include?(name)
751
759
  items << KeywordArgumentItem.new(identifier: "#{name}:", range: range)
@@ -784,7 +792,7 @@ module Steep
784
792
  def unwrap_optional(type)
785
793
  if type.is_a?(AST::Types::Union) && type.types.include?(AST::Builtin.nil_type)
786
794
  types = type.types.reject { |t| t == AST::Builtin.nil_type }
787
- AST::Types::Union.new(types: types, location: type.location)
795
+ AST::Types::Union.new(types: types)
788
796
  else
789
797
  type
790
798
  end
@@ -176,7 +176,7 @@ module Steep
176
176
  when :def, :defs
177
177
  named_location = (_ = node.location) #: Parser::AST::_NamedLocation
178
178
  if test_ast_location(named_location.name, line: line, column: column)
179
- if method_context = typing.context_at(line: line, column: column).method_context
179
+ if method_context = typing.cursor_context.context&.method_context
180
180
  if method = method_context.method
181
181
  method.defs.each do |defn|
182
182
  singleton_method =
@@ -285,8 +285,9 @@ module Steep
285
285
  source = Source.parse(content, path: path, factory: subtyping.factory)
286
286
  source = source.without_unrelated_defs(line: line, column: column)
287
287
  resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
288
+ loc = source.buffer.loc_to_pos([line, column])
288
289
  [
289
- Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver),
290
+ Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: loc),
290
291
  signature_service
291
292
  ]
292
293
  rescue
@@ -84,7 +84,8 @@ module Steep
84
84
  source = Source.parse(content, path: path, factory: subtyping.factory)
85
85
  source = source.without_unrelated_defs(line: line, column: column)
86
86
  resolver = ::RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
87
- Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
87
+ pos = source.buffer.loc_to_pos([line, column])
88
+ Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: pos)
88
89
  rescue
89
90
  nil
90
91
  end
@@ -118,17 +119,27 @@ module Steep
118
119
  case node.type
119
120
  when :lvar
120
121
  var_name = node.children[0]
121
- context = typing.context_at(line: line, column: column)
122
- var_type = context.type_env[var_name] || AST::Types::Any.new(location: nil)
122
+ context = typing.cursor_context.context or raise
123
+ var_type = context.type_env[var_name] || AST::Types::Any.instance()
123
124
 
124
- return VariableContent.new(node: node, name: var_name, type: var_type, location: node.location.name)
125
+ return VariableContent.new(
126
+ node: node,
127
+ name: var_name,
128
+ type: var_type,
129
+ location: node.location.name # steep:ignore NoMethod
130
+ )
125
131
 
126
132
  when :lvasgn
127
133
  var_name, rhs = node.children
128
- context = typing.context_at(line: line, column: column)
134
+ context = typing.cursor_context.context or raise
129
135
  type = context.type_env[var_name] || typing.type_of(node: node)
130
136
 
131
- return VariableContent.new(node: node, name: var_name, type: type, location: node.location.name)
137
+ return VariableContent.new(
138
+ node: node,
139
+ name: var_name,
140
+ type: type,
141
+ location: node.location.name # steep:ignore NoMethod
142
+ )
132
143
 
133
144
  when :send, :csend
134
145
  result_node =
@@ -149,27 +160,29 @@ module Steep
149
160
  return MethodCallContent.new(
150
161
  node: result_node,
151
162
  method_call: call,
152
- location: node.location.selector
163
+ location: node.location.selector # steep:ignore NoMethod
153
164
  )
154
165
  end
155
166
  end
156
167
 
157
168
  when :def, :defs
158
- context = typing.context_at(line: line, column: column)
169
+ context = typing.cursor_context.context or raise
159
170
  method_context = context.method_context
160
171
 
161
172
  if method_context && method_context.method
162
- return DefinitionContent.new(
163
- node: node,
164
- method_name: method_name_from_method(method_context, builder: context.factory.definition_builder),
165
- method_type: method_context.method_type,
166
- definition: method_context.method,
167
- location: node.loc.name
168
- )
173
+ if method_context.method_type
174
+ return DefinitionContent.new(
175
+ node: node,
176
+ method_name: method_name_from_method(method_context, builder: context.factory.definition_builder),
177
+ method_type: method_context.method_type,
178
+ definition: method_context.method,
179
+ location: node.loc.name # steep:ignore NoMethod
180
+ )
181
+ end
169
182
  end
170
183
 
171
184
  when :const, :casgn
172
- context = typing.context_at(line: line, column: column)
185
+ context = typing.cursor_context.context or raise
173
186
 
174
187
  type = typing.type_of(node: node)
175
188
  const_name = typing.source_index.reference(constant_node: node)
@@ -178,7 +191,7 @@ module Steep
178
191
  entry = context.env.constant_entry(const_name) or return
179
192
 
180
193
  return ConstantContent.new(
181
- location: node.location.name,
194
+ location: node.location.name, # steep:ignore NoMethod
182
195
  full_name: const_name,
183
196
  type: type,
184
197
  decl: entry
@@ -11,7 +11,7 @@ module Steep
11
11
  arguments = [] #: Array[String]
12
12
  arguments.push(*method_type.type.required_positionals.map(&:to_s))
13
13
  arguments.push(*method_type.type.optional_positionals.map {|p| "?#{p}"})
14
- arguments.push("*#{self.method_type.type.rest_positionals}") if method_type.type.rest_positionals
14
+ arguments.push("*#{method_type.type.rest_positionals}") if method_type.type.rest_positionals
15
15
  arguments.push(*method_type.type.trailing_positionals.map(&:to_s))
16
16
  arguments.push(*method_type.type.required_keywords.map {|name, param| "#{name}: #{param}" })
17
17
  arguments.push(*method_type.type.optional_keywords.map {|name, param| "?#{name}: #{param}" })
@@ -76,7 +76,8 @@ module Steep
76
76
  def type_check!(line:, column:)
77
77
  source = self.source.without_unrelated_defs(line: line, column: column)
78
78
  resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
79
- TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
79
+ pos = self.source.buffer.loc_to_pos([line, column])
80
+ TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: pos)
80
81
  end
81
82
 
82
83
  def last_argument_nodes_for(argument_nodes:, line:, column:)
@@ -99,7 +100,7 @@ module Steep
99
100
 
100
101
  def signature_help_for(node, argument, last_argument, typing)
101
102
  call = typing.call_of(node: node)
102
- context = typing.context_at(line: node.loc.expression.line, column: node.loc.expression.column)
103
+ context = typing.cursor_context.context or raise
103
104
 
104
105
  items = [] #: Array[Item]
105
106
  index = nil #: Integer?
@@ -113,14 +114,14 @@ module Steep
113
114
  shape = shape.public_shape if private_send?(node)
114
115
 
115
116
  if method = shape.methods[call.method_name]
116
- method.method_types.each.with_index do |method_type, i|
117
- defn = method_type.method_decls.to_a[0]&.method_def
117
+ method.overloads.each.with_index do |overload, i|
118
+ defn = overload.method_defs[0]
118
119
 
119
120
  active_parameter = active_parameter_for(defn&.type, argument, last_argument, node)
120
- items << Item.new(subtyping.factory.method_type_1(method_type), defn&.comment, active_parameter)
121
+ items << Item.new(subtyping.factory.method_type_1(overload.method_type), defn&.comment, active_parameter)
121
122
 
122
123
  if call.is_a?(MethodCall::Typed)
123
- if method_type.method_decls.intersect?(call.method_decls)
124
+ if call.method_decls.intersect?(overload.method_decls(call.method_name).to_set)
124
125
  index = i
125
126
  end
126
127
  end
@@ -136,6 +137,7 @@ module Steep
136
137
 
137
138
  def active_parameter_for(method_type, argument_nodes, last_argument_nodes, node)
138
139
  return unless method_type
140
+ return unless method_type.type.is_a?(RBS::Types::Function)
139
141
 
140
142
  positionals = method_type.type.required_positionals.size + method_type.type.optional_positionals.size + (method_type.type.rest_positionals ? 1 : 0) + method_type.type.trailing_positionals.size
141
143
 
@@ -156,6 +156,7 @@ module Steep
156
156
  old_text = files[path]&.content
157
157
  content = cs.inject(old_text || "") {|text, change| change.apply_to(text) }
158
158
 
159
+ content ||= "" # It was not clear why `content` can be `nil`, but it happens with `master_test`.
159
160
  buffer = RBS::Buffer.new(name: path, content: content)
160
161
 
161
162
  update[path] =
@@ -228,7 +229,6 @@ module Steep
228
229
  end
229
230
 
230
231
  def update_env(updated_files, paths:)
231
-
232
232
  Steep.logger.tagged "#update_env" do
233
233
  errors = [] #: Array[RBS::BaseError]
234
234
  new_decls = Set[].compare_by_identity #: Set[RBS::AST::Declarations::t]
@@ -139,8 +139,11 @@ module Steep
139
139
 
140
140
  case service.status
141
141
  when SignatureService::SyntaxErrorStatus, SignatureService::AncestorErrorStatus
142
- service.status.diagnostics.group_by {|diag| Pathname(diag.location.buffer.name) }.each do |path, diagnostics|
143
- signature_diagnostics[path].push(*diagnostics)
142
+ service.status.diagnostics.group_by {|diag| diag.location&.buffer&.name&.to_s }.each do |path_string, diagnostics|
143
+ if path_string
144
+ path = Pathname(path_string)
145
+ signature_diagnostics[path].push(*diagnostics)
146
+ end
144
147
  end
145
148
  when SignatureService::LoadedStatus
146
149
  validation_diagnostics = signature_validation_diagnostics[target.name] || {}
@@ -230,6 +233,7 @@ module Steep
230
233
  case service.status
231
234
  when SignatureService::SyntaxErrorStatus
232
235
  diagnostics = service.status.diagnostics.select do |diag|
236
+ diag.location or raise
233
237
  Pathname(diag.location.buffer.name) == path &&
234
238
  (diag.is_a?(Diagnostic::Signature::SyntaxError) || diag.is_a?(Diagnostic::Signature::UnexpectedError))
235
239
  end
@@ -239,12 +243,15 @@ module Steep
239
243
  end
240
244
 
241
245
  when SignatureService::AncestorErrorStatus
242
- diagnostics = service.status.diagnostics.select {|diag| Pathname(diag.location.buffer.name) == path }
246
+ diagnostics = service.status.diagnostics.select do |diag|
247
+ diag.location or raise
248
+ Pathname(diag.location.buffer.name) == path
249
+ end
243
250
  accumulated_diagnostics.push(*diagnostics)
244
251
  yield [path, accumulated_diagnostics]
245
252
 
246
253
  when SignatureService::LoadedStatus
247
- validator = Signature::Validator.new(checker: service.current_subtyping)
254
+ validator = Signature::Validator.new(checker: service.current_subtyping || raise)
248
255
  type_names = service.type_names(paths: Set[path], env: service.latest_env).to_set
249
256
 
250
257
  unless type_names.empty?
@@ -286,7 +293,10 @@ module Steep
286
293
  end
287
294
  end
288
295
 
289
- diagnostics = validator.each_error.select {|error| Pathname(error.location.buffer.name) == path }
296
+ diagnostics = validator.each_error.select do |error|
297
+ error.location or raise
298
+ Pathname(error.location.buffer.name) == path
299
+ end
290
300
  accumulated_diagnostics.push(*diagnostics)
291
301
  yield [path, accumulated_diagnostics]
292
302
  end
@@ -353,7 +363,7 @@ module Steep
353
363
  def type_check_file(target:, subtyping:, path:, text:)
354
364
  Steep.logger.tagged "#type_check_file(#{path}@#{target.name})" do
355
365
  source = Source.parse(text, path: path, factory: subtyping.factory)
356
- typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: yield)
366
+ typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: yield, cursor: nil)
357
367
  ignores = Source::IgnoreRanges.new(ignores: source.ignores)
358
368
  SourceFile.with_typing(path: path, content: text, node: source.node, typing: typing, ignores: ignores)
359
369
  end
@@ -361,7 +371,7 @@ module Steep
361
371
  error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: exn.location)
362
372
  SourceFile.with_syntax_error(path: path, content: text, error: error)
363
373
  rescue ::Parser::SyntaxError => exn
364
- error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: exn.diagnostic.location)
374
+ error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: (_ = exn).diagnostic.location)
365
375
  SourceFile.with_syntax_error(path: path, content: text, error: error)
366
376
  rescue EncodingError => exn
367
377
  SourceFile.no_data(path: path, content: "")
@@ -370,7 +380,7 @@ module Steep
370
380
  SourceFile.no_data(path: path, content: text)
371
381
  end
372
382
 
373
- def self.type_check(source:, subtyping:, constant_resolver:)
383
+ def self.type_check(source:, subtyping:, constant_resolver:, cursor:)
374
384
  annotations = source.annotations(block: source.node, factory: subtyping.factory, context: nil)
375
385
 
376
386
  definition = subtyping.factory.definition_builder.build_instance(AST::Builtin::Object.module_name)
@@ -408,7 +418,7 @@ module Steep
408
418
  variable_context: TypeInference::Context::TypeVariableContext.empty
409
419
  )
410
420
 
411
- typing = Typing.new(source: source, root_context: context)
421
+ typing = Typing.new(source: source, root_context: context, cursor: cursor)
412
422
 
413
423
  construction = TypeConstruction.new(
414
424
  checker: subtyping,