ruby-lsp 0.27.0.beta2 → 0.27.0.beta3

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp +0 -46
  4. data/exe/ruby-lsp-check +0 -15
  5. data/lib/ruby_lsp/global_state.rb +0 -5
  6. data/lib/ruby_lsp/internal.rb +2 -1
  7. data/lib/ruby_lsp/listeners/code_lens.rb +1 -1
  8. data/lib/ruby_lsp/listeners/completion.rb +246 -382
  9. data/lib/ruby_lsp/listeners/definition.rb +6 -9
  10. data/lib/ruby_lsp/listeners/hover.rb +11 -9
  11. data/lib/ruby_lsp/listeners/signature_help.rb +11 -12
  12. data/lib/ruby_lsp/listeners/test_discovery.rb +17 -1
  13. data/lib/ruby_lsp/listeners/test_style.rb +1 -1
  14. data/lib/ruby_lsp/requests/completion_resolve.rb +49 -29
  15. data/lib/ruby_lsp/requests/references.rb +21 -7
  16. data/lib/ruby_lsp/requests/rename.rb +1 -1
  17. data/lib/ruby_lsp/requests/support/common.rb +69 -68
  18. data/lib/ruby_lsp/ruby_document.rb +0 -73
  19. data/lib/ruby_lsp/rubydex/declaration.rb +128 -2
  20. data/lib/ruby_lsp/rubydex/definition.rb +16 -0
  21. data/lib/ruby_lsp/rubydex/signature.rb +107 -0
  22. data/lib/ruby_lsp/scripts/compose_bundle.rb +1 -1
  23. data/lib/ruby_lsp/server.rb +7 -162
  24. data/lib/ruby_lsp/test_helper.rb +0 -1
  25. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +1 -1
  26. data/lib/ruby_lsp/type_inferrer.rb +2 -2
  27. metadata +11 -14
  28. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +0 -276
  29. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +0 -1101
  30. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +0 -44
  31. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +0 -605
  32. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +0 -1077
  33. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +0 -37
  34. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +0 -149
  35. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +0 -294
  36. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +0 -32
  37. data/lib/ruby_indexer/ruby_indexer.rb +0 -19
  38. /data/lib/{ruby_indexer/lib/ruby_indexer → ruby_lsp}/uri.rb +0 -0
@@ -1,1101 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module RubyIndexer
5
- class DeclarationListener
6
- OBJECT_NESTING = ["Object"].freeze #: Array[String]
7
- BASIC_OBJECT_NESTING = ["BasicObject"].freeze #: Array[String]
8
-
9
- #: Array[String]
10
- attr_reader :indexing_errors
11
-
12
- #: (Index index, Prism::Dispatcher dispatcher, Prism::ParseLexResult | Prism::ParseResult parse_result, URI::Generic uri, ?collect_comments: bool) -> void
13
- def initialize(index, dispatcher, parse_result, uri, collect_comments: false)
14
- @index = index
15
- @uri = uri
16
- @enhancements = Enhancement.all(self) #: Array[Enhancement]
17
- @visibility_stack = [VisibilityScope.public_scope] #: Array[VisibilityScope]
18
- @comments_by_line = parse_result.comments.to_h do |c|
19
- [c.location.start_line, c]
20
- end #: Hash[Integer, Prism::Comment]
21
- @inside_def = false #: bool
22
- @code_units_cache = parse_result
23
- .code_units_cache(@index.configuration.encoding) #: (^(Integer arg0) -> Integer | Prism::CodeUnitsCache)
24
-
25
- @source_lines = parse_result.source.lines #: Array[String]
26
-
27
- # The nesting stack we're currently inside. Used to determine the fully qualified name of constants, but only
28
- # stored by unresolved aliases which need the original nesting to be lazily resolved
29
- @stack = [] #: Array[String]
30
-
31
- # A stack of namespace entries that represent where we currently are. Used to properly assign methods to an owner
32
- @owner_stack = [] #: Array[Entry::Namespace]
33
- @indexing_errors = [] #: Array[String]
34
- @collect_comments = collect_comments
35
-
36
- dispatcher.register(
37
- self,
38
- :on_class_node_enter,
39
- :on_class_node_leave,
40
- :on_module_node_enter,
41
- :on_module_node_leave,
42
- :on_singleton_class_node_enter,
43
- :on_singleton_class_node_leave,
44
- :on_def_node_enter,
45
- :on_def_node_leave,
46
- :on_call_node_enter,
47
- :on_call_node_leave,
48
- :on_multi_write_node_enter,
49
- :on_constant_path_write_node_enter,
50
- :on_constant_path_or_write_node_enter,
51
- :on_constant_path_operator_write_node_enter,
52
- :on_constant_path_and_write_node_enter,
53
- :on_constant_write_node_enter,
54
- :on_constant_or_write_node_enter,
55
- :on_constant_and_write_node_enter,
56
- :on_constant_operator_write_node_enter,
57
- :on_global_variable_and_write_node_enter,
58
- :on_global_variable_operator_write_node_enter,
59
- :on_global_variable_or_write_node_enter,
60
- :on_global_variable_target_node_enter,
61
- :on_global_variable_write_node_enter,
62
- :on_instance_variable_write_node_enter,
63
- :on_instance_variable_and_write_node_enter,
64
- :on_instance_variable_operator_write_node_enter,
65
- :on_instance_variable_or_write_node_enter,
66
- :on_instance_variable_target_node_enter,
67
- :on_alias_method_node_enter,
68
- :on_class_variable_and_write_node_enter,
69
- :on_class_variable_operator_write_node_enter,
70
- :on_class_variable_or_write_node_enter,
71
- :on_class_variable_target_node_enter,
72
- :on_class_variable_write_node_enter,
73
- )
74
- end
75
-
76
- #: (Prism::ClassNode node) -> void
77
- def on_class_node_enter(node)
78
- constant_path = node.constant_path
79
- superclass = node.superclass
80
- nesting = Index.actual_nesting(@stack, constant_path.slice)
81
-
82
- parent_class = case superclass
83
- when Prism::ConstantReadNode, Prism::ConstantPathNode
84
- superclass.slice
85
- else
86
- case nesting
87
- when OBJECT_NESTING
88
- # When Object is reopened, its parent class should still be the top-level BasicObject
89
- "::BasicObject"
90
- when BASIC_OBJECT_NESTING
91
- # When BasicObject is reopened, its parent class should still be nil
92
- nil
93
- else
94
- # Otherwise, the parent class should be the top-level Object
95
- "::Object"
96
- end
97
- end
98
-
99
- add_class(
100
- nesting,
101
- node.location,
102
- constant_path.location,
103
- parent_class_name: parent_class,
104
- comments: collect_comments(node),
105
- )
106
- end
107
-
108
- #: (Prism::ClassNode node) -> void
109
- def on_class_node_leave(node)
110
- pop_namespace_stack
111
- end
112
-
113
- #: (Prism::ModuleNode node) -> void
114
- def on_module_node_enter(node)
115
- constant_path = node.constant_path
116
- add_module(constant_path.slice, node.location, constant_path.location, comments: collect_comments(node))
117
- end
118
-
119
- #: (Prism::ModuleNode node) -> void
120
- def on_module_node_leave(node)
121
- pop_namespace_stack
122
- end
123
-
124
- #: (Prism::SingletonClassNode node) -> void
125
- def on_singleton_class_node_enter(node)
126
- @visibility_stack.push(VisibilityScope.public_scope)
127
-
128
- current_owner = @owner_stack.last
129
-
130
- if current_owner
131
- expression = node.expression
132
- name = (expression.is_a?(Prism::SelfNode) ? "<#{last_name_in_stack}>" : "<#{expression.slice}>")
133
- real_nesting = Index.actual_nesting(@stack, name)
134
-
135
- existing_entries = @index[real_nesting.join("::")] #: as Array[Entry::SingletonClass]?
136
-
137
- if existing_entries
138
- entry = existing_entries.first #: as !nil
139
- entry.update_singleton_information(
140
- Location.from_prism_location(node.location, @code_units_cache),
141
- Location.from_prism_location(expression.location, @code_units_cache),
142
- collect_comments(node),
143
- )
144
- else
145
- entry = Entry::SingletonClass.new(
146
- @index.configuration,
147
- real_nesting,
148
- @uri,
149
- Location.from_prism_location(node.location, @code_units_cache),
150
- Location.from_prism_location(expression.location, @code_units_cache),
151
- collect_comments(node),
152
- nil,
153
- )
154
- @index.add(entry, skip_prefix_tree: true)
155
- end
156
-
157
- @owner_stack << entry
158
- @stack << name
159
- end
160
- end
161
-
162
- #: (Prism::SingletonClassNode node) -> void
163
- def on_singleton_class_node_leave(node)
164
- pop_namespace_stack
165
- end
166
-
167
- #: (Prism::MultiWriteNode node) -> void
168
- def on_multi_write_node_enter(node)
169
- value = node.value
170
- values = value.is_a?(Prism::ArrayNode) && value.opening_loc ? value.elements : []
171
-
172
- [*node.lefts, *node.rest, *node.rights].each_with_index do |target, i|
173
- current_value = values[i]
174
- # The moment we find a splat on the right hand side of the assignment, we can no longer figure out which value
175
- # gets assigned to what
176
- values.clear if current_value.is_a?(Prism::SplatNode)
177
-
178
- case target
179
- when Prism::ConstantTargetNode
180
- add_constant(target, fully_qualify_name(target.name.to_s), current_value)
181
- when Prism::ConstantPathTargetNode
182
- add_constant(target, fully_qualify_name(target.slice), current_value)
183
- end
184
- end
185
- end
186
-
187
- #: (Prism::ConstantPathWriteNode node) -> void
188
- def on_constant_path_write_node_enter(node)
189
- # ignore variable constants like `var::FOO` or `self.class::FOO`
190
- target = node.target
191
- return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
192
-
193
- name = fully_qualify_name(target.location.slice)
194
- add_constant(node, name)
195
- end
196
-
197
- #: (Prism::ConstantPathOrWriteNode node) -> void
198
- def on_constant_path_or_write_node_enter(node)
199
- # ignore variable constants like `var::FOO` or `self.class::FOO`
200
- target = node.target
201
- return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
202
-
203
- name = fully_qualify_name(target.location.slice)
204
- add_constant(node, name)
205
- end
206
-
207
- #: (Prism::ConstantPathOperatorWriteNode node) -> void
208
- def on_constant_path_operator_write_node_enter(node)
209
- # ignore variable constants like `var::FOO` or `self.class::FOO`
210
- target = node.target
211
- return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
212
-
213
- name = fully_qualify_name(target.location.slice)
214
- add_constant(node, name)
215
- end
216
-
217
- #: (Prism::ConstantPathAndWriteNode node) -> void
218
- def on_constant_path_and_write_node_enter(node)
219
- # ignore variable constants like `var::FOO` or `self.class::FOO`
220
- target = node.target
221
- return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
222
-
223
- name = fully_qualify_name(target.location.slice)
224
- add_constant(node, name)
225
- end
226
-
227
- #: (Prism::ConstantWriteNode node) -> void
228
- def on_constant_write_node_enter(node)
229
- name = fully_qualify_name(node.name.to_s)
230
- add_constant(node, name)
231
- end
232
-
233
- #: (Prism::ConstantOrWriteNode node) -> void
234
- def on_constant_or_write_node_enter(node)
235
- name = fully_qualify_name(node.name.to_s)
236
- add_constant(node, name)
237
- end
238
-
239
- #: (Prism::ConstantAndWriteNode node) -> void
240
- def on_constant_and_write_node_enter(node)
241
- name = fully_qualify_name(node.name.to_s)
242
- add_constant(node, name)
243
- end
244
-
245
- #: (Prism::ConstantOperatorWriteNode node) -> void
246
- def on_constant_operator_write_node_enter(node)
247
- name = fully_qualify_name(node.name.to_s)
248
- add_constant(node, name)
249
- end
250
-
251
- #: (Prism::CallNode node) -> void
252
- def on_call_node_enter(node)
253
- message = node.name
254
-
255
- case message
256
- when :private_constant
257
- handle_private_constant(node)
258
- when :attr_reader
259
- handle_attribute(node, reader: true, writer: false)
260
- when :attr_writer
261
- handle_attribute(node, reader: false, writer: true)
262
- when :attr_accessor
263
- handle_attribute(node, reader: true, writer: true)
264
- when :attr
265
- has_writer = node.arguments&.arguments&.last&.is_a?(Prism::TrueNode) || false
266
- handle_attribute(node, reader: true, writer: has_writer)
267
- when :alias_method
268
- handle_alias_method(node)
269
- when :include, :prepend, :extend
270
- handle_module_operation(node, message)
271
- when :public
272
- handle_visibility_change(node, :public)
273
- when :protected
274
- handle_visibility_change(node, :protected)
275
- when :private
276
- handle_visibility_change(node, :private)
277
- when :module_function
278
- handle_module_function(node)
279
- when :private_class_method
280
- handle_private_class_method(node)
281
- end
282
-
283
- @enhancements.each do |enhancement|
284
- enhancement.on_call_node_enter(node)
285
- rescue StandardError => e
286
- @indexing_errors << <<~MSG
287
- Indexing error in #{@uri} with '#{enhancement.class.name}' on call node enter enhancement: #{e.message}
288
- MSG
289
- end
290
- end
291
-
292
- #: (Prism::CallNode node) -> void
293
- def on_call_node_leave(node)
294
- message = node.name
295
- case message
296
- when :public, :protected, :private, :private_class_method
297
- # We want to restore the visibility stack when we leave a method definition with a visibility modifier
298
- # e.g. `private def foo; end`
299
- if node.arguments&.arguments&.first&.is_a?(Prism::DefNode)
300
- @visibility_stack.pop
301
- end
302
- end
303
-
304
- @enhancements.each do |enhancement|
305
- enhancement.on_call_node_leave(node)
306
- rescue StandardError => e
307
- @indexing_errors << <<~MSG
308
- Indexing error in #{@uri} with '#{enhancement.class.name}' on call node leave enhancement: #{e.message}
309
- MSG
310
- end
311
- end
312
-
313
- #: (Prism::DefNode node) -> void
314
- def on_def_node_enter(node)
315
- owner = @owner_stack.last
316
- return unless owner
317
-
318
- @inside_def = true
319
- method_name = node.name.to_s
320
- comments = collect_comments(node)
321
- scope = current_visibility_scope
322
-
323
- case node.receiver
324
- when nil
325
- location = Location.from_prism_location(node.location, @code_units_cache)
326
- name_location = Location.from_prism_location(node.name_loc, @code_units_cache)
327
- signatures = [Entry::Signature.new(list_params(node.parameters))]
328
-
329
- @index.add(Entry::Method.new(
330
- @index.configuration,
331
- method_name,
332
- @uri,
333
- location,
334
- name_location,
335
- comments,
336
- signatures,
337
- scope.visibility,
338
- owner,
339
- ))
340
-
341
- if scope.module_func
342
- singleton = @index.existing_or_new_singleton_class(owner.name)
343
-
344
- @index.add(Entry::Method.new(
345
- @index.configuration,
346
- method_name,
347
- @uri,
348
- location,
349
- name_location,
350
- comments,
351
- signatures,
352
- :public,
353
- singleton,
354
- ))
355
- end
356
- when Prism::SelfNode
357
- singleton = @index.existing_or_new_singleton_class(owner.name)
358
-
359
- @index.add(Entry::Method.new(
360
- @index.configuration,
361
- method_name,
362
- @uri,
363
- Location.from_prism_location(node.location, @code_units_cache),
364
- Location.from_prism_location(node.name_loc, @code_units_cache),
365
- comments,
366
- [Entry::Signature.new(list_params(node.parameters))],
367
- scope.visibility,
368
- singleton,
369
- ))
370
-
371
- @owner_stack << singleton
372
- end
373
- end
374
-
375
- #: (Prism::DefNode node) -> void
376
- def on_def_node_leave(node)
377
- @inside_def = false
378
-
379
- if node.receiver.is_a?(Prism::SelfNode)
380
- @owner_stack.pop
381
- end
382
- end
383
-
384
- #: (Prism::GlobalVariableAndWriteNode node) -> void
385
- def on_global_variable_and_write_node_enter(node)
386
- handle_global_variable(node, node.name_loc)
387
- end
388
-
389
- #: (Prism::GlobalVariableOperatorWriteNode node) -> void
390
- def on_global_variable_operator_write_node_enter(node)
391
- handle_global_variable(node, node.name_loc)
392
- end
393
-
394
- #: (Prism::GlobalVariableOrWriteNode node) -> void
395
- def on_global_variable_or_write_node_enter(node)
396
- handle_global_variable(node, node.name_loc)
397
- end
398
-
399
- #: (Prism::GlobalVariableTargetNode node) -> void
400
- def on_global_variable_target_node_enter(node)
401
- handle_global_variable(node, node.location)
402
- end
403
-
404
- #: (Prism::GlobalVariableWriteNode node) -> void
405
- def on_global_variable_write_node_enter(node)
406
- handle_global_variable(node, node.name_loc)
407
- end
408
-
409
- #: (Prism::InstanceVariableWriteNode node) -> void
410
- def on_instance_variable_write_node_enter(node)
411
- handle_instance_variable(node, node.name_loc)
412
- end
413
-
414
- #: (Prism::InstanceVariableAndWriteNode node) -> void
415
- def on_instance_variable_and_write_node_enter(node)
416
- handle_instance_variable(node, node.name_loc)
417
- end
418
-
419
- #: (Prism::InstanceVariableOperatorWriteNode node) -> void
420
- def on_instance_variable_operator_write_node_enter(node)
421
- handle_instance_variable(node, node.name_loc)
422
- end
423
-
424
- #: (Prism::InstanceVariableOrWriteNode node) -> void
425
- def on_instance_variable_or_write_node_enter(node)
426
- handle_instance_variable(node, node.name_loc)
427
- end
428
-
429
- #: (Prism::InstanceVariableTargetNode node) -> void
430
- def on_instance_variable_target_node_enter(node)
431
- handle_instance_variable(node, node.location)
432
- end
433
-
434
- #: (Prism::AliasMethodNode node) -> void
435
- def on_alias_method_node_enter(node)
436
- method_name = node.new_name.slice
437
- comments = collect_comments(node)
438
- @index.add(
439
- Entry::UnresolvedMethodAlias.new(
440
- @index.configuration,
441
- method_name,
442
- node.old_name.slice,
443
- @owner_stack.last,
444
- @uri,
445
- Location.from_prism_location(node.new_name.location, @code_units_cache),
446
- comments,
447
- ),
448
- )
449
- end
450
-
451
- #: (Prism::ClassVariableAndWriteNode node) -> void
452
- def on_class_variable_and_write_node_enter(node)
453
- handle_class_variable(node, node.name_loc)
454
- end
455
-
456
- #: (Prism::ClassVariableOperatorWriteNode node) -> void
457
- def on_class_variable_operator_write_node_enter(node)
458
- handle_class_variable(node, node.name_loc)
459
- end
460
-
461
- #: (Prism::ClassVariableOrWriteNode node) -> void
462
- def on_class_variable_or_write_node_enter(node)
463
- handle_class_variable(node, node.name_loc)
464
- end
465
-
466
- #: (Prism::ClassVariableTargetNode node) -> void
467
- def on_class_variable_target_node_enter(node)
468
- handle_class_variable(node, node.location)
469
- end
470
-
471
- #: (Prism::ClassVariableWriteNode node) -> void
472
- def on_class_variable_write_node_enter(node)
473
- handle_class_variable(node, node.name_loc)
474
- end
475
-
476
- #: (String name, Prism::Location node_location, Array[Entry::Signature] signatures, ?visibility: Symbol, ?comments: String?) -> void
477
- def add_method(name, node_location, signatures, visibility: :public, comments: nil)
478
- location = Location.from_prism_location(node_location, @code_units_cache)
479
-
480
- @index.add(Entry::Method.new(
481
- @index.configuration,
482
- name,
483
- @uri,
484
- location,
485
- location,
486
- comments,
487
- signatures,
488
- visibility,
489
- @owner_stack.last,
490
- ))
491
- end
492
-
493
- #: (String name, Prism::Location full_location, Prism::Location name_location, ?comments: String?) -> void
494
- def add_module(name, full_location, name_location, comments: nil)
495
- location = Location.from_prism_location(full_location, @code_units_cache)
496
- name_loc = Location.from_prism_location(name_location, @code_units_cache)
497
-
498
- entry = Entry::Module.new(
499
- @index.configuration,
500
- Index.actual_nesting(@stack, name),
501
- @uri,
502
- location,
503
- name_loc,
504
- comments,
505
- )
506
-
507
- advance_namespace_stack(name, entry)
508
- end
509
-
510
- #: ((String | Array[String]) name_or_nesting, Prism::Location full_location, Prism::Location name_location, ?parent_class_name: String?, ?comments: String?) -> void
511
- def add_class(name_or_nesting, full_location, name_location, parent_class_name: nil, comments: nil)
512
- nesting = name_or_nesting.is_a?(Array) ? name_or_nesting : Index.actual_nesting(@stack, name_or_nesting)
513
- entry = Entry::Class.new(
514
- @index.configuration,
515
- nesting,
516
- @uri,
517
- Location.from_prism_location(full_location, @code_units_cache),
518
- Location.from_prism_location(name_location, @code_units_cache),
519
- comments,
520
- parent_class_name,
521
- )
522
-
523
- advance_namespace_stack(
524
- nesting.last, #: as !nil
525
- entry,
526
- )
527
- end
528
-
529
- #: { (Index index, Entry::Namespace base) -> void } -> void
530
- def register_included_hook(&block)
531
- owner = @owner_stack.last
532
- return unless owner
533
-
534
- @index.register_included_hook(owner.name) do |index, base|
535
- block.call(index, base)
536
- end
537
- end
538
-
539
- #: -> void
540
- def pop_namespace_stack
541
- @stack.pop
542
- @owner_stack.pop
543
- @visibility_stack.pop
544
- end
545
-
546
- #: -> Entry::Namespace?
547
- def current_owner
548
- @owner_stack.last
549
- end
550
-
551
- private
552
-
553
- #: ((Prism::GlobalVariableAndWriteNode | Prism::GlobalVariableOperatorWriteNode | Prism::GlobalVariableOrWriteNode | Prism::GlobalVariableTargetNode | Prism::GlobalVariableWriteNode) node, Prism::Location loc) -> void
554
- def handle_global_variable(node, loc)
555
- name = node.name.to_s
556
- comments = collect_comments(node)
557
-
558
- @index.add(Entry::GlobalVariable.new(
559
- @index.configuration,
560
- name,
561
- @uri,
562
- Location.from_prism_location(loc, @code_units_cache),
563
- comments,
564
- ))
565
- end
566
-
567
- #: ((Prism::ClassVariableAndWriteNode | Prism::ClassVariableOperatorWriteNode | Prism::ClassVariableOrWriteNode | Prism::ClassVariableTargetNode | Prism::ClassVariableWriteNode) node, Prism::Location loc) -> void
568
- def handle_class_variable(node, loc)
569
- name = node.name.to_s
570
- # Ignore incomplete class variable names, which aren't valid Ruby syntax.
571
- # This could occur if the code is in an incomplete or temporary state.
572
- return if name == "@@"
573
-
574
- comments = collect_comments(node)
575
-
576
- owner = @owner_stack.last
577
-
578
- # set the class variable's owner to the attached context when defined within a singleton scope.
579
- if owner.is_a?(Entry::SingletonClass)
580
- owner = @owner_stack.reverse.find { |entry| !entry.name.include?("<") }
581
- end
582
-
583
- @index.add(Entry::ClassVariable.new(
584
- @index.configuration,
585
- name,
586
- @uri,
587
- Location.from_prism_location(loc, @code_units_cache),
588
- comments,
589
- owner,
590
- ))
591
- end
592
-
593
- #: ((Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode) node, Prism::Location loc) -> void
594
- def handle_instance_variable(node, loc)
595
- name = node.name.to_s
596
- return if name == "@"
597
-
598
- # When instance variables are declared inside the class body, they turn into class instance variables rather than
599
- # regular instance variables
600
- owner = @owner_stack.last
601
-
602
- if owner && !@inside_def
603
- owner = @index.existing_or_new_singleton_class(owner.name)
604
- end
605
-
606
- @index.add(Entry::InstanceVariable.new(
607
- @index.configuration,
608
- name,
609
- @uri,
610
- Location.from_prism_location(loc, @code_units_cache),
611
- collect_comments(node),
612
- owner,
613
- ))
614
- end
615
-
616
- #: (Prism::CallNode node) -> void
617
- def handle_private_constant(node)
618
- arguments = node.arguments&.arguments
619
- return unless arguments
620
-
621
- first_argument = arguments.first
622
-
623
- name = case first_argument
624
- when Prism::StringNode
625
- first_argument.content
626
- when Prism::SymbolNode
627
- first_argument.value
628
- end
629
-
630
- return unless name
631
-
632
- receiver = node.receiver
633
- name = "#{receiver.slice}::#{name}" if receiver
634
-
635
- # The private_constant method does not resolve the constant name. It always points to a constant that needs to
636
- # exist in the current namespace
637
- entries = @index[fully_qualify_name(name)]
638
- entries&.each { |entry| entry.visibility = :private }
639
- end
640
-
641
- #: (Prism::CallNode node) -> void
642
- def handle_alias_method(node)
643
- arguments = node.arguments&.arguments
644
- return unless arguments
645
-
646
- new_name, old_name = arguments
647
- return unless new_name && old_name
648
-
649
- new_name_value = case new_name
650
- when Prism::StringNode
651
- new_name.content
652
- when Prism::SymbolNode
653
- new_name.value
654
- end
655
-
656
- return unless new_name_value
657
-
658
- old_name_value = case old_name
659
- when Prism::StringNode
660
- old_name.content
661
- when Prism::SymbolNode
662
- old_name.value
663
- end
664
-
665
- return unless old_name_value
666
-
667
- comments = collect_comments(node)
668
- @index.add(
669
- Entry::UnresolvedMethodAlias.new(
670
- @index.configuration,
671
- new_name_value,
672
- old_name_value,
673
- @owner_stack.last,
674
- @uri,
675
- Location.from_prism_location(new_name.location, @code_units_cache),
676
- comments,
677
- ),
678
- )
679
- end
680
-
681
- #: ((Prism::ConstantWriteNode | Prism::ConstantOrWriteNode | Prism::ConstantAndWriteNode | Prism::ConstantOperatorWriteNode | Prism::ConstantPathWriteNode | Prism::ConstantPathOrWriteNode | Prism::ConstantPathOperatorWriteNode | Prism::ConstantPathAndWriteNode | Prism::ConstantTargetNode | Prism::ConstantPathTargetNode) node, String name, ?Prism::Node? value) -> void
682
- def add_constant(node, name, value = nil)
683
- value = node.value unless node.is_a?(Prism::ConstantTargetNode) || node.is_a?(Prism::ConstantPathTargetNode)
684
- comments = collect_comments(node)
685
-
686
- @index.add(
687
- case value
688
- when Prism::ConstantReadNode, Prism::ConstantPathNode
689
- Entry::UnresolvedConstantAlias.new(
690
- @index.configuration,
691
- value.slice,
692
- @stack.dup,
693
- name,
694
- @uri,
695
- Location.from_prism_location(node.location, @code_units_cache),
696
- comments,
697
- )
698
- when Prism::ConstantWriteNode, Prism::ConstantAndWriteNode, Prism::ConstantOrWriteNode,
699
- Prism::ConstantOperatorWriteNode
700
-
701
- # If the right hand side is another constant assignment, we need to visit it because that constant has to be
702
- # indexed too
703
- Entry::UnresolvedConstantAlias.new(
704
- @index.configuration,
705
- value.name.to_s,
706
- @stack.dup,
707
- name,
708
- @uri,
709
- Location.from_prism_location(node.location, @code_units_cache),
710
- comments,
711
- )
712
- when Prism::ConstantPathWriteNode, Prism::ConstantPathOrWriteNode, Prism::ConstantPathOperatorWriteNode,
713
- Prism::ConstantPathAndWriteNode
714
-
715
- Entry::UnresolvedConstantAlias.new(
716
- @index.configuration,
717
- value.target.slice,
718
- @stack.dup,
719
- name,
720
- @uri,
721
- Location.from_prism_location(node.location, @code_units_cache),
722
- comments,
723
- )
724
- else
725
- Entry::Constant.new(
726
- @index.configuration,
727
- name,
728
- @uri,
729
- Location.from_prism_location(node.location, @code_units_cache),
730
- comments,
731
- )
732
- end,
733
- )
734
- end
735
-
736
- #: (Prism::Node node) -> String?
737
- def collect_comments(node)
738
- return unless @collect_comments
739
-
740
- comments = +""
741
-
742
- start_line = node.location.start_line - 1
743
- start_line -= 1 unless comment_exists_at?(start_line)
744
- start_line.downto(1) do |line|
745
- comment = @comments_by_line[line]
746
- break unless comment
747
-
748
- # a trailing comment from a previous line is not a comment for this node
749
- break if comment.trailing?
750
-
751
- comment_content = comment.location.slice
752
-
753
- # invalid encodings would raise an "invalid byte sequence" exception
754
- if !comment_content.valid_encoding? || comment_content.match?(@index.configuration.magic_comment_regex)
755
- next
756
- end
757
-
758
- comment_content.delete_prefix!("#")
759
- comment_content.delete_prefix!(" ")
760
- comments.prepend("#{comment_content}\n")
761
- end
762
-
763
- comments.chomp!
764
- comments
765
- end
766
-
767
- #: (Integer line) -> bool
768
- def comment_exists_at?(line)
769
- @comments_by_line.key?(line) || !@source_lines[line - 1].to_s.strip.empty?
770
- end
771
-
772
- #: (String name) -> String
773
- def fully_qualify_name(name)
774
- if @stack.empty? || name.start_with?("::")
775
- name
776
- else
777
- "#{@stack.join("::")}::#{name}"
778
- end.delete_prefix("::")
779
- end
780
-
781
- #: (Prism::CallNode node, reader: bool, writer: bool) -> void
782
- def handle_attribute(node, reader:, writer:)
783
- arguments = node.arguments&.arguments
784
- return unless arguments
785
-
786
- receiver = node.receiver
787
- return unless receiver.nil? || receiver.is_a?(Prism::SelfNode)
788
-
789
- comments = collect_comments(node)
790
- scope = current_visibility_scope
791
-
792
- arguments.each do |argument|
793
- name, loc = case argument
794
- when Prism::SymbolNode
795
- [argument.value, argument.value_loc]
796
- when Prism::StringNode
797
- [argument.content, argument.content_loc]
798
- end
799
-
800
- next unless name && loc
801
-
802
- if reader
803
- @index.add(Entry::Accessor.new(
804
- @index.configuration,
805
- name,
806
- @uri,
807
- Location.from_prism_location(loc, @code_units_cache),
808
- comments,
809
- scope.visibility,
810
- @owner_stack.last,
811
- ))
812
- end
813
-
814
- next unless writer
815
-
816
- @index.add(Entry::Accessor.new(
817
- @index.configuration,
818
- "#{name}=",
819
- @uri,
820
- Location.from_prism_location(loc, @code_units_cache),
821
- comments,
822
- scope.visibility,
823
- @owner_stack.last,
824
- ))
825
- end
826
- end
827
-
828
- #: (Prism::CallNode node, Symbol operation) -> void
829
- def handle_module_operation(node, operation)
830
- return if @inside_def
831
-
832
- owner = @owner_stack.last
833
- return unless owner
834
-
835
- arguments = node.arguments&.arguments
836
- return unless arguments
837
-
838
- arguments.each do |node|
839
- next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode) ||
840
- (node.is_a?(Prism::SelfNode) && operation == :extend)
841
-
842
- if node.is_a?(Prism::SelfNode)
843
- singleton = @index.existing_or_new_singleton_class(owner.name)
844
- singleton.mixin_operations << Entry::Include.new(owner.name)
845
- else
846
- case operation
847
- when :include
848
- owner.mixin_operations << Entry::Include.new(node.full_name)
849
- when :prepend
850
- owner.mixin_operations << Entry::Prepend.new(node.full_name)
851
- when :extend
852
- singleton = @index.existing_or_new_singleton_class(owner.name)
853
- singleton.mixin_operations << Entry::Include.new(node.full_name)
854
- end
855
- end
856
- rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
857
- Prism::ConstantPathNode::MissingNodesInConstantPathError
858
- # Do nothing
859
- end
860
- end
861
-
862
- #: (Prism::CallNode node) -> void
863
- def handle_module_function(node)
864
- # Invoking `module_function` in a class raises
865
- owner = @owner_stack.last
866
- return unless owner.is_a?(Entry::Module)
867
-
868
- arguments_node = node.arguments
869
-
870
- # If `module_function` is invoked without arguments, all methods defined after it become singleton methods and the
871
- # visibility for instance methods changes to private
872
- unless arguments_node
873
- @visibility_stack.push(VisibilityScope.module_function_scope)
874
- return
875
- end
876
-
877
- owner_name = owner.name
878
-
879
- arguments_node.arguments.each do |argument|
880
- method_name = case argument
881
- when Prism::StringNode
882
- argument.content
883
- when Prism::SymbolNode
884
- argument.value
885
- end
886
- next unless method_name
887
-
888
- entries = @index.resolve_method(method_name, owner_name)
889
- next unless entries
890
-
891
- entries.each do |entry|
892
- entry_owner_name = entry.owner&.name
893
- next unless entry_owner_name
894
-
895
- entry.visibility = :private
896
-
897
- singleton = @index.existing_or_new_singleton_class(entry_owner_name)
898
- location = Location.from_prism_location(argument.location, @code_units_cache)
899
- @index.add(Entry::Method.new(
900
- @index.configuration,
901
- method_name,
902
- @uri,
903
- location,
904
- location,
905
- collect_comments(node)&.concat(entry.comments),
906
- entry.signatures,
907
- :public,
908
- singleton,
909
- ))
910
- end
911
- end
912
- end
913
-
914
- #: (Prism::CallNode node) -> void
915
- def handle_private_class_method(node)
916
- arguments = node.arguments&.arguments
917
- return unless arguments
918
-
919
- # If we're passing a method definition directly to `private_class_method`, push a new private scope. That will be
920
- # applied when the indexer finds the method definition and then popped on `call_node_leave`
921
- if arguments.first.is_a?(Prism::DefNode)
922
- @visibility_stack.push(VisibilityScope.new(visibility: :private))
923
- return
924
- end
925
-
926
- owner_name = @owner_stack.last&.name
927
- return unless owner_name
928
-
929
- # private_class_method accepts strings, symbols or arrays of strings and symbols as arguments. Here we build a
930
- # single list of all of the method names that have to be made private
931
- arrays, others = arguments.partition do |argument|
932
- argument.is_a?(Prism::ArrayNode)
933
- end #: as [Array[Prism::ArrayNode], Array[Prism::Node]]
934
- arrays.each { |array| others.concat(array.elements) }
935
-
936
- names = others.filter_map do |argument|
937
- case argument
938
- when Prism::StringNode
939
- argument.unescaped
940
- when Prism::SymbolNode
941
- argument.value
942
- end
943
- end
944
-
945
- names.each do |name|
946
- entries = @index.resolve_method(name, @index.existing_or_new_singleton_class(owner_name).name)
947
- next unless entries
948
-
949
- entries.each { |entry| entry.visibility = :private }
950
- end
951
- end
952
-
953
- #: -> VisibilityScope
954
- def current_visibility_scope
955
- @visibility_stack.last #: as !nil
956
- end
957
-
958
- #: (Prism::ParametersNode? parameters_node) -> Array[Entry::Parameter]
959
- def list_params(parameters_node)
960
- return [] unless parameters_node
961
-
962
- parameters = []
963
-
964
- parameters_node.requireds.each do |required|
965
- name = parameter_name(required)
966
- next unless name
967
-
968
- parameters << Entry::RequiredParameter.new(name: name)
969
- end
970
-
971
- parameters_node.optionals.each do |optional|
972
- name = parameter_name(optional)
973
- next unless name
974
-
975
- parameters << Entry::OptionalParameter.new(name: name)
976
- end
977
-
978
- rest = parameters_node.rest
979
-
980
- if rest.is_a?(Prism::RestParameterNode)
981
- rest_name = rest.name || Entry::RestParameter::DEFAULT_NAME
982
- parameters << Entry::RestParameter.new(name: rest_name)
983
- end
984
-
985
- parameters_node.keywords.each do |keyword|
986
- name = parameter_name(keyword)
987
- next unless name
988
-
989
- case keyword
990
- when Prism::RequiredKeywordParameterNode
991
- parameters << Entry::KeywordParameter.new(name: name)
992
- when Prism::OptionalKeywordParameterNode
993
- parameters << Entry::OptionalKeywordParameter.new(name: name)
994
- end
995
- end
996
-
997
- keyword_rest = parameters_node.keyword_rest
998
-
999
- case keyword_rest
1000
- when Prism::KeywordRestParameterNode
1001
- keyword_rest_name = parameter_name(keyword_rest) || Entry::KeywordRestParameter::DEFAULT_NAME
1002
- parameters << Entry::KeywordRestParameter.new(name: keyword_rest_name)
1003
- when Prism::ForwardingParameterNode
1004
- parameters << Entry::ForwardingParameter.new
1005
- end
1006
-
1007
- parameters_node.posts.each do |post|
1008
- name = parameter_name(post)
1009
- next unless name
1010
-
1011
- parameters << Entry::RequiredParameter.new(name: name)
1012
- end
1013
-
1014
- block = parameters_node.block
1015
- parameters << Entry::BlockParameter.new(name: block.name || Entry::BlockParameter::DEFAULT_NAME) if block
1016
-
1017
- parameters
1018
- end
1019
-
1020
- #: (Prism::Node? node) -> Symbol?
1021
- def parameter_name(node)
1022
- case node
1023
- when Prism::RequiredParameterNode, Prism::OptionalParameterNode,
1024
- Prism::RequiredKeywordParameterNode, Prism::OptionalKeywordParameterNode,
1025
- Prism::RestParameterNode, Prism::KeywordRestParameterNode
1026
- node.name
1027
- when Prism::MultiTargetNode
1028
- names = node.lefts.map { |parameter_node| parameter_name(parameter_node) }
1029
-
1030
- rest = node.rest
1031
- if rest.is_a?(Prism::SplatNode)
1032
- name = rest.expression&.slice
1033
- names << (rest.operator == "*" ? "*#{name}".to_sym : name&.to_sym)
1034
- end
1035
-
1036
- names << nil if rest.is_a?(Prism::ImplicitRestNode)
1037
-
1038
- names.concat(node.rights.map { |parameter_node| parameter_name(parameter_node) })
1039
-
1040
- names_with_commas = names.join(", ")
1041
- :"(#{names_with_commas})"
1042
- end
1043
- end
1044
-
1045
- #: (String short_name, Entry::Namespace entry) -> void
1046
- def advance_namespace_stack(short_name, entry)
1047
- @visibility_stack.push(VisibilityScope.public_scope)
1048
- @owner_stack << entry
1049
- @index.add(entry)
1050
- @stack << short_name
1051
- end
1052
-
1053
- # Returns the last name in the stack not as we found it, but in terms of declared constants. For example, if the
1054
- # last entry in the stack is a compact namespace like `Foo::Bar`, then the last name is `Bar`
1055
- #: -> String?
1056
- def last_name_in_stack
1057
- name = @stack.last
1058
- return unless name
1059
-
1060
- name.split("::").last
1061
- end
1062
-
1063
- #: (Prism::CallNode, Symbol) -> void
1064
- def handle_visibility_change(node, visibility)
1065
- owner = @owner_stack.last
1066
- return unless owner
1067
-
1068
- owner_name = owner.name
1069
- method_names = string_or_symbol_argument_values(node)
1070
-
1071
- if method_names.empty?
1072
- @visibility_stack.push(VisibilityScope.new(visibility: visibility))
1073
- return
1074
- end
1075
-
1076
- method_names.each do |method_name|
1077
- entries = @index.resolve_method(method_name, owner_name)
1078
- next unless entries
1079
-
1080
- entries.each do |entry|
1081
- entry.visibility = visibility
1082
- end
1083
- end
1084
- end
1085
-
1086
- #: (Prism::CallNode) -> Array[String]
1087
- def string_or_symbol_argument_values(node)
1088
- arguments = node.arguments&.arguments
1089
- return [] unless arguments
1090
-
1091
- arguments.filter_map do |argument|
1092
- case argument
1093
- when Prism::StringNode
1094
- argument.content
1095
- when Prism::SymbolNode
1096
- argument.value
1097
- end
1098
- end
1099
- end
1100
- end
1101
- end