ruby-lsp 0.23.15 → 0.26.9

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp +17 -14
  4. data/exe/ruby-lsp-check +0 -4
  5. data/exe/ruby-lsp-launcher +41 -14
  6. data/exe/ruby-lsp-test-exec +6 -0
  7. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +0 -1
  8. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +0 -1
  9. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -3
  10. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +42 -20
  11. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -7
  12. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +49 -62
  13. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +84 -74
  14. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -9
  15. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +9 -14
  16. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +4 -4
  18. data/lib/ruby_lsp/addon.rb +44 -15
  19. data/lib/ruby_lsp/base_server.rb +56 -37
  20. data/lib/ruby_lsp/client_capabilities.rb +6 -1
  21. data/lib/ruby_lsp/document.rb +174 -62
  22. data/lib/ruby_lsp/erb_document.rb +10 -8
  23. data/lib/ruby_lsp/global_state.rb +86 -33
  24. data/lib/ruby_lsp/internal.rb +6 -3
  25. data/lib/ruby_lsp/listeners/completion.rb +22 -11
  26. data/lib/ruby_lsp/listeners/definition.rb +41 -21
  27. data/lib/ruby_lsp/listeners/document_highlight.rb +26 -1
  28. data/lib/ruby_lsp/listeners/document_link.rb +64 -28
  29. data/lib/ruby_lsp/listeners/hover.rb +27 -16
  30. data/lib/ruby_lsp/listeners/inlay_hints.rb +5 -3
  31. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +2 -2
  32. data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
  33. data/lib/ruby_lsp/listeners/spec_style.rb +155 -79
  34. data/lib/ruby_lsp/listeners/test_discovery.rb +39 -21
  35. data/lib/ruby_lsp/listeners/test_style.rb +75 -35
  36. data/lib/ruby_lsp/rbs_document.rb +3 -6
  37. data/lib/ruby_lsp/requests/code_action_resolve.rb +83 -58
  38. data/lib/ruby_lsp/requests/code_actions.rb +20 -5
  39. data/lib/ruby_lsp/requests/code_lens.rb +27 -6
  40. data/lib/ruby_lsp/requests/completion.rb +3 -3
  41. data/lib/ruby_lsp/requests/completion_resolve.rb +8 -6
  42. data/lib/ruby_lsp/requests/definition.rb +4 -7
  43. data/lib/ruby_lsp/requests/discover_tests.rb +2 -2
  44. data/lib/ruby_lsp/requests/document_highlight.rb +2 -2
  45. data/lib/ruby_lsp/requests/document_link.rb +1 -1
  46. data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
  47. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +64 -12
  48. data/lib/ruby_lsp/requests/hover.rb +3 -6
  49. data/lib/ruby_lsp/requests/inlay_hints.rb +4 -4
  50. data/lib/ruby_lsp/requests/on_type_formatting.rb +1 -1
  51. data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
  52. data/lib/ruby_lsp/requests/references.rb +10 -21
  53. data/lib/ruby_lsp/requests/rename.rb +9 -10
  54. data/lib/ruby_lsp/requests/request.rb +8 -8
  55. data/lib/ruby_lsp/requests/selection_ranges.rb +2 -2
  56. data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
  57. data/lib/ruby_lsp/requests/show_syntax_tree.rb +2 -2
  58. data/lib/ruby_lsp/requests/signature_help.rb +2 -2
  59. data/lib/ruby_lsp/requests/support/annotation.rb +1 -1
  60. data/lib/ruby_lsp/requests/support/common.rb +9 -12
  61. data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
  62. data/lib/ruby_lsp/requests/support/package_url.rb +414 -0
  63. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +7 -1
  64. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
  65. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +13 -3
  66. data/lib/ruby_lsp/requests/support/source_uri.rb +7 -4
  67. data/lib/ruby_lsp/requests/support/test_item.rb +7 -1
  68. data/lib/ruby_lsp/requests/workspace_symbol.rb +20 -12
  69. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +1 -4
  70. data/lib/ruby_lsp/response_builders/document_symbol.rb +2 -3
  71. data/lib/ruby_lsp/response_builders/hover.rb +1 -4
  72. data/lib/ruby_lsp/response_builders/response_builder.rb +6 -7
  73. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +4 -5
  74. data/lib/ruby_lsp/response_builders/signature_help.rb +1 -2
  75. data/lib/ruby_lsp/response_builders/test_collection.rb +29 -3
  76. data/lib/ruby_lsp/ruby_document.rb +14 -42
  77. data/lib/ruby_lsp/scripts/compose_bundle.rb +3 -3
  78. data/lib/ruby_lsp/scripts/compose_bundle_windows.rb +3 -1
  79. data/lib/ruby_lsp/server.rb +173 -130
  80. data/lib/ruby_lsp/setup_bundler.rb +114 -47
  81. data/lib/ruby_lsp/static_docs.rb +1 -0
  82. data/lib/ruby_lsp/store.rb +6 -16
  83. data/lib/ruby_lsp/test_helper.rb +1 -4
  84. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +121 -17
  85. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +65 -25
  86. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +16 -18
  87. data/lib/ruby_lsp/utils.rb +102 -13
  88. data/static_docs/break.md +103 -0
  89. metadata +8 -33
  90. data/lib/ruby_indexer/test/class_variables_test.rb +0 -140
  91. data/lib/ruby_indexer/test/classes_and_modules_test.rb +0 -770
  92. data/lib/ruby_indexer/test/configuration_test.rb +0 -280
  93. data/lib/ruby_indexer/test/constant_test.rb +0 -402
  94. data/lib/ruby_indexer/test/enhancements_test.rb +0 -325
  95. data/lib/ruby_indexer/test/global_variable_test.rb +0 -49
  96. data/lib/ruby_indexer/test/index_test.rb +0 -2190
  97. data/lib/ruby_indexer/test/instance_variables_test.rb +0 -240
  98. data/lib/ruby_indexer/test/method_test.rb +0 -973
  99. data/lib/ruby_indexer/test/prefix_tree_test.rb +0 -150
  100. data/lib/ruby_indexer/test/rbs_indexer_test.rb +0 -380
  101. data/lib/ruby_indexer/test/reference_finder_test.rb +0 -330
  102. data/lib/ruby_indexer/test/test_case.rb +0 -51
  103. data/lib/ruby_indexer/test/uri_test.rb +0 -85
  104. data/lib/ruby_lsp/load_sorbet.rb +0 -62
@@ -3,13 +3,8 @@
3
3
 
4
4
  module RubyIndexer
5
5
  class Entry
6
- class Visibility < T::Enum
7
- enums do
8
- PUBLIC = new(:public)
9
- PROTECTED = new(:protected)
10
- PRIVATE = new(:private)
11
- end
12
- end
6
+ #: Configuration
7
+ attr_reader :configuration
13
8
 
14
9
  #: String
15
10
  attr_reader :name
@@ -22,31 +17,32 @@ module RubyIndexer
22
17
 
23
18
  alias_method :name_location, :location
24
19
 
25
- #: Visibility
20
+ #: Symbol
26
21
  attr_accessor :visibility
27
22
 
28
- #: (String name, URI::Generic uri, Location location, String? comments) -> void
29
- def initialize(name, uri, location, comments)
23
+ #: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments) -> void
24
+ def initialize(configuration, name, uri, location, comments)
25
+ @configuration = configuration
30
26
  @name = name
31
27
  @uri = uri
32
28
  @comments = comments
33
- @visibility = Visibility::PUBLIC #: Visibility
29
+ @visibility = :public #: Symbol
34
30
  @location = location
35
31
  end
36
32
 
37
33
  #: -> bool
38
34
  def public?
39
- visibility == Visibility::PUBLIC
35
+ @visibility == :public
40
36
  end
41
37
 
42
38
  #: -> bool
43
39
  def protected?
44
- visibility == Visibility::PROTECTED
40
+ @visibility == :protected
45
41
  end
46
42
 
47
43
  #: -> bool
48
44
  def private?
49
- visibility == Visibility::PRIVATE
45
+ @visibility == :private
50
46
  end
51
47
 
52
48
  #: -> String
@@ -90,7 +86,7 @@ module RubyIndexer
90
86
  correct_group.filter_map do |comment|
91
87
  content = comment.slice.chomp
92
88
 
93
- if content.valid_encoding?
89
+ if content.valid_encoding? && !content.match?(@configuration.magic_comment_regex)
94
90
  content.delete_prefix!("#")
95
91
  content.delete_prefix!(" ")
96
92
  content
@@ -106,12 +102,8 @@ module RubyIndexer
106
102
  end
107
103
  end
108
104
 
105
+ # @abstract
109
106
  class ModuleOperation
110
- extend T::Sig
111
- extend T::Helpers
112
-
113
- abstract!
114
-
115
107
  #: String
116
108
  attr_reader :module_name
117
109
 
@@ -124,12 +116,8 @@ module RubyIndexer
124
116
  class Include < ModuleOperation; end
125
117
  class Prepend < ModuleOperation; end
126
118
 
119
+ # @abstract
127
120
  class Namespace < Entry
128
- extend T::Sig
129
- extend T::Helpers
130
-
131
- abstract!
132
-
133
121
  #: Array[String]
134
122
  attr_reader :nesting
135
123
 
@@ -137,13 +125,13 @@ module RubyIndexer
137
125
  #: Location
138
126
  attr_reader :name_location
139
127
 
140
- #: (Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments) -> void
141
- def initialize(nesting, uri, location, name_location, comments)
128
+ #: (Configuration configuration, Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments) -> void
129
+ def initialize(configuration, nesting, uri, location, name_location, comments) # rubocop:disable Metrics/ParameterLists
142
130
  @name = nesting.join("::") #: String
143
131
  # The original nesting where this namespace was discovered
144
132
  @nesting = nesting
145
133
 
146
- super(@name, uri, location, comments)
134
+ super(configuration, @name, uri, location, comments)
147
135
 
148
136
  @name_location = name_location
149
137
  end
@@ -176,9 +164,9 @@ module RubyIndexer
176
164
  #: String?
177
165
  attr_reader :parent_class
178
166
 
179
- #: (Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments, String? parent_class) -> void
180
- def initialize(nesting, uri, location, name_location, comments, parent_class) # rubocop:disable Metrics/ParameterLists
181
- super(nesting, uri, location, name_location, comments)
167
+ #: (Configuration configuration, Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments, String? parent_class) -> void
168
+ def initialize(configuration, nesting, uri, location, name_location, comments, parent_class) # rubocop:disable Metrics/ParameterLists
169
+ super(configuration, nesting, uri, location, name_location, comments)
182
170
  @parent_class = parent_class
183
171
  end
184
172
 
@@ -201,12 +189,8 @@ module RubyIndexer
201
189
  class Constant < Entry
202
190
  end
203
191
 
192
+ # @abstract
204
193
  class Parameter
205
- extend T::Helpers
206
- extend T::Sig
207
-
208
- abstract!
209
-
210
194
  # Name includes just the name of the parameter, excluding symbols like splats
211
195
  #: Symbol
212
196
  attr_reader :name
@@ -300,24 +284,23 @@ module RubyIndexer
300
284
  end
301
285
  end
302
286
 
287
+ # @abstract
303
288
  class Member < Entry
304
- extend T::Sig
305
- extend T::Helpers
306
-
307
- abstract!
308
-
309
289
  #: Entry::Namespace?
310
290
  attr_reader :owner
311
291
 
312
- #: (String name, URI::Generic uri, Location location, String? comments, Visibility visibility, Entry::Namespace? owner) -> void
313
- def initialize(name, uri, location, comments, visibility, owner) # rubocop:disable Metrics/ParameterLists
314
- super(name, uri, location, comments)
292
+ #: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments, Symbol visibility, Entry::Namespace? owner) -> void
293
+ def initialize(configuration, name, uri, location, comments, visibility, owner) # rubocop:disable Metrics/ParameterLists
294
+ super(configuration, name, uri, location, comments)
315
295
  @visibility = visibility
316
296
  @owner = owner
317
297
  end
318
298
 
319
- sig { abstract.returns(T::Array[Entry::Signature]) }
320
- def signatures; end
299
+ # @abstract
300
+ #: -> Array[Signature]
301
+ def signatures
302
+ raise AbstractMethodInvokedError
303
+ end
321
304
 
322
305
  #: -> String
323
306
  def decorated_parameters
@@ -354,6 +337,7 @@ module RubyIndexer
354
337
  end
355
338
 
356
339
  class Method < Member
340
+ # @override
357
341
  #: Array[Signature]
358
342
  attr_reader :signatures
359
343
 
@@ -361,9 +345,9 @@ module RubyIndexer
361
345
  #: Location
362
346
  attr_reader :name_location
363
347
 
364
- #: (String name, URI::Generic uri, Location location, Location name_location, String? comments, Array[Signature] signatures, Visibility visibility, Entry::Namespace? owner) -> void
365
- def initialize(name, uri, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists
366
- super(name, uri, location, comments, visibility, owner)
348
+ #: (Configuration configuration, String name, URI::Generic uri, Location location, Location name_location, String? comments, Array[Signature] signatures, Symbol visibility, Entry::Namespace? owner) -> void
349
+ def initialize(configuration, name, uri, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists
350
+ super(configuration, name, uri, location, comments, visibility, owner)
367
351
  @signatures = signatures
368
352
  @name_location = name_location
369
353
  end
@@ -386,9 +370,9 @@ module RubyIndexer
386
370
  #: Array[String]
387
371
  attr_reader :nesting
388
372
 
389
- #: (String target, Array[String] nesting, String name, URI::Generic uri, Location location, String? comments) -> void
390
- def initialize(target, nesting, name, uri, location, comments) # rubocop:disable Metrics/ParameterLists
391
- super(name, uri, location, comments)
373
+ #: (Configuration configuration, String target, Array[String] nesting, String name, URI::Generic uri, Location location, String? comments) -> void
374
+ def initialize(configuration, target, nesting, name, uri, location, comments) # rubocop:disable Metrics/ParameterLists
375
+ super(configuration, name, uri, location, comments)
392
376
 
393
377
  @target = target
394
378
  @nesting = nesting
@@ -403,6 +387,7 @@ module RubyIndexer
403
387
  #: (String target, UnresolvedConstantAlias unresolved_alias) -> void
404
388
  def initialize(target, unresolved_alias)
405
389
  super(
390
+ unresolved_alias.configuration,
406
391
  unresolved_alias.name,
407
392
  unresolved_alias.uri,
408
393
  unresolved_alias.location,
@@ -422,9 +407,9 @@ module RubyIndexer
422
407
  #: Entry::Namespace?
423
408
  attr_reader :owner
424
409
 
425
- #: (String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
426
- def initialize(name, uri, location, comments, owner)
427
- super(name, uri, location, comments)
410
+ #: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
411
+ def initialize(configuration, name, uri, location, comments, owner) # rubocop:disable Metrics/ParameterLists
412
+ super(configuration, name, uri, location, comments)
428
413
  @owner = owner
429
414
  end
430
415
  end
@@ -434,9 +419,9 @@ module RubyIndexer
434
419
  #: Entry::Namespace?
435
420
  attr_reader :owner
436
421
 
437
- #: (String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
438
- def initialize(name, uri, location, comments, owner)
439
- super(name, uri, location, comments)
422
+ #: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
423
+ def initialize(configuration, name, uri, location, comments, owner) # rubocop:disable Metrics/ParameterLists
424
+ super(configuration, name, uri, location, comments)
440
425
  @owner = owner
441
426
  end
442
427
  end
@@ -451,9 +436,9 @@ module RubyIndexer
451
436
  #: Entry::Namespace?
452
437
  attr_reader :owner
453
438
 
454
- #: (String new_name, String old_name, Entry::Namespace? owner, URI::Generic uri, Location location, String? comments) -> void
455
- def initialize(new_name, old_name, owner, uri, location, comments) # rubocop:disable Metrics/ParameterLists
456
- super(new_name, uri, location, comments)
439
+ #: (Configuration configuration, String new_name, String old_name, Entry::Namespace? owner, URI::Generic uri, Location location, String? comments) -> void
440
+ def initialize(configuration, new_name, old_name, owner, uri, location, comments) # rubocop:disable Metrics/ParameterLists
441
+ super(configuration, new_name, uri, location, comments)
457
442
 
458
443
  @new_name = new_name
459
444
  @old_name = old_name
@@ -476,6 +461,7 @@ module RubyIndexer
476
461
  full_comments << target.comments
477
462
 
478
463
  super(
464
+ unresolved_alias.configuration,
479
465
  unresolved_alias.new_name,
480
466
  unresolved_alias.uri,
481
467
  unresolved_alias.location,
@@ -563,7 +549,8 @@ module RubyIndexer
563
549
  end
564
550
 
565
551
  keyword_hash_nodes, positional_args = arguments.partition { |arg| arg.is_a?(Prism::KeywordHashNode) }
566
- keyword_args = T.cast(keyword_hash_nodes.first, T.nilable(Prism::KeywordHashNode))&.elements
552
+ keyword_args = keyword_hash_nodes.first #: as Prism::KeywordHashNode?
553
+ &.elements
567
554
  forwarding_arguments, positionals = positional_args.partition do |arg|
568
555
  arg.is_a?(Prism::ForwardingArgumentsNode)
569
556
  end
@@ -36,12 +36,10 @@ module RubyIndexer
36
36
 
37
37
  # Returns the unresolved name for a constant reference including all parts of a constant path, or `nil` if the
38
38
  # constant contains dynamic or incomplete parts
39
- #: ((Prism::ConstantPathNode | Prism::ConstantReadNode | Prism::ConstantPathTargetNode | Prism::CallNode | Prism::MissingNode) node) -> String?
39
+ #: (Prism::Node) -> String?
40
40
  def constant_name(node)
41
41
  case node
42
- when Prism::CallNode, Prism::MissingNode
43
- nil
44
- else
42
+ when Prism::ConstantPathNode, Prism::ConstantReadNode, Prism::ConstantPathTargetNode
45
43
  node.full_name
46
44
  end
47
45
  rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
@@ -60,7 +58,7 @@ module RubyIndexer
60
58
  @entries = {} #: Hash[String, Array[Entry]]
61
59
 
62
60
  # Holds all entries in the index using a prefix tree for searching based on prefixes to provide autocompletion
63
- @entries_tree = PrefixTree[T::Array[Entry]].new #: PrefixTree[Array[Entry]]
61
+ @entries_tree = PrefixTree.new #: PrefixTree[Array[Entry]]
64
62
 
65
63
  # Holds references to where entries where discovered so that we can easily delete them
66
64
  # {
@@ -71,7 +69,7 @@ module RubyIndexer
71
69
  @uris_to_entries = {} #: Hash[String, Array[Entry]]
72
70
 
73
71
  # Holds all require paths for every indexed item so that we can provide autocomplete for requires
74
- @require_paths_tree = PrefixTree[URI::Generic].new #: PrefixTree[URI::Generic]
72
+ @require_paths_tree = PrefixTree.new #: PrefixTree[URI::Generic]
75
73
 
76
74
  # Holds the linearized ancestors list for every namespace
77
75
  @ancestors = {} #: Hash[String, Array[String]]
@@ -147,7 +145,7 @@ module RubyIndexer
147
145
 
148
146
  # Searches for a constant based on an unqualified name and returns the first possible match regardless of whether
149
147
  # there are more possible matching entries
150
- #: (String name) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]?
148
+ #: (String name) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
151
149
  def first_unqualified_const(name)
152
150
  # Look for an exact match first
153
151
  _name, entries = @entries.find do |const_name, _entries|
@@ -161,15 +159,7 @@ module RubyIndexer
161
159
  end
162
160
  end
163
161
 
164
- T.cast(
165
- entries,
166
- T.nilable(T::Array[T.any(
167
- Entry::Namespace,
168
- Entry::ConstantAlias,
169
- Entry::UnresolvedConstantAlias,
170
- Entry::Constant,
171
- )]),
172
- )
162
+ entries #: as Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
173
163
  end
174
164
 
175
165
  # Searches entries in the index based on an exact prefix, intended for providing autocomplete. All possible matches
@@ -205,12 +195,13 @@ module RubyIndexer
205
195
  end
206
196
 
207
197
  # Fuzzy searches index entries based on Jaro-Winkler similarity. If no query is provided, all entries are returned
208
- #: (String? query) -> Array[Entry]
209
- def fuzzy_search(query)
198
+ #: (String? query) ?{ (Entry) -> bool? } -> Array[Entry]
199
+ def fuzzy_search(query, &condition)
210
200
  unless query
211
201
  entries = @entries.filter_map do |_name, entries|
212
202
  next if entries.first.is_a?(Entry::SingletonClass)
213
203
 
204
+ entries = entries.select(&condition) if condition
214
205
  entries
215
206
  end
216
207
 
@@ -222,6 +213,9 @@ module RubyIndexer
222
213
  results = @entries.filter_map do |name, entries|
223
214
  next if entries.first.is_a?(Entry::SingletonClass)
224
215
 
216
+ entries = entries.select(&condition) if condition
217
+ next if entries.empty?
218
+
225
219
  similarity = DidYouMean::JaroWinkler.distance(name.gsub("::", "").downcase, normalized_query)
226
220
  [entries, -similarity] if similarity > ENTRY_SIMILARITY_THRESHOLD
227
221
  end
@@ -272,19 +266,11 @@ module RubyIndexer
272
266
  completion_items.values.map!(&:first)
273
267
  end
274
268
 
275
- #: (String name, Array[String] nesting) -> Array[Array[(Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias)]]
269
+ #: (String name, Array[String] nesting) -> Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]]
276
270
  def constant_completion_candidates(name, nesting)
277
271
  # If we have a top level reference, then we don't need to include completions inside the current nesting
278
272
  if name.start_with?("::")
279
- return T.cast(
280
- @entries_tree.search(name.delete_prefix("::")),
281
- T::Array[T::Array[T.any(
282
- Entry::Constant,
283
- Entry::ConstantAlias,
284
- Entry::Namespace,
285
- Entry::UnresolvedConstantAlias,
286
- )]],
287
- )
273
+ return @entries_tree.search(name.delete_prefix("::")) #: as Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]]
288
274
  end
289
275
 
290
276
  # Otherwise, we have to include every possible constant the user might be referring to. This is essentially the
@@ -309,16 +295,19 @@ module RubyIndexer
309
295
 
310
296
  # Top level constants
311
297
  entries.concat(@entries_tree.search(name))
298
+
299
+ # Filter only constants since methods may have names that look like constants
300
+ entries.select! do |definitions|
301
+ definitions.select! do |entry|
302
+ entry.is_a?(Entry::Constant) || entry.is_a?(Entry::ConstantAlias) ||
303
+ entry.is_a?(Entry::Namespace) || entry.is_a?(Entry::UnresolvedConstantAlias)
304
+ end
305
+
306
+ definitions.any?
307
+ end
308
+
312
309
  entries.uniq!
313
- T.cast(
314
- entries,
315
- T::Array[T::Array[T.any(
316
- Entry::Constant,
317
- Entry::ConstantAlias,
318
- Entry::Namespace,
319
- Entry::UnresolvedConstantAlias,
320
- )]],
321
- )
310
+ entries #: as Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]]
322
311
  end
323
312
 
324
313
  # Resolve a constant to its declaration based on its name and the nesting where the reference was found. Parameter
@@ -328,7 +317,7 @@ module RubyIndexer
328
317
  # nesting: the nesting structure where the reference was found (e.g.: ["Foo", "Bar"])
329
318
  # seen_names: this parameter should not be used by consumers of the api. It is used to avoid infinite recursion when
330
319
  # resolving circular references
331
- #: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
320
+ #: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
332
321
  def resolve(name, nesting, seen_names = [])
333
322
  # If we have a top level reference, then we just search for it straight away ignoring the nesting
334
323
  if name.start_with?("::")
@@ -439,7 +428,10 @@ module RubyIndexer
439
428
  (parts.length - 1).downto(0) do |i|
440
429
  current_name = parts[0..i] #: as !nil
441
430
  .join("::")
442
- entry = @entries[current_name]&.first
431
+
432
+ entry = unless seen_names.include?(current_name)
433
+ @entries[current_name]&.first
434
+ end
443
435
 
444
436
  case entry
445
437
  when Entry::ConstantAlias
@@ -586,7 +578,7 @@ module RubyIndexer
586
578
  # and find inherited instance variables as well
587
579
  #: (String variable_name, String owner_name) -> Array[Entry::InstanceVariable]?
588
580
  def resolve_instance_variable(variable_name, owner_name)
589
- entries = T.cast(self[variable_name], T.nilable(T::Array[Entry::InstanceVariable]))
581
+ entries = self[variable_name] #: as Array[Entry::InstanceVariable]?
590
582
  return unless entries
591
583
 
592
584
  ancestors = linearized_ancestors_of(owner_name)
@@ -610,7 +602,7 @@ module RubyIndexer
610
602
  # include the `@` prefix
611
603
  #: (String name, String owner_name) -> Array[(Entry::InstanceVariable | Entry::ClassVariable)]
612
604
  def instance_variable_completion_candidates(name, owner_name)
613
- entries = T.cast(prefix_search(name).flatten, T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
605
+ entries = prefix_search(name).flatten #: as Array[Entry::InstanceVariable | Entry::ClassVariable]
614
606
  # Avoid wasting time linearizing ancestors if we didn't find anything
615
607
  return entries if entries.empty?
616
608
 
@@ -640,7 +632,7 @@ module RubyIndexer
640
632
 
641
633
  #: (String name, String owner_name) -> Array[Entry::ClassVariable]
642
634
  def class_variable_completion_candidates(name, owner_name)
643
- entries = T.cast(prefix_search(name).flatten, T::Array[Entry::ClassVariable])
635
+ entries = prefix_search(name).flatten #: as Array[Entry::ClassVariable]
644
636
  # Avoid wasting time linearizing ancestors if we didn't find anything
645
637
  return entries if entries.empty?
646
638
 
@@ -676,19 +668,22 @@ module RubyIndexer
676
668
  # indirect means like including a module that than includes the ancestor. Trying to figure out exactly which
677
669
  # ancestors need to be deleted is too expensive. Therefore, if any of the namespace entries has a change to their
678
670
  # ancestor hash, we clear all ancestors and start linearizing lazily again from scratch
679
- original_map = T.cast(
680
- original_entries.select { |e| e.is_a?(Entry::Namespace) },
681
- T::Array[Entry::Namespace],
682
- ).to_h { |e| [e.name, e.ancestor_hash] }
671
+ original_map = original_entries
672
+ .select { |e| e.is_a?(Entry::Namespace) } #: as Array[Entry::Namespace]
673
+ .to_h { |e| [e.name, e.ancestor_hash] }
683
674
 
684
- updated_map = T.cast(
685
- updated_entries.select { |e| e.is_a?(Entry::Namespace) },
686
- T::Array[Entry::Namespace],
687
- ).to_h { |e| [e.name, e.ancestor_hash] }
675
+ updated_map = updated_entries
676
+ .select { |e| e.is_a?(Entry::Namespace) } #: as Array[Entry::Namespace]
677
+ .to_h { |e| [e.name, e.ancestor_hash] }
688
678
 
689
679
  @ancestors.clear if original_map.any? { |name, hash| updated_map[name] != hash }
690
680
  end
691
681
 
682
+ #: -> void
683
+ def clear_ancestors
684
+ @ancestors.clear
685
+ end
686
+
692
687
  #: -> bool
693
688
  def empty?
694
689
  @entries.empty?
@@ -713,12 +708,13 @@ module RubyIndexer
713
708
  def existing_or_new_singleton_class(name)
714
709
  *_namespace, unqualified_name = name.split("::")
715
710
  full_singleton_name = "#{name}::<Class:#{unqualified_name}>"
716
- singleton = T.cast(self[full_singleton_name]&.first, T.nilable(Entry::SingletonClass))
711
+ singleton = self[full_singleton_name]&.first #: as Entry::SingletonClass?
717
712
 
718
713
  unless singleton
719
714
  attached_ancestor = self[name]&.first #: as !nil
720
715
 
721
716
  singleton = Entry::SingletonClass.new(
717
+ @configuration,
722
718
  [full_singleton_name],
723
719
  attached_ancestor.uri,
724
720
  attached_ancestor.location,
@@ -841,14 +837,22 @@ module RubyIndexer
841
837
  )
842
838
  # Find the first class entry that has a parent class. Notice that if the developer makes a mistake and inherits
843
839
  # from two different classes in different files, we simply ignore it
844
- superclass = T.cast(
845
- if singleton_levels > 0
846
- self[attached_class_name]&.find { |n| n.is_a?(Entry::Class) && n.parent_class }
847
- else
848
- namespace_entries.find { |n| n.is_a?(Entry::Class) && n.parent_class }
849
- end,
850
- T.nilable(Entry::Class),
851
- )
840
+ possible_parents = singleton_levels > 0 ? self[attached_class_name] : namespace_entries
841
+ superclass = nil #: Entry::Class?
842
+
843
+ possible_parents&.each do |n|
844
+ # Ignore non class entries
845
+ next unless n.is_a?(Entry::Class)
846
+
847
+ parent_class = n.parent_class
848
+ next unless parent_class
849
+
850
+ # Always set the superclass, but break early if we found one that isn't `::Object` (meaning we found an explicit
851
+ # parent class and not the implicit default). Note that when setting different parents to the same class, which
852
+ # is invalid, we pick whatever is the first one we find
853
+ superclass = n
854
+ break if parent_class != "::Object"
855
+ end
852
856
 
853
857
  if superclass
854
858
  # If the user makes a mistake and creates a class that inherits from itself, this method would throw a stack
@@ -882,7 +886,7 @@ module RubyIndexer
882
886
  elsif singleton_levels > 0
883
887
  # When computing the linearization for a module's singleton class, it inherits from the linearized ancestors of
884
888
  # the `Module` class
885
- mod = T.cast(self[attached_class_name]&.find { |n| n.is_a?(Entry::Module) }, T.nilable(Entry::Module))
889
+ mod = self[attached_class_name]&.find { |n| n.is_a?(Entry::Module) } #: as Entry::Module?
886
890
 
887
891
  if mod
888
892
  module_class_name_parts = ["Module"]
@@ -908,6 +912,9 @@ module RubyIndexer
908
912
  target = resolve(entry.target, entry.nesting, seen_names)
909
913
  return entry unless target
910
914
 
915
+ # Self referential alias can be unresolved we should bail out from resolving
916
+ return entry if target.first == entry
917
+
911
918
  target_name = target.first #: as !nil
912
919
  .name
913
920
  resolved_alias = Entry::ConstantAlias.new(target_name, entry)
@@ -922,7 +929,7 @@ module RubyIndexer
922
929
  resolved_alias
923
930
  end
924
931
 
925
- #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
932
+ #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
926
933
  def lookup_enclosing_scopes(name, nesting, seen_names)
927
934
  nesting.length.downto(1) do |i|
928
935
  namespace = nesting[0...i] #: as !nil
@@ -942,7 +949,7 @@ module RubyIndexer
942
949
  nil
943
950
  end
944
951
 
945
- #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
952
+ #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
946
953
  def lookup_ancestor_chain(name, nesting, seen_names)
947
954
  *nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
948
955
  return if nesting_parts.empty?
@@ -1023,22 +1030,25 @@ module RubyIndexer
1023
1030
  # Otherwise, push all of the leading parts of the nesting that aren't redundant into the name. For example, if we
1024
1031
  # have a reference to `Foo::Bar` inside the `[Namespace, Foo]` nesting, then only the `Foo` part is redundant, but
1025
1032
  # we still need to include the `Namespace` part
1026
- T.unsafe(name_parts).unshift(*nesting[0...first_redundant_part])
1033
+ name_parts.unshift(*nesting[0...first_redundant_part])
1027
1034
  name_parts.join("::")
1028
1035
  end
1029
1036
 
1030
- #: (String full_name, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
1037
+ # Tries to return direct entry from index then non seen canonicalized alias or nil
1038
+ #: (String full_name, Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
1031
1039
  def direct_or_aliased_constant(full_name, seen_names)
1032
- entries = @entries[full_name] || @entries[follow_aliased_namespace(full_name)]
1033
-
1034
- T.cast(
1035
- entries&.map { |e| e.is_a?(Entry::UnresolvedConstantAlias) ? resolve_alias(e, seen_names) : e },
1036
- T.nilable(T::Array[T.any(
1037
- Entry::Namespace,
1038
- Entry::ConstantAlias,
1039
- Entry::UnresolvedConstantAlias,
1040
- )]),
1041
- )
1040
+ if (entries = @entries[full_name])
1041
+ return entries.map do |e|
1042
+ e.is_a?(Entry::UnresolvedConstantAlias) ? resolve_alias(e, seen_names) : e
1043
+ end #: as Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias])?
1044
+ end
1045
+
1046
+ aliased = follow_aliased_namespace(full_name, seen_names)
1047
+ return if full_name == aliased || seen_names.include?(aliased)
1048
+
1049
+ @entries[aliased]&.map do |e|
1050
+ e.is_a?(Entry::UnresolvedConstantAlias) ? resolve_alias(e, seen_names) : e
1051
+ end #: as Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias])?
1042
1052
  end
1043
1053
 
1044
1054
  # Attempt to resolve a given unresolved method alias. This method returns the resolved alias if we managed to
@@ -32,14 +32,14 @@ module RubyIndexer
32
32
  # `Value` type.
33
33
  #
34
34
  # See https://en.wikipedia.org/wiki/Trie for more information
35
+ #: [Value]
35
36
  class PrefixTree
36
- extend T::Generic
37
-
38
- Value = type_member
39
-
40
37
  #: -> void
41
38
  def initialize
42
- @root = Node.new("", "") #: Node[Value]
39
+ @root = Node.new(
40
+ "",
41
+ "", #: as untyped
42
+ ) #: Node[Value]
43
43
  end
44
44
 
45
45
  # Search the PrefixTree based on a given `prefix`. If `foo` is an entry in the tree, then searching for `fo` will
@@ -106,11 +106,8 @@ module RubyIndexer
106
106
  node
107
107
  end
108
108
 
109
+ #: [Value]
109
110
  class Node
110
- extend T::Generic
111
-
112
- Value = type_member
113
-
114
111
  #: Hash[String, Node[Value]]
115
112
  attr_reader :children
116
113