ruby-lsp 0.23.10 → 0.23.12

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-launcher +12 -11
  5. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
  6. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +52 -77
  7. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +61 -144
  8. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +8 -6
  9. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +74 -183
  10. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +55 -181
  11. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  12. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +12 -14
  13. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +21 -44
  14. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +40 -58
  15. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +9 -16
  16. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +5 -9
  17. data/lib/ruby_indexer/test/classes_and_modules_test.rb +75 -0
  18. data/lib/ruby_indexer/test/configuration_test.rb +32 -2
  19. data/lib/ruby_indexer/test/index_test.rb +21 -0
  20. data/lib/ruby_indexer/test/method_test.rb +2 -2
  21. data/lib/ruby_lsp/addon.rb +32 -67
  22. data/lib/ruby_lsp/base_server.rb +12 -11
  23. data/lib/ruby_lsp/client_capabilities.rb +4 -6
  24. data/lib/ruby_lsp/document.rb +21 -32
  25. data/lib/ruby_lsp/erb_document.rb +17 -27
  26. data/lib/ruby_lsp/global_state.rb +30 -32
  27. data/lib/ruby_lsp/internal.rb +6 -0
  28. data/lib/ruby_lsp/listeners/code_lens.rb +21 -39
  29. data/lib/ruby_lsp/listeners/completion.rb +34 -53
  30. data/lib/ruby_lsp/listeners/definition.rb +35 -49
  31. data/lib/ruby_lsp/listeners/document_highlight.rb +60 -69
  32. data/lib/ruby_lsp/listeners/document_link.rb +9 -19
  33. data/lib/ruby_lsp/listeners/document_symbol.rb +34 -48
  34. data/lib/ruby_lsp/listeners/folding_ranges.rb +31 -38
  35. data/lib/ruby_lsp/listeners/hover.rb +37 -47
  36. data/lib/ruby_lsp/listeners/inlay_hints.rb +3 -10
  37. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +29 -35
  38. data/lib/ruby_lsp/listeners/signature_help.rb +4 -23
  39. data/lib/ruby_lsp/listeners/spec_style.rb +199 -0
  40. data/lib/ruby_lsp/listeners/test_style.rb +270 -0
  41. data/lib/ruby_lsp/node_context.rb +8 -35
  42. data/lib/ruby_lsp/rbs_document.rb +7 -5
  43. data/lib/ruby_lsp/requests/code_action_resolve.rb +10 -10
  44. data/lib/ruby_lsp/requests/code_actions.rb +5 -14
  45. data/lib/ruby_lsp/requests/code_lens.rb +4 -13
  46. data/lib/ruby_lsp/requests/completion.rb +4 -15
  47. data/lib/ruby_lsp/requests/completion_resolve.rb +4 -4
  48. data/lib/ruby_lsp/requests/definition.rb +4 -12
  49. data/lib/ruby_lsp/requests/diagnostics.rb +6 -9
  50. data/lib/ruby_lsp/requests/discover_tests.rb +74 -0
  51. data/lib/ruby_lsp/requests/document_highlight.rb +3 -11
  52. data/lib/ruby_lsp/requests/document_link.rb +4 -13
  53. data/lib/ruby_lsp/requests/document_symbol.rb +4 -7
  54. data/lib/ruby_lsp/requests/folding_ranges.rb +4 -7
  55. data/lib/ruby_lsp/requests/formatting.rb +4 -7
  56. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +87 -0
  57. data/lib/ruby_lsp/requests/hover.rb +6 -16
  58. data/lib/ruby_lsp/requests/inlay_hints.rb +4 -13
  59. data/lib/ruby_lsp/requests/on_type_formatting.rb +17 -24
  60. data/lib/ruby_lsp/requests/prepare_rename.rb +3 -8
  61. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +4 -13
  62. data/lib/ruby_lsp/requests/range_formatting.rb +3 -4
  63. data/lib/ruby_lsp/requests/references.rb +5 -35
  64. data/lib/ruby_lsp/requests/rename.rb +9 -35
  65. data/lib/ruby_lsp/requests/request.rb +5 -17
  66. data/lib/ruby_lsp/requests/selection_ranges.rb +3 -3
  67. data/lib/ruby_lsp/requests/semantic_highlighting.rb +6 -23
  68. data/lib/ruby_lsp/requests/show_syntax_tree.rb +4 -5
  69. data/lib/ruby_lsp/requests/signature_help.rb +6 -24
  70. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  71. data/lib/ruby_lsp/requests/support/common.rb +12 -47
  72. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -14
  73. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +7 -10
  74. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +9 -15
  75. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  76. data/lib/ruby_lsp/requests/support/sorbet.rb +1 -7
  77. data/lib/ruby_lsp/requests/support/source_uri.rb +5 -16
  78. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +7 -10
  79. data/lib/ruby_lsp/requests/support/test_item.rb +60 -0
  80. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +4 -5
  81. data/lib/ruby_lsp/requests/workspace_symbol.rb +3 -3
  82. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +4 -4
  83. data/lib/ruby_lsp/response_builders/document_symbol.rb +8 -11
  84. data/lib/ruby_lsp/response_builders/hover.rb +5 -5
  85. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  86. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +18 -40
  87. data/lib/ruby_lsp/response_builders/signature_help.rb +4 -5
  88. data/lib/ruby_lsp/response_builders/test_collection.rb +34 -0
  89. data/lib/ruby_lsp/ruby_document.rb +15 -40
  90. data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +106 -0
  91. data/lib/ruby_lsp/scope.rb +6 -10
  92. data/lib/ruby_lsp/server.rb +169 -72
  93. data/lib/ruby_lsp/setup_bundler.rb +25 -17
  94. data/lib/ruby_lsp/store.rb +12 -28
  95. data/lib/ruby_lsp/test_helper.rb +3 -12
  96. data/lib/ruby_lsp/test_reporter.rb +71 -0
  97. data/lib/ruby_lsp/test_unit_test_runner.rb +96 -0
  98. data/lib/ruby_lsp/type_inferrer.rb +9 -13
  99. data/lib/ruby_lsp/utils.rb +27 -65
  100. metadata +12 -3
@@ -3,8 +3,6 @@
3
3
 
4
4
  module RubyIndexer
5
5
  class Index
6
- extend T::Sig
7
-
8
6
  class UnresolvableAliasError < StandardError; end
9
7
  class NonExistingNamespaceError < StandardError; end
10
8
  class IndexNotEmptyError < StandardError; end
@@ -12,18 +10,19 @@ module RubyIndexer
12
10
  # The minimum Jaro-Winkler similarity score for an entry to be considered a match for a given fuzzy search query
13
11
  ENTRY_SIMILARITY_THRESHOLD = 0.7
14
12
 
15
- sig { returns(Configuration) }
13
+ #: Configuration
16
14
  attr_reader :configuration
17
15
 
18
- class << self
19
- extend T::Sig
16
+ #: bool
17
+ attr_reader :initial_indexing_completed
20
18
 
19
+ class << self
21
20
  # Returns the real nesting of a constant name taking into account top level
22
21
  # references that may be included anywhere in the name or nesting where that
23
22
  # constant was found
24
- sig { params(stack: T::Array[String], name: String).returns(T::Array[String]) }
23
+ #: (Array[String] stack, String? name) -> Array[String]
25
24
  def actual_nesting(stack, name)
26
- nesting = stack + [name]
25
+ nesting = name ? stack + [name] : stack
27
26
  corrected_nesting = []
28
27
 
29
28
  nesting.reverse_each do |name|
@@ -37,24 +36,21 @@ module RubyIndexer
37
36
 
38
37
  # Returns the unresolved name for a constant reference including all parts of a constant path, or `nil` if the
39
38
  # constant contains dynamic or incomplete parts
40
- sig do
41
- params(
42
- node: T.any(
43
- Prism::ConstantPathNode,
44
- Prism::ConstantReadNode,
45
- Prism::ConstantPathTargetNode,
46
- ),
47
- ).returns(T.nilable(String))
48
- end
39
+ #: ((Prism::ConstantPathNode | Prism::ConstantReadNode | Prism::ConstantPathTargetNode | Prism::CallNode | Prism::MissingNode) node) -> String?
49
40
  def constant_name(node)
50
- node.full_name
41
+ case node
42
+ when Prism::CallNode, Prism::MissingNode
43
+ nil
44
+ else
45
+ node.full_name
46
+ end
51
47
  rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
52
48
  Prism::ConstantPathNode::MissingNodesInConstantPathError
53
49
  nil
54
50
  end
55
51
  end
56
52
 
57
- sig { void }
53
+ #: -> void
58
54
  def initialize
59
55
  # Holds all entries in the index using the following format:
60
56
  # {
@@ -92,12 +88,12 @@ module RubyIndexer
92
88
  end
93
89
 
94
90
  # Register an included `hook` that will be executed when `module_name` is included into any namespace
95
- sig { params(module_name: String, hook: T.proc.params(index: Index, base: Entry::Namespace).void).void }
91
+ #: (String module_name) { (Index index, Entry::Namespace base) -> void } -> void
96
92
  def register_included_hook(module_name, &hook)
97
93
  (@included_hooks[module_name] ||= []) << hook
98
94
  end
99
95
 
100
- sig { params(uri: URI::Generic, skip_require_paths_tree: T::Boolean).void }
96
+ #: (URI::Generic uri, ?skip_require_paths_tree: bool) -> void
101
97
  def delete(uri, skip_require_paths_tree: false)
102
98
  key = uri.to_s
103
99
  # For each constant discovered in `path`, delete the associated entry from the index. If there are no entries
@@ -127,7 +123,7 @@ module RubyIndexer
127
123
  @require_paths_tree.delete(require_path) if require_path
128
124
  end
129
125
 
130
- sig { params(entry: Entry, skip_prefix_tree: T::Boolean).void }
126
+ #: (Entry entry, ?skip_prefix_tree: bool) -> void
131
127
  def add(entry, skip_prefix_tree: false)
132
128
  name = entry.name
133
129
 
@@ -136,28 +132,19 @@ module RubyIndexer
136
132
  @entries_tree.insert(name, T.must(@entries[name])) unless skip_prefix_tree
137
133
  end
138
134
 
139
- sig { params(fully_qualified_name: String).returns(T.nilable(T::Array[Entry])) }
135
+ #: (String fully_qualified_name) -> Array[Entry]?
140
136
  def [](fully_qualified_name)
141
137
  @entries[fully_qualified_name.delete_prefix("::")]
142
138
  end
143
139
 
144
- sig { params(query: String).returns(T::Array[URI::Generic]) }
140
+ #: (String query) -> Array[URI::Generic]
145
141
  def search_require_paths(query)
146
142
  @require_paths_tree.search(query)
147
143
  end
148
144
 
149
145
  # Searches for a constant based on an unqualified name and returns the first possible match regardless of whether
150
146
  # there are more possible matching entries
151
- sig do
152
- params(
153
- name: String,
154
- ).returns(T.nilable(T::Array[T.any(
155
- Entry::Namespace,
156
- Entry::ConstantAlias,
157
- Entry::UnresolvedConstantAlias,
158
- Entry::Constant,
159
- )]))
160
- end
147
+ #: (String name) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]?
161
148
  def first_unqualified_const(name)
162
149
  # Look for an exact match first
163
150
  _name, entries = @entries.find do |const_name, _entries|
@@ -195,7 +182,7 @@ module RubyIndexer
195
182
  # [#<Entry::Class name="Foo::Baz">],
196
183
  # ]
197
184
  # ```
198
- sig { params(query: String, nesting: T.nilable(T::Array[String])).returns(T::Array[T::Array[Entry]]) }
185
+ #: (String query, ?Array[String]? nesting) -> Array[Array[Entry]]
199
186
  def prefix_search(query, nesting = nil)
200
187
  unless nesting
201
188
  results = @entries_tree.search(query)
@@ -214,7 +201,7 @@ module RubyIndexer
214
201
  end
215
202
 
216
203
  # Fuzzy searches index entries based on Jaro-Winkler similarity. If no query is provided, all entries are returned
217
- sig { params(query: T.nilable(String)).returns(T::Array[Entry]) }
204
+ #: (String? query) -> Array[Entry]
218
205
  def fuzzy_search(query)
219
206
  unless query
220
207
  entries = @entries.filter_map do |_name, entries|
@@ -238,12 +225,7 @@ module RubyIndexer
238
225
  results.flat_map(&:first)
239
226
  end
240
227
 
241
- sig do
242
- params(
243
- name: T.nilable(String),
244
- receiver_name: String,
245
- ).returns(T::Array[T.any(Entry::Member, Entry::MethodAlias)])
246
- end
228
+ #: (String? name, String receiver_name) -> Array[(Entry::Member | Entry::MethodAlias)]
247
229
  def method_completion_candidates(name, receiver_name)
248
230
  ancestors = linearized_ancestors_of(receiver_name)
249
231
 
@@ -286,17 +268,7 @@ module RubyIndexer
286
268
  completion_items.values.map!(&:first)
287
269
  end
288
270
 
289
- sig do
290
- params(
291
- name: String,
292
- nesting: T::Array[String],
293
- ).returns(T::Array[T::Array[T.any(
294
- Entry::Constant,
295
- Entry::ConstantAlias,
296
- Entry::Namespace,
297
- Entry::UnresolvedConstantAlias,
298
- )]])
299
- end
271
+ #: (String name, Array[String] nesting) -> Array[Array[(Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias)]]
300
272
  def constant_completion_candidates(name, nesting)
301
273
  # If we have a top level reference, then we don't need to include completions inside the current nesting
302
274
  if name.start_with?("::")
@@ -351,17 +323,7 @@ module RubyIndexer
351
323
  # nesting: the nesting structure where the reference was found (e.g.: ["Foo", "Bar"])
352
324
  # seen_names: this parameter should not be used by consumers of the api. It is used to avoid infinite recursion when
353
325
  # resolving circular references
354
- sig do
355
- params(
356
- name: String,
357
- nesting: T::Array[String],
358
- seen_names: T::Array[String],
359
- ).returns(T.nilable(T::Array[T.any(
360
- Entry::Namespace,
361
- Entry::ConstantAlias,
362
- Entry::UnresolvedConstantAlias,
363
- )]))
364
- end
326
+ #: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
365
327
  def resolve(name, nesting, seen_names = [])
366
328
  # If we have a top level reference, then we just search for it straight away ignoring the nesting
367
329
  if name.start_with?("::")
@@ -397,12 +359,7 @@ module RubyIndexer
397
359
  # Index all files for the given URIs, which defaults to what is configured. A block can be used to track and control
398
360
  # indexing progress. That block is invoked with the current progress percentage and should return `true` to continue
399
361
  # indexing or `false` to stop indexing.
400
- sig do
401
- params(
402
- uris: T::Array[URI::Generic],
403
- block: T.nilable(T.proc.params(progress: Integer).returns(T::Boolean)),
404
- ).void
405
- end
362
+ #: (?uris: Array[URI::Generic]) ?{ (Integer progress) -> bool } -> void
406
363
  def index_all(uris: @configuration.indexable_uris, &block)
407
364
  # When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
408
365
  # existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
@@ -412,8 +369,6 @@ module RubyIndexer
412
369
  "The index is not empty. To prevent invalid entries, `index_all` can only be called once."
413
370
  end
414
371
 
415
- @initial_indexing_completed = true
416
-
417
372
  RBSIndexer.new(self).index_ruby_core
418
373
  # Calculate how many paths are worth 1% of progress
419
374
  progress_step = (uris.length / 100.0).ceil
@@ -426,9 +381,11 @@ module RubyIndexer
426
381
 
427
382
  index_file(uri, collect_comments: false)
428
383
  end
384
+
385
+ @initial_indexing_completed = true
429
386
  end
430
387
 
431
- sig { params(uri: URI::Generic, source: String, collect_comments: T::Boolean).void }
388
+ #: (URI::Generic uri, String source, ?collect_comments: bool) -> void
432
389
  def index_single(uri, source, collect_comments: true)
433
390
  dispatcher = Prism::Dispatcher.new
434
391
 
@@ -450,7 +407,7 @@ module RubyIndexer
450
407
  end
451
408
 
452
409
  # Indexes a File URI by reading the contents from disk
453
- sig { params(uri: URI::Generic, collect_comments: T::Boolean).void }
410
+ #: (URI::Generic uri, ?collect_comments: bool) -> void
454
411
  def index_file(uri, collect_comments: true)
455
412
  index_single(uri, File.read(T.must(uri.full_path)), collect_comments: collect_comments)
456
413
  rescue Errno::EISDIR, Errno::ENOENT
@@ -468,7 +425,7 @@ module RubyIndexer
468
425
  # If we find an alias, then we want to follow its target. In the same example, if `Foo::Bar` is an alias to
469
426
  # `Something::Else`, then we first discover `Something::Else::Baz`. But `Something::Else::Baz` might contain other
470
427
  # aliases, so we have to invoke `follow_aliased_namespace` again to check until we only return a real name
471
- sig { params(name: String, seen_names: T::Array[String]).returns(String) }
428
+ #: (String name, ?Array[String] seen_names) -> String
472
429
  def follow_aliased_namespace(name, seen_names = [])
473
430
  parts = name.split("::")
474
431
  real_parts = []
@@ -501,14 +458,7 @@ module RubyIndexer
501
458
  # Attempts to find methods for a resolved fully qualified receiver name. Do not provide the `seen_names` parameter
502
459
  # as it is used only internally to prevent infinite loops when resolving circular aliases
503
460
  # Returns `nil` if the method does not exist on that receiver
504
- sig do
505
- params(
506
- method_name: String,
507
- receiver_name: String,
508
- seen_names: T::Array[String],
509
- inherited_only: T::Boolean,
510
- ).returns(T.nilable(T::Array[T.any(Entry::Member, Entry::MethodAlias)]))
511
- end
461
+ #: (String method_name, String receiver_name, ?Array[String] seen_names, ?inherited_only: bool) -> Array[(Entry::Member | Entry::MethodAlias)]?
512
462
  def resolve_method(method_name, receiver_name, seen_names = [], inherited_only: false)
513
463
  method_entries = self[method_name]
514
464
  return unless method_entries
@@ -546,7 +496,7 @@ module RubyIndexer
546
496
  # module that prepends another module, then the prepend module appears before the included module.
547
497
  #
548
498
  # The order of ancestors is [linearized_prepends, self, linearized_includes, linearized_superclass]
549
- sig { params(fully_qualified_name: String).returns(T::Array[String]) }
499
+ #: (String fully_qualified_name) -> Array[String]
550
500
  def linearized_ancestors_of(fully_qualified_name)
551
501
  # If we already computed the ancestors for this namespace, return it straight away
552
502
  cached_ancestors = @ancestors[fully_qualified_name]
@@ -624,7 +574,7 @@ module RubyIndexer
624
574
 
625
575
  # Resolves an instance variable name for a given owner name. This method will linearize the ancestors of the owner
626
576
  # and find inherited instance variables as well
627
- sig { params(variable_name: String, owner_name: String).returns(T.nilable(T::Array[Entry::InstanceVariable])) }
577
+ #: (String variable_name, String owner_name) -> Array[Entry::InstanceVariable]?
628
578
  def resolve_instance_variable(variable_name, owner_name)
629
579
  entries = T.cast(self[variable_name], T.nilable(T::Array[Entry::InstanceVariable]))
630
580
  return unless entries
@@ -635,7 +585,7 @@ module RubyIndexer
635
585
  entries.select { |e| ancestors.include?(e.owner&.name) }
636
586
  end
637
587
 
638
- sig { params(variable_name: String, owner_name: String).returns(T.nilable(T::Array[Entry::ClassVariable])) }
588
+ #: (String variable_name, String owner_name) -> Array[Entry::ClassVariable]?
639
589
  def resolve_class_variable(variable_name, owner_name)
640
590
  entries = self[variable_name]&.grep(Entry::ClassVariable)
641
591
  return unless entries&.any?
@@ -648,9 +598,7 @@ module RubyIndexer
648
598
 
649
599
  # Returns a list of possible candidates for completion of instance variables for a given owner name. The name must
650
600
  # include the `@` prefix
651
- sig do
652
- params(name: String, owner_name: String).returns(T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
653
- end
601
+ #: (String name, String owner_name) -> Array[(Entry::InstanceVariable | Entry::ClassVariable)]
654
602
  def instance_variable_completion_candidates(name, owner_name)
655
603
  entries = T.cast(prefix_search(name).flatten, T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
656
604
  # Avoid wasting time linearizing ancestors if we didn't find anything
@@ -679,7 +627,7 @@ module RubyIndexer
679
627
  variables
680
628
  end
681
629
 
682
- sig { params(name: String, owner_name: String).returns(T::Array[Entry::ClassVariable]) }
630
+ #: (String name, String owner_name) -> Array[Entry::ClassVariable]
683
631
  def class_variable_completion_candidates(name, owner_name)
684
632
  entries = T.cast(prefix_search(name).flatten, T::Array[Entry::ClassVariable])
685
633
  # Avoid wasting time linearizing ancestors if we didn't find anything
@@ -695,9 +643,7 @@ module RubyIndexer
695
643
  # declarations removed and that the ancestor linearization cache is cleared if necessary. If a block is passed, the
696
644
  # consumer of this API has to handle deleting and inserting/updating entries in the index instead of passing the
697
645
  # document's source (used to handle unsaved changes to files)
698
- sig do
699
- params(uri: URI::Generic, source: T.nilable(String), block: T.nilable(T.proc.params(index: Index).void)).void
700
- end
646
+ #: (URI::Generic uri, ?String? source) ?{ (Index index) -> void } -> void
701
647
  def handle_change(uri, source = nil, &block)
702
648
  key = uri.to_s
703
649
  original_entries = @uris_to_entries[key]
@@ -729,27 +675,27 @@ module RubyIndexer
729
675
  @ancestors.clear if original_map.any? { |name, hash| updated_map[name] != hash }
730
676
  end
731
677
 
732
- sig { returns(T::Boolean) }
678
+ #: -> bool
733
679
  def empty?
734
680
  @entries.empty?
735
681
  end
736
682
 
737
- sig { returns(T::Array[String]) }
683
+ #: -> Array[String]
738
684
  def names
739
685
  @entries.keys
740
686
  end
741
687
 
742
- sig { params(name: String).returns(T::Boolean) }
688
+ #: (String name) -> bool
743
689
  def indexed?(name)
744
690
  @entries.key?(name)
745
691
  end
746
692
 
747
- sig { returns(Integer) }
693
+ #: -> Integer
748
694
  def length
749
695
  @entries.count
750
696
  end
751
697
 
752
- sig { params(name: String).returns(Entry::SingletonClass) }
698
+ #: (String name) -> Entry::SingletonClass
753
699
  def existing_or_new_singleton_class(name)
754
700
  *_namespace, unqualified_name = name.split("::")
755
701
  full_singleton_name = "#{name}::<Class:#{unqualified_name}>"
@@ -772,12 +718,7 @@ module RubyIndexer
772
718
  singleton
773
719
  end
774
720
 
775
- sig do
776
- type_parameters(:T).params(
777
- uri: String,
778
- type: T.nilable(T::Class[T.all(T.type_parameter(:T), Entry)]),
779
- ).returns(T.nilable(T.any(T::Array[Entry], T::Array[T.type_parameter(:T)])))
780
- end
721
+ #: [T] (String uri, ?Class[(T & Entry)]? type) -> (Array[Entry] | Array[T])?
781
722
  def entries_for(uri, type = nil)
782
723
  entries = @uris_to_entries[uri.to_s]
783
724
  return entries unless type
@@ -789,7 +730,7 @@ module RubyIndexer
789
730
 
790
731
  # Always returns the linearized ancestors for the attached class, regardless of whether `name` refers to a singleton
791
732
  # or attached namespace
792
- sig { params(name: String).returns(T::Array[String]) }
733
+ #: (String name) -> Array[String]
793
734
  def linearized_attached_ancestors(name)
794
735
  name_parts = name.split("::")
795
736
 
@@ -802,7 +743,7 @@ module RubyIndexer
802
743
  end
803
744
 
804
745
  # Runs the registered included hooks
805
- sig { params(fully_qualified_name: String, nesting: T::Array[String]).void }
746
+ #: (String fully_qualified_name, Array[String] nesting) -> void
806
747
  def run_included_hooks(fully_qualified_name, nesting)
807
748
  return if @included_hooks.empty?
808
749
 
@@ -831,13 +772,7 @@ module RubyIndexer
831
772
 
832
773
  # Linearize mixins for an array of namespace entries. This method will mutate the `ancestors` array with the
833
774
  # linearized ancestors of the mixins
834
- sig do
835
- params(
836
- ancestors: T::Array[String],
837
- namespace_entries: T::Array[Entry::Namespace],
838
- nesting: T::Array[String],
839
- ).void
840
- end
775
+ #: (Array[String] ancestors, Array[Entry::Namespace] namespace_entries, Array[String] nesting) -> void
841
776
  def linearize_mixins(ancestors, namespace_entries, nesting)
842
777
  mixin_operations = namespace_entries.flat_map(&:mixin_operations)
843
778
  main_namespace_index = 0
@@ -878,16 +813,7 @@ module RubyIndexer
878
813
 
879
814
  # Linearize the superclass of a given namespace (including modules with the implicit `Module` superclass). This
880
815
  # method will mutate the `ancestors` array with the linearized ancestors of the superclass
881
- sig do
882
- params(
883
- ancestors: T::Array[String],
884
- attached_class_name: String,
885
- fully_qualified_name: String,
886
- namespace_entries: T::Array[Entry::Namespace],
887
- nesting: T::Array[String],
888
- singleton_levels: Integer,
889
- ).void
890
- end
816
+ #: (Array[String] ancestors, String attached_class_name, String fully_qualified_name, Array[Entry::Namespace] namespace_entries, Array[String] nesting, Integer singleton_levels) -> void
891
817
  def linearize_superclass( # rubocop:disable Metrics/ParameterLists
892
818
  ancestors,
893
819
  attached_class_name,
@@ -955,12 +881,7 @@ module RubyIndexer
955
881
 
956
882
  # Attempts to resolve an UnresolvedAlias into a resolved Alias. If the unresolved alias is pointing to a constant
957
883
  # that doesn't exist, then we return the same UnresolvedAlias
958
- sig do
959
- params(
960
- entry: Entry::UnresolvedConstantAlias,
961
- seen_names: T::Array[String],
962
- ).returns(T.any(Entry::ConstantAlias, Entry::UnresolvedConstantAlias))
963
- end
884
+ #: (Entry::UnresolvedConstantAlias entry, Array[String] seen_names) -> (Entry::ConstantAlias | Entry::UnresolvedConstantAlias)
964
885
  def resolve_alias(entry, seen_names)
965
886
  alias_name = entry.name
966
887
  return entry if seen_names.include?(alias_name)
@@ -983,17 +904,7 @@ module RubyIndexer
983
904
  resolved_alias
984
905
  end
985
906
 
986
- sig do
987
- params(
988
- name: String,
989
- nesting: T::Array[String],
990
- seen_names: T::Array[String],
991
- ).returns(T.nilable(T::Array[T.any(
992
- Entry::Namespace,
993
- Entry::ConstantAlias,
994
- Entry::UnresolvedConstantAlias,
995
- )]))
996
- end
907
+ #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
997
908
  def lookup_enclosing_scopes(name, nesting, seen_names)
998
909
  nesting.length.downto(1) do |i|
999
910
  namespace = T.must(nesting[0...i]).join("::")
@@ -1012,17 +923,7 @@ module RubyIndexer
1012
923
  nil
1013
924
  end
1014
925
 
1015
- sig do
1016
- params(
1017
- name: String,
1018
- nesting: T::Array[String],
1019
- seen_names: T::Array[String],
1020
- ).returns(T.nilable(T::Array[T.any(
1021
- Entry::Namespace,
1022
- Entry::ConstantAlias,
1023
- Entry::UnresolvedConstantAlias,
1024
- )]))
1025
- end
926
+ #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
1026
927
  def lookup_ancestor_chain(name, nesting, seen_names)
1027
928
  *nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
1028
929
  return if nesting_parts.empty?
@@ -1042,17 +943,7 @@ module RubyIndexer
1042
943
  nil
1043
944
  end
1044
945
 
1045
- sig do
1046
- params(
1047
- name: T.nilable(String),
1048
- nesting: T::Array[String],
1049
- ).returns(T::Array[T::Array[T.any(
1050
- Entry::Namespace,
1051
- Entry::ConstantAlias,
1052
- Entry::UnresolvedConstantAlias,
1053
- Entry::Constant,
1054
- )]])
1055
- end
946
+ #: (String? name, Array[String] nesting) -> Array[Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]]
1056
947
  def inherited_constant_completion_candidates(name, nesting)
1057
948
  namespace_entries = if name
1058
949
  *nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
@@ -1091,7 +982,7 @@ module RubyIndexer
1091
982
  # inside of the ["A", "B"] nesting, then we should not concatenate the nesting with the name or else we'll end up
1092
983
  # with `A::B::A::B::Foo`. This method will remove any redundant parts from the final name based on the reference and
1093
984
  # the nesting
1094
- sig { params(name: String, nesting: T::Array[String]).returns(String) }
985
+ #: (String name, Array[String] nesting) -> String
1095
986
  def build_non_redundant_full_name(name, nesting)
1096
987
  # If there's no nesting, then we can just return the name as is
1097
988
  return name if nesting.empty?
@@ -1112,18 +1003,7 @@ module RubyIndexer
1112
1003
  name_parts.join("::")
1113
1004
  end
1114
1005
 
1115
- sig do
1116
- params(
1117
- full_name: String,
1118
- seen_names: T::Array[String],
1119
- ).returns(
1120
- T.nilable(T::Array[T.any(
1121
- Entry::Namespace,
1122
- Entry::ConstantAlias,
1123
- Entry::UnresolvedConstantAlias,
1124
- )]),
1125
- )
1126
- end
1006
+ #: (String full_name, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
1127
1007
  def direct_or_aliased_constant(full_name, seen_names)
1128
1008
  entries = @entries[full_name] || @entries[follow_aliased_namespace(full_name)]
1129
1009
 
@@ -1139,13 +1019,7 @@ module RubyIndexer
1139
1019
 
1140
1020
  # Attempt to resolve a given unresolved method alias. This method returns the resolved alias if we managed to
1141
1021
  # identify the target or the same unresolved alias entry if we couldn't
1142
- sig do
1143
- params(
1144
- entry: Entry::UnresolvedMethodAlias,
1145
- receiver_name: String,
1146
- seen_names: T::Array[String],
1147
- ).returns(T.any(Entry::MethodAlias, Entry::UnresolvedMethodAlias))
1148
- end
1022
+ #: (Entry::UnresolvedMethodAlias entry, String receiver_name, Array[String] seen_names) -> (Entry::MethodAlias | Entry::UnresolvedMethodAlias)
1149
1023
  def resolve_method_alias(entry, receiver_name, seen_names)
1150
1024
  new_name = entry.new_name
1151
1025
  return entry if new_name == entry.old_name
@@ -3,20 +3,8 @@
3
3
 
4
4
  module RubyIndexer
5
5
  class Location
6
- extend T::Sig
7
-
8
6
  class << self
9
- extend T::Sig
10
-
11
- sig do
12
- params(
13
- prism_location: Prism::Location,
14
- code_units_cache: T.any(
15
- T.proc.params(arg0: Integer).returns(Integer),
16
- Prism::CodeUnitsCache,
17
- ),
18
- ).returns(T.attached_class)
19
- end
7
+ #: (Prism::Location prism_location, (^(Integer arg0) -> Integer | Prism::CodeUnitsCache) code_units_cache) -> instance
20
8
  def from_prism_location(prism_location, code_units_cache)
21
9
  new(
22
10
  prism_location.start_line,
@@ -27,17 +15,10 @@ module RubyIndexer
27
15
  end
28
16
  end
29
17
 
30
- sig { returns(Integer) }
18
+ #: Integer
31
19
  attr_reader :start_line, :end_line, :start_column, :end_column
32
20
 
33
- sig do
34
- params(
35
- start_line: Integer,
36
- end_line: Integer,
37
- start_column: Integer,
38
- end_column: Integer,
39
- ).void
40
- end
21
+ #: (Integer start_line, Integer end_line, Integer start_column, Integer end_column) -> void
41
22
  def initialize(start_line, end_line, start_column, end_column)
42
23
  @start_line = start_line
43
24
  @end_line = end_line
@@ -45,11 +26,7 @@ module RubyIndexer
45
26
  @end_column = end_column
46
27
  end
47
28
 
48
- sig do
49
- params(
50
- other: T.any(Location, Prism::Location),
51
- ).returns(T::Boolean)
52
- end
29
+ #: ((Location | Prism::Location) other) -> bool
53
30
  def ==(other)
54
31
  start_line == other.start_line &&
55
32
  end_line == other.end_line &&
@@ -33,12 +33,11 @@ module RubyIndexer
33
33
  #
34
34
  # See https://en.wikipedia.org/wiki/Trie for more information
35
35
  class PrefixTree
36
- extend T::Sig
37
36
  extend T::Generic
38
37
 
39
38
  Value = type_member
40
39
 
41
- sig { void }
40
+ #: -> void
42
41
  def initialize
43
42
  @root = T.let(Node.new("", ""), Node[Value])
44
43
  end
@@ -47,7 +46,7 @@ module RubyIndexer
47
46
  # return it as a result. The result is always an array of the type of value attribute to the generic `Value` type.
48
47
  # Notice that if the `Value` is an array, this method will return an array of arrays, where each entry is the array
49
48
  # of values for a given match
50
- sig { params(prefix: String).returns(T::Array[Value]) }
49
+ #: (String prefix) -> Array[Value]
51
50
  def search(prefix)
52
51
  node = find_node(prefix)
53
52
  return [] unless node
@@ -56,7 +55,7 @@ module RubyIndexer
56
55
  end
57
56
 
58
57
  # Inserts a `value` using the given `key`
59
- sig { params(key: String, value: Value).void }
58
+ #: (String key, Value value) -> void
60
59
  def insert(key, value)
61
60
  node = @root
62
61
 
@@ -73,7 +72,7 @@ module RubyIndexer
73
72
 
74
73
  # Deletes the entry identified by `key` from the tree. Notice that a partial match will still delete all entries
75
74
  # that match it. For example, if the tree contains `foo` and we ask to delete `fo`, then `foo` will be deleted
76
- sig { params(key: String).void }
75
+ #: (String key) -> void
77
76
  def delete(key)
78
77
  node = find_node(key)
79
78
  return unless node
@@ -93,7 +92,7 @@ module RubyIndexer
93
92
  private
94
93
 
95
94
  # Find a node that matches the given `key`
96
- sig { params(key: String).returns(T.nilable(Node[Value])) }
95
+ #: (String key) -> Node[Value]?
97
96
  def find_node(key)
98
97
  node = @root
99
98
 
@@ -108,27 +107,26 @@ module RubyIndexer
108
107
  end
109
108
 
110
109
  class Node
111
- extend T::Sig
112
110
  extend T::Generic
113
111
 
114
112
  Value = type_member
115
113
 
116
- sig { returns(T::Hash[String, Node[Value]]) }
114
+ #: Hash[String, Node[Value]]
117
115
  attr_reader :children
118
116
 
119
- sig { returns(String) }
117
+ #: String
120
118
  attr_reader :key
121
119
 
122
- sig { returns(Value) }
120
+ #: Value
123
121
  attr_accessor :value
124
122
 
125
- sig { returns(T::Boolean) }
123
+ #: bool
126
124
  attr_accessor :leaf
127
125
 
128
- sig { returns(T.nilable(Node[Value])) }
126
+ #: Node[Value]?
129
127
  attr_reader :parent
130
128
 
131
- sig { params(key: String, value: Value, parent: T.nilable(Node[Value])).void }
129
+ #: (String key, Value value, ?Node[Value]? parent) -> void
132
130
  def initialize(key, value, parent = nil)
133
131
  @key = key
134
132
  @value = value
@@ -137,7 +135,7 @@ module RubyIndexer
137
135
  @leaf = false
138
136
  end
139
137
 
140
- sig { returns(T::Array[Value]) }
138
+ #: -> Array[Value]
141
139
  def collect
142
140
  result = []
143
141
  result << @value if @leaf