steep 1.8.0.dev.1 → 1.8.0.pre.1

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