steep 1.10.0.pre.3 → 2.0.0

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +87 -0
  3. data/CLAUDE.md +114 -0
  4. data/README.md +1 -1
  5. data/Rakefile +15 -3
  6. data/Steepfile +13 -13
  7. data/lib/steep/annotation_parser.rb +5 -1
  8. data/lib/steep/annotations_helper.rb +12 -2
  9. data/lib/steep/ast/node/type_application.rb +22 -16
  10. data/lib/steep/ast/node/type_assertion.rb +7 -4
  11. data/lib/steep/ast/types/factory.rb +3 -2
  12. data/lib/steep/cli.rb +246 -2
  13. data/lib/steep/daemon/configuration.rb +19 -0
  14. data/lib/steep/daemon/server.rb +476 -0
  15. data/lib/steep/daemon.rb +201 -0
  16. data/lib/steep/diagnostic/ruby.rb +50 -8
  17. data/lib/steep/diagnostic/signature.rb +31 -8
  18. data/lib/steep/drivers/check.rb +301 -140
  19. data/lib/steep/drivers/print_project.rb +9 -10
  20. data/lib/steep/drivers/query.rb +102 -0
  21. data/lib/steep/drivers/start_server.rb +19 -0
  22. data/lib/steep/drivers/stop_server.rb +20 -0
  23. data/lib/steep/drivers/watch.rb +2 -2
  24. data/lib/steep/index/rbs_index.rb +38 -13
  25. data/lib/steep/index/signature_symbol_provider.rb +24 -3
  26. data/lib/steep/interface/builder.rb +48 -15
  27. data/lib/steep/interface/shape.rb +13 -5
  28. data/lib/steep/locator.rb +377 -0
  29. data/lib/steep/project/dsl.rb +26 -5
  30. data/lib/steep/project/group.rb +8 -2
  31. data/lib/steep/project/target.rb +16 -2
  32. data/lib/steep/project.rb +21 -2
  33. data/lib/steep/server/base_worker.rb +2 -2
  34. data/lib/steep/server/change_buffer.rb +2 -1
  35. data/lib/steep/server/custom_methods.rb +12 -0
  36. data/lib/steep/server/inline_source_change_detector.rb +94 -0
  37. data/lib/steep/server/interaction_worker.rb +51 -74
  38. data/lib/steep/server/lsp_formatter.rb +48 -12
  39. data/lib/steep/server/master.rb +100 -18
  40. data/lib/steep/server/target_group_files.rb +124 -151
  41. data/lib/steep/server/type_check_controller.rb +276 -123
  42. data/lib/steep/server/type_check_worker.rb +104 -3
  43. data/lib/steep/services/completion_provider/rbs.rb +74 -0
  44. data/lib/steep/services/completion_provider/ruby.rb +652 -0
  45. data/lib/steep/services/completion_provider/type_name.rb +243 -0
  46. data/lib/steep/services/completion_provider.rb +39 -662
  47. data/lib/steep/services/content_change.rb +14 -1
  48. data/lib/steep/services/file_loader.rb +4 -2
  49. data/lib/steep/services/goto_service.rb +271 -68
  50. data/lib/steep/services/hover_provider/content.rb +67 -0
  51. data/lib/steep/services/hover_provider/rbs.rb +8 -9
  52. data/lib/steep/services/hover_provider/ruby.rb +123 -64
  53. data/lib/steep/services/hover_provider/singleton_methods.rb +4 -0
  54. data/lib/steep/services/signature_service.rb +129 -54
  55. data/lib/steep/services/type_check_service.rb +72 -27
  56. data/lib/steep/signature/validator.rb +30 -18
  57. data/lib/steep/source/ignore_ranges.rb +14 -4
  58. data/lib/steep/source.rb +16 -2
  59. data/lib/steep/tagged_logging.rb +39 -0
  60. data/lib/steep/type_construction.rb +94 -21
  61. data/lib/steep/type_inference/block_params.rb +7 -7
  62. data/lib/steep/type_inference/context.rb +4 -2
  63. data/lib/steep/type_inference/logic_type_interpreter.rb +21 -3
  64. data/lib/steep/type_inference/method_call.rb +4 -0
  65. data/lib/steep/type_inference/type_env.rb +1 -1
  66. data/lib/steep/typing.rb +0 -2
  67. data/lib/steep/version.rb +1 -1
  68. data/lib/steep.rb +42 -32
  69. data/manual/ruby-diagnostics.md +67 -0
  70. data/sample/Steepfile +1 -0
  71. data/sample/lib/conference.rb +1 -0
  72. data/sample/lib/deprecated.rb +6 -0
  73. data/sample/lib/inline.rb +43 -0
  74. data/sample/sig/generics.rbs +3 -0
  75. data/steep.gemspec +4 -5
  76. metadata +26 -26
  77. data/lib/steep/services/type_name_completion.rb +0 -236
@@ -1,8 +1,6 @@
1
1
  module Steep
2
2
  module Services
3
- class CompletionProvider
4
- include NodeHelper
5
-
3
+ module CompletionProvider
6
4
  Position = _ = Struct.new(:line, :column, keyword_init: true) do
7
5
  # @implements Position
8
6
  def -(size)
@@ -28,11 +26,18 @@ module Steep
28
26
 
29
27
  def comments
30
28
  case entry = env.constant_entry(full_name)
31
- when RBS::Environment::ConstantEntry
29
+ when ::RBS::Environment::ConstantEntry
32
30
  [entry.decl.comment]
33
- when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
34
- entry.decls.map {|d| d.decl.comment }
35
- when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
31
+ when ::RBS::Environment::ClassEntry, ::RBS::Environment::ModuleEntry
32
+ entry.each_decl.map do |decl|
33
+ case decl
34
+ when ::RBS::AST::Declarations::Base
35
+ decl.comment
36
+ when ::RBS::AST::Ruby::Declarations::Base
37
+ nil
38
+ end
39
+ end
40
+ when ::RBS::Environment::ClassAliasEntry, ::RBS::Environment::ModuleAliasEntry
36
41
  [entry.decl.comment]
37
42
  else
38
43
  raise
@@ -41,11 +46,11 @@ module Steep
41
46
 
42
47
  def decl
43
48
  case entry = env.constant_entry(full_name)
44
- when RBS::Environment::ConstantEntry
49
+ when ::RBS::Environment::ConstantEntry
45
50
  entry.decl
46
- when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
47
- entry.primary.decl
48
- when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
51
+ when ::RBS::Environment::ClassEntry, ::RBS::Environment::ModuleEntry
52
+ entry.primary_decl
53
+ when ::RBS::Environment::ClassAliasEntry, ::RBS::Environment::ModuleAliasEntry
49
54
  entry.decl
50
55
  else
51
56
  raise
@@ -65,7 +70,12 @@ module Steep
65
70
  # @implements SimpleMethodNameItem
66
71
 
67
72
  def comment
68
- method_member.comment
73
+ case method_member
74
+ when ::RBS::AST::Members::Base
75
+ method_member.comment
76
+ when ::RBS::AST::Ruby::Members::Base
77
+ nil
78
+ end
69
79
  end
70
80
  end
71
81
 
@@ -89,18 +99,20 @@ module Steep
89
99
 
90
100
  def defining_method_name(type_name, name, member)
91
101
  case member
92
- when RBS::AST::Members::MethodDefinition
102
+ when ::RBS::AST::Members::MethodDefinition
93
103
  if member.instance?
94
104
  InstanceMethodName.new(type_name: type_name, method_name: name)
95
105
  else
96
106
  SingletonMethodName.new(type_name: type_name, method_name: name)
97
107
  end
98
- when RBS::AST::Members::Attribute
108
+ when ::RBS::AST::Members::Attribute
99
109
  if member.kind == :instance
100
110
  InstanceMethodName.new(type_name: type_name, method_name: name)
101
111
  else
102
112
  SingletonMethodName.new(type_name: type_name, method_name: name)
103
113
  end
114
+ when ::RBS::AST::Ruby::Members::DefMember, ::RBS::AST::Ruby::Members::AttributeMember
115
+ InstanceMethodName.new(type_name: type_name, method_name: name)
104
116
  end
105
117
  end
106
118
  end
@@ -118,9 +130,9 @@ module Steep
118
130
  env.type_alias_decls.fetch(absolute_type_name).decl
119
131
  when absolute_type_name.class?
120
132
  case entry = env.module_class_entry(absolute_type_name)
121
- when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
122
- entry.primary.decl
123
- when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
133
+ when ::RBS::Environment::ClassEntry, ::RBS::Environment::ModuleEntry
134
+ entry.primary_decl
135
+ when ::RBS::Environment::ClassAliasEntry, ::RBS::Environment::ModuleAliasEntry
124
136
  entry.decl
125
137
  else
126
138
  raise "absolute_type_name=#{absolute_type_name}, relative_type_name=#{relative_type_name}"
@@ -144,13 +156,18 @@ module Steep
144
156
  end
145
157
  when absolute_type_name.class?
146
158
  case entry = env.module_class_entry(absolute_type_name)
147
- when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
148
- entry.decls.each do |decl|
149
- if comment = decl.decl.comment
150
- comments << comment
159
+ when ::RBS::Environment::ClassEntry, ::RBS::Environment::ModuleEntry
160
+ entry.each_decl do |decl|
161
+ case decl
162
+ when ::RBS::AST::Declarations::Base
163
+ if comment = decl.comment
164
+ comments << comment
165
+ end
166
+ when ::RBS::AST::Ruby::Declarations::Base
167
+ # noop
151
168
  end
152
169
  end
153
- when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
170
+ when ::RBS::Environment::ClassAliasEntry, ::RBS::Environment::ModuleAliasEntry
154
171
  if comment = entry.decl.comment
155
172
  comments << comment
156
173
  end
@@ -167,646 +184,6 @@ module Steep
167
184
 
168
185
  class TextItem < Struct.new(:text, :help_text, :range, :label, keyword_init: true)
169
186
  end
170
-
171
- attr_reader :source_text
172
- attr_reader :path
173
- attr_reader :subtyping
174
- attr_reader :modified_text
175
- attr_reader :source
176
- attr_reader :typing
177
-
178
- def initialize(source_text:, path:, subtyping:)
179
- @source_text = source_text
180
- @path = path
181
- @subtyping = subtyping
182
- end
183
-
184
- def type_check!(text, line:, column:)
185
- @modified_text = text
186
-
187
- Steep.measure "parsing" do
188
- @source = Source
189
- .parse(text, path: path, factory: subtyping.factory)
190
- .without_unrelated_defs(line: line, column: column)
191
- end
192
-
193
- Steep.measure "typechecking" do
194
- location = source.buffer.loc_to_pos([line, column])
195
- resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
196
- @typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: location)
197
- end
198
- end
199
-
200
- def env
201
- subtyping.factory.env
202
- end
203
-
204
- def run(line:, column:)
205
- source_text = self.source_text.dup
206
- index = index_for(source_text, line:line, column: column)
207
- possible_trigger = source_text[index-1]
208
-
209
- Steep.logger.debug "possible_trigger: #{possible_trigger.inspect}"
210
-
211
- position = Position.new(line: line, column: column)
212
-
213
- begin
214
- Steep.logger.tagged "completion_provider#run(line: #{line}, column: #{column})" do
215
- Steep.measure "type_check!" do
216
- type_check!(source_text, line: line, column: column)
217
- end
218
- end
219
-
220
- if comment = at_comment?(position)
221
- node, *parents = source.find_nodes(line: position.line, column: position.column)
222
-
223
- case
224
- when node&.type == :assertion
225
- # continue
226
- node or raise
227
- assertion = node.children[1] #: AST::Node::TypeAssertion
228
- return items_for_rbs(position: position, buffer: assertion.location.buffer)
229
-
230
- when node && parents && tapp_node = ([node] + parents).find {|n| n.type == :tapp }
231
- tapp = tapp_node.children[1] #: AST::Node::TypeApplication
232
- type_range = tapp.type_location.range
233
-
234
- if type_range.begin < index && index <= type_range.end
235
- return items_for_rbs(position: position, buffer: tapp.location.buffer)
236
- end
237
- else
238
- annotation = source.each_annotation.flat_map {|_, annots| annots }.find do |a|
239
- if a.location
240
- a.location.start_pos < index && index <= a.location.end_pos
241
- end
242
- end
243
-
244
- if annotation
245
- annotation.location or raise
246
- return items_for_rbs(position: position, buffer: annotation.location.buffer)
247
- end
248
-
249
- comment_content = comment.text[1..] || ""
250
- comment_content.strip!
251
-
252
- range = Range.new(
253
- start: Position.new(line: line, column: column),
254
- end: Position.new(line: line, column: column)
255
- )
256
-
257
- items = [
258
- TextItem.new(label: "steep:ignore:start", text: "steep:ignore:start", help_text: "Open ignore block", range: range),
259
- TextItem.new(label: "steep:ignore:end", text: "steep:ignore:end", help_text: "Close ignore block", range: range),
260
- TextItem.new(label: "steep:ignore", text: "steep:ignore ${1:optional diagnostics}", help_text: "Ignore line", range: range),
261
- TextItem.new(label: "@type var x: T", text: "@type var ${1:variable}: ${2:var type}", help_text: "Type of local variable", range: range),
262
- TextItem.new(label: "@type self: T", text: "@type self: ${1:self type}", help_text: "Type of `self`", range: range),
263
- TextItem.new(label: "@type block: T", text: "@type block: ${1:block type}", help_text: "Type of `block`", range: range),
264
- TextItem.new(label: "@type break: T", text: "@type break: ${1:break type}", help_text: "Type of `block`", range: range),
265
- ]
266
-
267
- items = items.filter_map do |item|
268
- if item.text.start_with?(comment_content)
269
- TextItem.new(
270
- label: item.label,
271
- text: item.text,
272
- help_text: item.help_text,
273
- range: Range.new(
274
- start: Position.new(line: item.range.start.line, column: item.range.start.column - comment_content.size),
275
- end: item.range.end
276
- )
277
- )
278
- end
279
- end
280
-
281
- return items
282
- end
283
- end
284
-
285
- Steep.measure "completion item collection" do
286
- items_for_trigger(position: position)
287
- end
288
-
289
- rescue Parser::SyntaxError => exn
290
- Steep.logger.info "recovering syntax error: #{exn.inspect}"
291
-
292
- @source_text = source_text.dup
293
-
294
- case possible_trigger
295
- when "."
296
- if source_text[index-2] == "&"
297
- source_text[index-1] = " "
298
- source_text[index-2] = " "
299
- type_check!(source_text, line: line, column: column)
300
- items_for_qcall(position: position)
301
- else
302
- source_text[index-1] = " "
303
- type_check!(source_text, line: line, column: column)
304
- items_for_dot(position: position)
305
- end
306
- when "@"
307
- source_text[index-1] = " "
308
- type_check!(source_text, line: line, column: column)
309
- items_for_atmark(position: position)
310
- when ":"
311
- if source_text[index-2] == ":"
312
- source_text[index-1] = " "
313
- source_text[index-2] = " "
314
- type_check!(source_text, line: line, column: column)
315
- items_for_colon2(position: position)
316
- else
317
- []
318
- end
319
- else
320
- items = [] #: Array[item]
321
- items_for_following_keyword_arguments(source_text, index: index, line: line, column: column, items: items)
322
- items
323
- end
324
- end
325
- end
326
-
327
- def range_from_loc(loc)
328
- Range.new(
329
- start: Position.new(line: loc.line, column: loc.column),
330
- end: Position.new(line: loc.last_line, column: loc.last_line)
331
- )
332
- end
333
-
334
- def at_end?(pos, of:)
335
- if of
336
- of.last_line == pos.line && of.last_column == pos.column
337
- end
338
- end
339
-
340
- def at_comment?(position)
341
- source.find_comment(line: position.line, column: position.column)
342
- end
343
-
344
- def range_for(position, prefix: "")
345
- if prefix.empty?
346
- Range.new(start: position, end: position)
347
- else
348
- Range.new(start: position - prefix.size, end: position)
349
- end
350
- end
351
-
352
- def items_for_trigger(position:)
353
- node, *parents = source.find_nodes(line: position.line, column: position.column)
354
- node ||= source.node
355
-
356
- return [] unless node && parents
357
-
358
- items = [] #: Array[item]
359
-
360
- context = typing.cursor_context.context or raise
361
-
362
- case
363
- when node.type == :send && node.children[0] == nil && at_end?(position, of: (_ = node.loc).selector)
364
- # foo ←
365
- prefix = node.children[1].to_s
366
-
367
- method_items_for_receiver_type(context.self_type, include_private: true, prefix: prefix, position: position, items: items)
368
- local_variable_items_for_context(context, position: position, prefix: prefix, items: items)
369
-
370
- if (send_node, block_node = deconstruct_sendish_and_block_nodes(*parents))
371
- keyword_argument_items_for_method(
372
- call_node: block_node || send_node,
373
- send_node: send_node,
374
- position: position,
375
- prefix: prefix,
376
- items: items
377
- )
378
- end
379
-
380
- when node.type == :lvar && at_end?(position, of: node.loc)
381
- # foo ← (lvar)
382
- local_variable_items_for_context(context, position: position, prefix: node.children[0].to_s, items: items)
383
-
384
- when node.type == :send && node.children[0] && at_end?(position, of: (_ = node.loc).selector)
385
- # foo.ba ←
386
- receiver_type =
387
- case (type = typing.type_of(node: node.children[0]))
388
- when AST::Types::Self
389
- context.self_type
390
- else
391
- type
392
- end
393
- prefix = node.children[1].to_s
394
-
395
- method_items_for_receiver_type(receiver_type, include_private: false, prefix: prefix, position: position, items: items)
396
-
397
- when node.type == :csend && node.children[0] && at_end?(position, of: (_ = node.loc).selector)
398
- # foo&.ba ←
399
- receiver_type =
400
- case (type = typing.type_of(node: node.children[0]))
401
- when AST::Types::Self
402
- context.self_type
403
- else
404
- unwrap_optional(type)
405
- end
406
- prefix = node.children[1].to_s
407
-
408
- method_items_for_receiver_type(receiver_type, include_private: false, prefix: prefix, position: position, items: items)
409
-
410
- when node.type == :const && node.children[0] == nil && at_end?(position, of: node.loc)
411
- # Foo ← (const)
412
- prefix = node.children[1].to_s
413
-
414
- method_items_for_receiver_type(context.self_type, include_private: false, prefix: prefix, position: position, items: items)
415
- constant_items_for_context(context, prefix: prefix, position: position, items: items)
416
-
417
- when node.type == :const && node.children[0] && at_end?(position, of: node.loc)
418
- # Foo::Ba ← (const)
419
- parent_node = node.children[0]
420
- parent_type = typing.type_of(node: parent_node)
421
-
422
- if parent_type
423
- prefix = node.children[1].to_s
424
-
425
- method_items_for_receiver_type(parent_type, include_private: false, prefix: prefix, position: position, items: items)
426
- constant_items_for_context(context, parent: parent_node, prefix: prefix, position: position, items: items)
427
- end
428
-
429
- when node.type == :send && at_end?(position, of: (_ = node.loc).dot) && (_ = node.loc).dot.source == "."
430
- # foo.← ba
431
- receiver_type =
432
- case (type = typing.type_of(node: node.children[0]))
433
- when AST::Types::Self
434
- context.self_type
435
- else
436
- type
437
- end
438
-
439
- method_items_for_receiver_type(receiver_type, include_private: false, prefix: "", position: position, items: items)
440
-
441
- when node.type == :send && at_end?(position, of: (_ = node.loc).dot) && (_ = node.loc).dot.source == "::"
442
- # foo::← ba
443
- items.push(*items_for_colon2(position: position))
444
-
445
- when node.type == :csend && at_end?(position, of: (_ = node.loc).dot)
446
- # foo&.← ba
447
- receiver_type =
448
- case (type = typing.type_of(node: node.children[0]))
449
- when AST::Types::Self
450
- context.self_type
451
- else
452
- unwrap_optional(type)
453
- end
454
-
455
- method_items_for_receiver_type(receiver_type, include_private: false, prefix: "", position: position, items: items)
456
-
457
- when node.type == :ivar && at_end?(position, of: node.loc)
458
- # @fo ←
459
- instance_variable_items_for_context(context, position: position, prefix: node.children[0].to_s, items: items)
460
-
461
- else
462
- method_items_for_receiver_type(context.self_type, include_private: true, prefix: "", position: position, items: items)
463
- local_variable_items_for_context(context, position: position, prefix: "", items: items)
464
- instance_variable_items_for_context(context, position: position, prefix: "", items: items)
465
- constant_items_for_context(context, position: position, prefix: "", items: items)
466
- end
467
-
468
- items
469
- end
470
-
471
- def items_for_dot(position:)
472
- # foo. ←
473
- shift_pos = position-1
474
- node, *_parents = source.find_nodes(line: shift_pos.line, column: shift_pos.column)
475
- node ||= source.node
476
-
477
- return [] unless node
478
-
479
- if at_end?(shift_pos, of: node.loc)
480
- begin
481
- context = typing.cursor_context.context or raise
482
- receiver_type =
483
- case (type = typing.type_of(node: node))
484
- when AST::Types::Self
485
- context.self_type
486
- else
487
- type
488
- end
489
-
490
- items = [] #: Array[item]
491
- method_items_for_receiver_type(receiver_type, include_private: false, prefix: "", position: position, items: items)
492
- items
493
- rescue Typing::UnknownNodeError
494
- []
495
- end
496
- else
497
- []
498
- end
499
- end
500
-
501
- def items_for_qcall(position:)
502
- # foo&. ←
503
- shift_pos = position-2
504
- node, *_parents = source.find_nodes(line: shift_pos.line, column: shift_pos.column)
505
- node ||= source.node
506
-
507
- return [] unless node
508
-
509
- if at_end?(shift_pos, of: node.loc)
510
- begin
511
- context = typing.cursor_context.context or raise
512
- receiver_type =
513
- case (type = typing.type_of(node: node))
514
- when AST::Types::Self
515
- context.self_type
516
- else
517
- unwrap_optional(type)
518
- end
519
-
520
- items = [] #: Array[item]
521
- method_items_for_receiver_type(receiver_type, include_private: false, prefix: "", position: position, items: items)
522
- items
523
- rescue Typing::UnknownNodeError
524
- []
525
- end
526
- else
527
- []
528
- end
529
- end
530
-
531
- def items_for_colon2(position:)
532
- # :: ←
533
- shift_pos = position-2
534
- node, *_ = source.find_nodes(line: shift_pos.line, column: shift_pos.column)
535
- node ||= source.node
536
-
537
- items = [] #: Array[item]
538
- case node&.type
539
- when :const
540
- # Constant:: ←
541
- context = typing.cursor_context.context or raise
542
- constant_items_for_context(context, parent: node, position: position, items: items, prefix: "")
543
- when nil
544
- # :: ←
545
- context = typing.cursor_context.context or raise
546
- constant_items_for_context(context, parent: nil, position: position, items: items, prefix: "")
547
- end
548
-
549
- if node
550
- items.push(*items_for_dot(position: position - 1))
551
- end
552
-
553
- items
554
- end
555
-
556
- def items_for_atmark(position:)
557
- # @ ←
558
- shift_pos = position-1
559
- node, *_ = source.find_nodes(line: shift_pos.line, column: shift_pos.column)
560
- node ||= source.node
561
-
562
- return [] unless node
563
-
564
- context = typing.cursor_context.context or raise
565
- items = [] #: Array[item]
566
- instance_variable_items_for_context(context, prefix: "@", position: position, items: items)
567
- items
568
- end
569
-
570
- def items_for_rbs(position:, buffer:)
571
- items = [] #: Array[item]
572
-
573
- context = typing.cursor_context.context or raise
574
- completion = TypeNameCompletion.new(env: context.env, context: context.module_context.nesting, dirs: [])
575
- prefix = TypeNameCompletion::Prefix.parse(buffer, line: position.line, column: position.column)
576
-
577
- size = prefix&.size || 0
578
- range = Range.new(start: position - size, end: position)
579
-
580
- completion.find_type_names(prefix).each do |name|
581
- absolute, relative = completion.resolve_name_in_context(name)
582
- items << TypeNameItem.new(relative_type_name: relative, absolute_type_name: absolute, env: context.env, range: range)
583
- end
584
-
585
- items
586
- end
587
-
588
- def items_for_following_keyword_arguments(text, index:, line:, column:, items:)
589
- return if text[index - 1] !~ /[a-zA-Z0-9]/
590
-
591
- text = text.dup
592
- argname = [] #: Array[String]
593
- while text[index - 1] =~ /[a-zA-Z0-9]/
594
- argname.unshift(text[index - 1] || '')
595
- source_text[index - 1] = " "
596
- index -= 1
597
- end
598
-
599
- begin
600
- type_check!(source_text, line: line, column: column)
601
- rescue Parser::SyntaxError
602
- return
603
- end
604
-
605
- if nodes = source.find_nodes(line: line, column: column)
606
- if (send_node, block_node = deconstruct_sendish_and_block_nodes(*nodes))
607
- position = Position.new(line: line, column: column)
608
- keyword_argument_items_for_method(
609
- call_node: block_node || send_node,
610
- send_node: send_node,
611
- position: position,
612
- prefix: argname.join,
613
- items: items
614
- )
615
- end
616
- end
617
- end
618
-
619
- def method_items_for_receiver_type(type, include_private:, prefix:, position:, items:)
620
- range = range_for(position, prefix: prefix)
621
- context = typing.cursor_context.context or raise
622
-
623
- config =
624
- if (module_type = context.module_context&.module_type) && (instance_type = context.module_context&.instance_type)
625
- Interface::Builder::Config.new(
626
- self_type: context.self_type,
627
- class_type: module_type,
628
- instance_type: instance_type,
629
- variable_bounds: context.variable_context.upper_bounds
630
- )
631
- else
632
- Interface::Builder::Config.new(self_type: context.self_type, variable_bounds: context.variable_context.upper_bounds)
633
- end
634
-
635
- if shape = subtyping.builder.shape(type, config)
636
- shape = shape.public_shape unless include_private
637
-
638
- shape.methods.each do |name, method_entry|
639
- next if disallowed_method?(name)
640
-
641
- if name.to_s.start_with?(prefix)
642
- if word_name?(name.to_s)
643
- case type
644
- when AST::Types::Name::Instance, AST::Types::Name::Interface, AST::Types::Name::Singleton
645
- # Simple method type
646
- all_decls = Set.new(method_entry.overloads.flat_map {|overload| overload.method_decls(name) }).sort_by {|decl| decl.method_name.to_s }
647
- all_members = Set.new(all_decls.flat_map {|decl| decl.method_def.member })
648
- all_members.each do |member|
649
- associated_decl = all_decls.find {|decl| decl.method_def.member == member } or next
650
- overloads = method_entry.overloads.select {|overload| overload.method_defs.any? {|defn| defn.member == member }}
651
- annotations = associated_decl.method_def.member_annotations
652
- items << SimpleMethodNameItem.new(
653
- identifier: name,
654
- range: range,
655
- receiver_type: type,
656
- method_name: associated_decl.method_name,
657
- method_types: overloads.map {|overload| subtyping.factory.method_type_1(overload.method_type) },
658
- method_member: member,
659
- deprecated: AnnotationsHelper.deprecated_annotation?(annotations) ? true : false
660
- )
661
- end
662
- else
663
- generated_overloads, defined_overloads =
664
- method_entry.overloads.partition {|overload| overload.method_defs.empty? }
665
-
666
- unless defined_overloads.empty?
667
- items << ComplexMethodNameItem.new(
668
- identifier: name,
669
- range: range,
670
- receiver_type: type,
671
- method_types: defined_overloads.map { subtyping.factory.method_type_1(_1.method_type) },
672
- method_decls: defined_overloads.flat_map { _1.method_decls(name).to_a }.sort_by {|decl| decl.method_name.to_s }
673
- )
674
- end
675
-
676
- unless generated_overloads.empty?
677
- items << GeneratedMethodNameItem.new(
678
- identifier: name,
679
- range: range,
680
- receiver_type: type,
681
- method_types: generated_overloads.map { subtyping.factory.method_type_1(_1.method_type) }
682
- )
683
- end
684
- end
685
- end
686
- end
687
- end
688
- end
689
- end
690
-
691
- def word_name?(name)
692
- name =~ /\w/ ? true : false
693
- end
694
-
695
- def local_variable_items_for_context(context, position:, prefix:, items:)
696
- range = range_for(position, prefix: prefix)
697
- context.type_env.local_variable_types.each do |name, pair|
698
- type, _ = pair
699
-
700
- if name.to_s.start_with?(prefix)
701
- items << LocalVariableItem.new(identifier: name, range: range, type: type)
702
- end
703
- end
704
- end
705
-
706
- def constant_items_for_context(context, parent: nil, position:, prefix:, items:)
707
- range = range_for(position, prefix: prefix)
708
-
709
- if parent
710
- case parent.type
711
- when :const
712
- const_name = typing.source_index.reference(constant_node: parent) or raise "Unknown node in source_index: #{parent}"
713
- consts = context.type_env.constant_env.children(const_name)
714
- end
715
- else
716
- consts = context.type_env.constant_env.constants
717
- end
718
-
719
- if consts
720
- consts.each do |name, tuple|
721
- type, full_name, _ = tuple
722
-
723
- if name.to_s.start_with?(prefix)
724
- items << ConstantItem.new(env: env, identifier: name, range: range, type: type, full_name: full_name)
725
- end
726
- end
727
- end
728
- end
729
-
730
- def instance_variable_items_for_context(context, position:, prefix:, items:)
731
- range = range_for(position, prefix: prefix)
732
- context.type_env.instance_variable_types.each do |name, type|
733
- if name.to_s.start_with?(prefix)
734
- items << InstanceVariableItem.new(identifier: name, range: range, type: type)
735
- end
736
- end
737
- end
738
-
739
- def keyword_argument_items_for_method(call_node:, send_node:, position:, prefix:, items:)
740
- _receiver_node, _method_name, argument_nodes = deconstruct_send_node!(send_node)
741
-
742
- call = typing.call_of(node: call_node)
743
-
744
- case call
745
- when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
746
- context = typing.cursor_context.context or raise
747
- type = call.receiver_type
748
- 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))
749
-
750
- config = Interface::Builder::Config.new(self_type: type, variable_bounds: context.variable_context.upper_bounds)
751
- if shape = subtyping.builder.shape(type, config)
752
- shape = shape.public_shape if private_send?(call_node)
753
- if method = shape.methods[call.method_name]
754
- method.overloads.each.with_index do |overload, i|
755
- defn = overload.method_decls(call.method_name).to_a[0]&.method_def
756
- if defn && defn.type.type
757
- range = range_for(position, prefix: prefix)
758
- kwargs = argument_nodes.find { |arg| arg.type == :kwargs }&.children || []
759
- used_kwargs = kwargs.filter_map { |arg| arg.type == :pair && arg.children.first.children.first }
760
-
761
- if defn.type.type.is_a?(RBS::Types::UntypedFunction)
762
- kwargs = [] #: Array[Symbol]
763
- else
764
- kwargs = defn.type.type.required_keywords.keys + defn.type.type.optional_keywords.keys
765
- end
766
-
767
- kwargs.each do |name|
768
- if name.to_s.start_with?(prefix) && !used_kwargs.include?(name)
769
- items << KeywordArgumentItem.new(identifier: "#{name}:", range: range)
770
- end
771
- end
772
- end
773
- end
774
- end
775
- end
776
- end
777
- end
778
-
779
-
780
- def index_for(string, line:, column:)
781
- index = 0
782
-
783
- string.each_line.with_index do |s, i|
784
- if i+1 == line
785
- index += column
786
- break
787
- else
788
- index += s.size
789
- end
790
- end
791
-
792
- index
793
- end
794
-
795
- def disallowed_method?(name)
796
- # initialize isn't invoked by developers when creating
797
- # instances of new classes, so don't show it as
798
- # an LSP option
799
- name == :initialize
800
- end
801
-
802
- def unwrap_optional(type)
803
- if type.is_a?(AST::Types::Union) && type.types.include?(AST::Builtin.nil_type)
804
- types = type.types.reject { |t| t == AST::Builtin.nil_type }
805
- AST::Types::Union.new(types: types)
806
- else
807
- type
808
- end
809
- end
810
187
  end
811
188
  end
812
189
  end