ruby-lsp 0.23.10 → 0.23.13

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/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_language_server_aliases.rb +1 -1
  6. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +81 -115
  8. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +117 -166
  9. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -7
  10. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +89 -201
  11. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +63 -192
  12. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  13. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +14 -16
  14. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +22 -45
  15. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +42 -60
  16. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +9 -16
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +5 -9
  18. data/lib/ruby_indexer/test/classes_and_modules_test.rb +75 -0
  19. data/lib/ruby_indexer/test/configuration_test.rb +42 -3
  20. data/lib/ruby_indexer/test/index_test.rb +21 -0
  21. data/lib/ruby_indexer/test/method_test.rb +28 -2
  22. data/lib/ruby_indexer/test/rbs_indexer_test.rb +1 -1
  23. data/lib/ruby_lsp/addon.rb +44 -71
  24. data/lib/ruby_lsp/base_server.rb +31 -33
  25. data/lib/ruby_lsp/client_capabilities.rb +10 -12
  26. data/lib/ruby_lsp/document.rb +34 -45
  27. data/lib/ruby_lsp/erb_document.rb +24 -36
  28. data/lib/ruby_lsp/global_state.rb +51 -56
  29. data/lib/ruby_lsp/internal.rb +6 -0
  30. data/lib/ruby_lsp/listeners/code_lens.rb +81 -88
  31. data/lib/ruby_lsp/listeners/completion.rb +36 -55
  32. data/lib/ruby_lsp/listeners/definition.rb +37 -51
  33. data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
  34. data/lib/ruby_lsp/listeners/document_link.rb +43 -62
  35. data/lib/ruby_lsp/listeners/document_symbol.rb +35 -49
  36. data/lib/ruby_lsp/listeners/folding_ranges.rb +32 -39
  37. data/lib/ruby_lsp/listeners/hover.rb +81 -100
  38. data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
  39. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +42 -51
  40. data/lib/ruby_lsp/listeners/signature_help.rb +6 -25
  41. data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
  42. data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
  43. data/lib/ruby_lsp/listeners/test_style.rb +236 -0
  44. data/lib/ruby_lsp/node_context.rb +12 -39
  45. data/lib/ruby_lsp/rbs_document.rb +8 -6
  46. data/lib/ruby_lsp/requests/code_action_resolve.rb +10 -10
  47. data/lib/ruby_lsp/requests/code_actions.rb +14 -26
  48. data/lib/ruby_lsp/requests/code_lens.rb +6 -17
  49. data/lib/ruby_lsp/requests/completion.rb +7 -20
  50. data/lib/ruby_lsp/requests/completion_resolve.rb +5 -5
  51. data/lib/ruby_lsp/requests/definition.rb +8 -17
  52. data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
  53. data/lib/ruby_lsp/requests/discover_tests.rb +75 -0
  54. data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
  55. data/lib/ruby_lsp/requests/document_link.rb +6 -17
  56. data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
  57. data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
  58. data/lib/ruby_lsp/requests/formatting.rb +6 -9
  59. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +87 -0
  60. data/lib/ruby_lsp/requests/hover.rb +8 -18
  61. data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
  62. data/lib/ruby_lsp/requests/on_type_formatting.rb +28 -38
  63. data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
  64. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +4 -13
  65. data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
  66. data/lib/ruby_lsp/requests/references.rb +6 -36
  67. data/lib/ruby_lsp/requests/rename.rb +11 -37
  68. data/lib/ruby_lsp/requests/request.rb +7 -19
  69. data/lib/ruby_lsp/requests/selection_ranges.rb +5 -5
  70. data/lib/ruby_lsp/requests/semantic_highlighting.rb +12 -31
  71. data/lib/ruby_lsp/requests/show_syntax_tree.rb +5 -6
  72. data/lib/ruby_lsp/requests/signature_help.rb +8 -26
  73. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  74. data/lib/ruby_lsp/requests/support/common.rb +13 -48
  75. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
  76. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +9 -12
  77. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
  78. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  79. data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
  80. data/lib/ruby_lsp/requests/support/source_uri.rb +16 -30
  81. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
  82. data/lib/ruby_lsp/requests/support/test_item.rb +55 -0
  83. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
  84. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
  85. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
  86. data/lib/ruby_lsp/response_builders/document_symbol.rb +10 -16
  87. data/lib/ruby_lsp/response_builders/hover.rb +10 -13
  88. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  89. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +59 -87
  90. data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
  91. data/lib/ruby_lsp/response_builders/test_collection.rb +34 -0
  92. data/lib/ruby_lsp/ruby_document.rb +22 -60
  93. data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +109 -0
  94. data/lib/ruby_lsp/scope.rb +7 -11
  95. data/lib/ruby_lsp/server.rb +177 -72
  96. data/lib/ruby_lsp/setup_bundler.rb +61 -59
  97. data/lib/ruby_lsp/static_docs.rb +4 -7
  98. data/lib/ruby_lsp/store.rb +21 -40
  99. data/lib/ruby_lsp/test_helper.rb +3 -12
  100. data/lib/ruby_lsp/test_reporter.rb +207 -0
  101. data/lib/ruby_lsp/test_unit_test_runner.rb +98 -0
  102. data/lib/ruby_lsp/type_inferrer.rb +9 -13
  103. data/lib/ruby_lsp/utils.rb +37 -81
  104. metadata +13 -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,34 +36,31 @@ 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
  # {
61
57
  # "Foo" => [#<Entry::Class>, #<Entry::Class>],
62
58
  # "Foo::Bar" => [#<Entry::Class>],
63
59
  # }
64
- @entries = T.let({}, T::Hash[String, T::Array[Entry]])
60
+ @entries = {} #: Hash[String, Array[Entry]]
65
61
 
66
62
  # Holds all entries in the index using a prefix tree for searching based on prefixes to provide autocompletion
67
- @entries_tree = T.let(PrefixTree[T::Array[Entry]].new, PrefixTree[T::Array[Entry]])
63
+ @entries_tree = PrefixTree[T::Array[Entry]].new #: PrefixTree[Array[Entry]]
68
64
 
69
65
  # Holds references to where entries where discovered so that we can easily delete them
70
66
  # {
@@ -72,32 +68,29 @@ module RubyIndexer
72
68
  # "file:///my/project/bar.rb" => [#<Entry::Class>],
73
69
  # "untitled:Untitled-1" => [#<Entry::Class>],
74
70
  # }
75
- @uris_to_entries = T.let({}, T::Hash[String, T::Array[Entry]])
71
+ @uris_to_entries = {} #: Hash[String, Array[Entry]]
76
72
 
77
73
  # Holds all require paths for every indexed item so that we can provide autocomplete for requires
78
- @require_paths_tree = T.let(PrefixTree[URI::Generic].new, PrefixTree[URI::Generic])
74
+ @require_paths_tree = PrefixTree[URI::Generic].new #: PrefixTree[URI::Generic]
79
75
 
80
76
  # Holds the linearized ancestors list for every namespace
81
- @ancestors = T.let({}, T::Hash[String, T::Array[String]])
77
+ @ancestors = {} #: Hash[String, Array[String]]
82
78
 
83
79
  # Map of module name to included hooks that have to be executed when we include the given module
84
- @included_hooks = T.let(
85
- {},
86
- T::Hash[String, T::Array[T.proc.params(index: Index, base: Entry::Namespace).void]],
87
- )
80
+ @included_hooks = {} #: Hash[String, Array[^(Index index, Entry::Namespace base) -> void]]
88
81
 
89
- @configuration = T.let(RubyIndexer::Configuration.new, Configuration)
82
+ @configuration = RubyIndexer::Configuration.new #: Configuration
90
83
 
91
- @initial_indexing_completed = T.let(false, T::Boolean)
84
+ @initial_indexing_completed = false #: bool
92
85
  end
93
86
 
94
87
  # 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 }
88
+ #: (String module_name) { (Index index, Entry::Namespace base) -> void } -> void
96
89
  def register_included_hook(module_name, &hook)
97
90
  (@included_hooks[module_name] ||= []) << hook
98
91
  end
99
92
 
100
- sig { params(uri: URI::Generic, skip_require_paths_tree: T::Boolean).void }
93
+ #: (URI::Generic uri, ?skip_require_paths_tree: bool) -> void
101
94
  def delete(uri, skip_require_paths_tree: false)
102
95
  key = uri.to_s
103
96
  # For each constant discovered in `path`, delete the associated entry from the index. If there are no entries
@@ -127,7 +120,7 @@ module RubyIndexer
127
120
  @require_paths_tree.delete(require_path) if require_path
128
121
  end
129
122
 
130
- sig { params(entry: Entry, skip_prefix_tree: T::Boolean).void }
123
+ #: (Entry entry, ?skip_prefix_tree: bool) -> void
131
124
  def add(entry, skip_prefix_tree: false)
132
125
  name = entry.name
133
126
 
@@ -136,28 +129,19 @@ module RubyIndexer
136
129
  @entries_tree.insert(name, T.must(@entries[name])) unless skip_prefix_tree
137
130
  end
138
131
 
139
- sig { params(fully_qualified_name: String).returns(T.nilable(T::Array[Entry])) }
132
+ #: (String fully_qualified_name) -> Array[Entry]?
140
133
  def [](fully_qualified_name)
141
134
  @entries[fully_qualified_name.delete_prefix("::")]
142
135
  end
143
136
 
144
- sig { params(query: String).returns(T::Array[URI::Generic]) }
137
+ #: (String query) -> Array[URI::Generic]
145
138
  def search_require_paths(query)
146
139
  @require_paths_tree.search(query)
147
140
  end
148
141
 
149
142
  # Searches for a constant based on an unqualified name and returns the first possible match regardless of whether
150
143
  # 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
144
+ #: (String name) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]?
161
145
  def first_unqualified_const(name)
162
146
  # Look for an exact match first
163
147
  _name, entries = @entries.find do |const_name, _entries|
@@ -195,7 +179,7 @@ module RubyIndexer
195
179
  # [#<Entry::Class name="Foo::Baz">],
196
180
  # ]
197
181
  # ```
198
- sig { params(query: String, nesting: T.nilable(T::Array[String])).returns(T::Array[T::Array[Entry]]) }
182
+ #: (String query, ?Array[String]? nesting) -> Array[Array[Entry]]
199
183
  def prefix_search(query, nesting = nil)
200
184
  unless nesting
201
185
  results = @entries_tree.search(query)
@@ -214,7 +198,7 @@ module RubyIndexer
214
198
  end
215
199
 
216
200
  # 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]) }
201
+ #: (String? query) -> Array[Entry]
218
202
  def fuzzy_search(query)
219
203
  unless query
220
204
  entries = @entries.filter_map do |_name, entries|
@@ -238,12 +222,7 @@ module RubyIndexer
238
222
  results.flat_map(&:first)
239
223
  end
240
224
 
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
225
+ #: (String? name, String receiver_name) -> Array[(Entry::Member | Entry::MethodAlias)]
247
226
  def method_completion_candidates(name, receiver_name)
248
227
  ancestors = linearized_ancestors_of(receiver_name)
249
228
 
@@ -286,17 +265,7 @@ module RubyIndexer
286
265
  completion_items.values.map!(&:first)
287
266
  end
288
267
 
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
268
+ #: (String name, Array[String] nesting) -> Array[Array[(Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias)]]
300
269
  def constant_completion_candidates(name, nesting)
301
270
  # If we have a top level reference, then we don't need to include completions inside the current nesting
302
271
  if name.start_with?("::")
@@ -351,17 +320,7 @@ module RubyIndexer
351
320
  # nesting: the nesting structure where the reference was found (e.g.: ["Foo", "Bar"])
352
321
  # seen_names: this parameter should not be used by consumers of the api. It is used to avoid infinite recursion when
353
322
  # 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
323
+ #: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
365
324
  def resolve(name, nesting, seen_names = [])
366
325
  # If we have a top level reference, then we just search for it straight away ignoring the nesting
367
326
  if name.start_with?("::")
@@ -397,12 +356,7 @@ module RubyIndexer
397
356
  # Index all files for the given URIs, which defaults to what is configured. A block can be used to track and control
398
357
  # indexing progress. That block is invoked with the current progress percentage and should return `true` to continue
399
358
  # 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
359
+ #: (?uris: Array[URI::Generic]) ?{ (Integer progress) -> bool } -> void
406
360
  def index_all(uris: @configuration.indexable_uris, &block)
407
361
  # When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
408
362
  # existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
@@ -412,8 +366,6 @@ module RubyIndexer
412
366
  "The index is not empty. To prevent invalid entries, `index_all` can only be called once."
413
367
  end
414
368
 
415
- @initial_indexing_completed = true
416
-
417
369
  RBSIndexer.new(self).index_ruby_core
418
370
  # Calculate how many paths are worth 1% of progress
419
371
  progress_step = (uris.length / 100.0).ceil
@@ -426,9 +378,11 @@ module RubyIndexer
426
378
 
427
379
  index_file(uri, collect_comments: false)
428
380
  end
381
+
382
+ @initial_indexing_completed = true
429
383
  end
430
384
 
431
- sig { params(uri: URI::Generic, source: String, collect_comments: T::Boolean).void }
385
+ #: (URI::Generic uri, String source, ?collect_comments: bool) -> void
432
386
  def index_single(uri, source, collect_comments: true)
433
387
  dispatcher = Prism::Dispatcher.new
434
388
 
@@ -450,7 +404,7 @@ module RubyIndexer
450
404
  end
451
405
 
452
406
  # Indexes a File URI by reading the contents from disk
453
- sig { params(uri: URI::Generic, collect_comments: T::Boolean).void }
407
+ #: (URI::Generic uri, ?collect_comments: bool) -> void
454
408
  def index_file(uri, collect_comments: true)
455
409
  index_single(uri, File.read(T.must(uri.full_path)), collect_comments: collect_comments)
456
410
  rescue Errno::EISDIR, Errno::ENOENT
@@ -468,7 +422,7 @@ module RubyIndexer
468
422
  # If we find an alias, then we want to follow its target. In the same example, if `Foo::Bar` is an alias to
469
423
  # `Something::Else`, then we first discover `Something::Else::Baz`. But `Something::Else::Baz` might contain other
470
424
  # 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) }
425
+ #: (String name, ?Array[String] seen_names) -> String
472
426
  def follow_aliased_namespace(name, seen_names = [])
473
427
  parts = name.split("::")
474
428
  real_parts = []
@@ -501,14 +455,7 @@ module RubyIndexer
501
455
  # Attempts to find methods for a resolved fully qualified receiver name. Do not provide the `seen_names` parameter
502
456
  # as it is used only internally to prevent infinite loops when resolving circular aliases
503
457
  # 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
458
+ #: (String method_name, String receiver_name, ?Array[String] seen_names, ?inherited_only: bool) -> Array[(Entry::Member | Entry::MethodAlias)]?
512
459
  def resolve_method(method_name, receiver_name, seen_names = [], inherited_only: false)
513
460
  method_entries = self[method_name]
514
461
  return unless method_entries
@@ -546,7 +493,7 @@ module RubyIndexer
546
493
  # module that prepends another module, then the prepend module appears before the included module.
547
494
  #
548
495
  # The order of ancestors is [linearized_prepends, self, linearized_includes, linearized_superclass]
549
- sig { params(fully_qualified_name: String).returns(T::Array[String]) }
496
+ #: (String fully_qualified_name) -> Array[String]
550
497
  def linearized_ancestors_of(fully_qualified_name)
551
498
  # If we already computed the ancestors for this namespace, return it straight away
552
499
  cached_ancestors = @ancestors[fully_qualified_name]
@@ -624,7 +571,7 @@ module RubyIndexer
624
571
 
625
572
  # Resolves an instance variable name for a given owner name. This method will linearize the ancestors of the owner
626
573
  # and find inherited instance variables as well
627
- sig { params(variable_name: String, owner_name: String).returns(T.nilable(T::Array[Entry::InstanceVariable])) }
574
+ #: (String variable_name, String owner_name) -> Array[Entry::InstanceVariable]?
628
575
  def resolve_instance_variable(variable_name, owner_name)
629
576
  entries = T.cast(self[variable_name], T.nilable(T::Array[Entry::InstanceVariable]))
630
577
  return unless entries
@@ -635,7 +582,7 @@ module RubyIndexer
635
582
  entries.select { |e| ancestors.include?(e.owner&.name) }
636
583
  end
637
584
 
638
- sig { params(variable_name: String, owner_name: String).returns(T.nilable(T::Array[Entry::ClassVariable])) }
585
+ #: (String variable_name, String owner_name) -> Array[Entry::ClassVariable]?
639
586
  def resolve_class_variable(variable_name, owner_name)
640
587
  entries = self[variable_name]&.grep(Entry::ClassVariable)
641
588
  return unless entries&.any?
@@ -648,9 +595,7 @@ module RubyIndexer
648
595
 
649
596
  # Returns a list of possible candidates for completion of instance variables for a given owner name. The name must
650
597
  # include the `@` prefix
651
- sig do
652
- params(name: String, owner_name: String).returns(T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
653
- end
598
+ #: (String name, String owner_name) -> Array[(Entry::InstanceVariable | Entry::ClassVariable)]
654
599
  def instance_variable_completion_candidates(name, owner_name)
655
600
  entries = T.cast(prefix_search(name).flatten, T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
656
601
  # Avoid wasting time linearizing ancestors if we didn't find anything
@@ -679,7 +624,7 @@ module RubyIndexer
679
624
  variables
680
625
  end
681
626
 
682
- sig { params(name: String, owner_name: String).returns(T::Array[Entry::ClassVariable]) }
627
+ #: (String name, String owner_name) -> Array[Entry::ClassVariable]
683
628
  def class_variable_completion_candidates(name, owner_name)
684
629
  entries = T.cast(prefix_search(name).flatten, T::Array[Entry::ClassVariable])
685
630
  # Avoid wasting time linearizing ancestors if we didn't find anything
@@ -695,9 +640,7 @@ module RubyIndexer
695
640
  # declarations removed and that the ancestor linearization cache is cleared if necessary. If a block is passed, the
696
641
  # consumer of this API has to handle deleting and inserting/updating entries in the index instead of passing the
697
642
  # 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
643
+ #: (URI::Generic uri, ?String? source) ?{ (Index index) -> void } -> void
701
644
  def handle_change(uri, source = nil, &block)
702
645
  key = uri.to_s
703
646
  original_entries = @uris_to_entries[key]
@@ -729,27 +672,27 @@ module RubyIndexer
729
672
  @ancestors.clear if original_map.any? { |name, hash| updated_map[name] != hash }
730
673
  end
731
674
 
732
- sig { returns(T::Boolean) }
675
+ #: -> bool
733
676
  def empty?
734
677
  @entries.empty?
735
678
  end
736
679
 
737
- sig { returns(T::Array[String]) }
680
+ #: -> Array[String]
738
681
  def names
739
682
  @entries.keys
740
683
  end
741
684
 
742
- sig { params(name: String).returns(T::Boolean) }
685
+ #: (String name) -> bool
743
686
  def indexed?(name)
744
687
  @entries.key?(name)
745
688
  end
746
689
 
747
- sig { returns(Integer) }
690
+ #: -> Integer
748
691
  def length
749
692
  @entries.count
750
693
  end
751
694
 
752
- sig { params(name: String).returns(Entry::SingletonClass) }
695
+ #: (String name) -> Entry::SingletonClass
753
696
  def existing_or_new_singleton_class(name)
754
697
  *_namespace, unqualified_name = name.split("::")
755
698
  full_singleton_name = "#{name}::<Class:#{unqualified_name}>"
@@ -772,12 +715,7 @@ module RubyIndexer
772
715
  singleton
773
716
  end
774
717
 
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
718
+ #: [T] (String uri, ?Class[(T & Entry)]? type) -> (Array[Entry] | Array[T])?
781
719
  def entries_for(uri, type = nil)
782
720
  entries = @uris_to_entries[uri.to_s]
783
721
  return entries unless type
@@ -789,7 +727,7 @@ module RubyIndexer
789
727
 
790
728
  # Always returns the linearized ancestors for the attached class, regardless of whether `name` refers to a singleton
791
729
  # or attached namespace
792
- sig { params(name: String).returns(T::Array[String]) }
730
+ #: (String name) -> Array[String]
793
731
  def linearized_attached_ancestors(name)
794
732
  name_parts = name.split("::")
795
733
 
@@ -802,7 +740,7 @@ module RubyIndexer
802
740
  end
803
741
 
804
742
  # Runs the registered included hooks
805
- sig { params(fully_qualified_name: String, nesting: T::Array[String]).void }
743
+ #: (String fully_qualified_name, Array[String] nesting) -> void
806
744
  def run_included_hooks(fully_qualified_name, nesting)
807
745
  return if @included_hooks.empty?
808
746
 
@@ -831,13 +769,7 @@ module RubyIndexer
831
769
 
832
770
  # Linearize mixins for an array of namespace entries. This method will mutate the `ancestors` array with the
833
771
  # 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
772
+ #: (Array[String] ancestors, Array[Entry::Namespace] namespace_entries, Array[String] nesting) -> void
841
773
  def linearize_mixins(ancestors, namespace_entries, nesting)
842
774
  mixin_operations = namespace_entries.flat_map(&:mixin_operations)
843
775
  main_namespace_index = 0
@@ -878,16 +810,7 @@ module RubyIndexer
878
810
 
879
811
  # Linearize the superclass of a given namespace (including modules with the implicit `Module` superclass). This
880
812
  # 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
813
+ #: (Array[String] ancestors, String attached_class_name, String fully_qualified_name, Array[Entry::Namespace] namespace_entries, Array[String] nesting, Integer singleton_levels) -> void
891
814
  def linearize_superclass( # rubocop:disable Metrics/ParameterLists
892
815
  ancestors,
893
816
  attached_class_name,
@@ -955,12 +878,7 @@ module RubyIndexer
955
878
 
956
879
  # Attempts to resolve an UnresolvedAlias into a resolved Alias. If the unresolved alias is pointing to a constant
957
880
  # 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
881
+ #: (Entry::UnresolvedConstantAlias entry, Array[String] seen_names) -> (Entry::ConstantAlias | Entry::UnresolvedConstantAlias)
964
882
  def resolve_alias(entry, seen_names)
965
883
  alias_name = entry.name
966
884
  return entry if seen_names.include?(alias_name)
@@ -983,17 +901,7 @@ module RubyIndexer
983
901
  resolved_alias
984
902
  end
985
903
 
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
904
+ #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
997
905
  def lookup_enclosing_scopes(name, nesting, seen_names)
998
906
  nesting.length.downto(1) do |i|
999
907
  namespace = T.must(nesting[0...i]).join("::")
@@ -1012,17 +920,7 @@ module RubyIndexer
1012
920
  nil
1013
921
  end
1014
922
 
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
923
+ #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
1026
924
  def lookup_ancestor_chain(name, nesting, seen_names)
1027
925
  *nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
1028
926
  return if nesting_parts.empty?
@@ -1042,17 +940,7 @@ module RubyIndexer
1042
940
  nil
1043
941
  end
1044
942
 
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
943
+ #: (String? name, Array[String] nesting) -> Array[Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]]
1056
944
  def inherited_constant_completion_candidates(name, nesting)
1057
945
  namespace_entries = if name
1058
946
  *nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
@@ -1091,7 +979,7 @@ module RubyIndexer
1091
979
  # inside of the ["A", "B"] nesting, then we should not concatenate the nesting with the name or else we'll end up
1092
980
  # with `A::B::A::B::Foo`. This method will remove any redundant parts from the final name based on the reference and
1093
981
  # the nesting
1094
- sig { params(name: String, nesting: T::Array[String]).returns(String) }
982
+ #: (String name, Array[String] nesting) -> String
1095
983
  def build_non_redundant_full_name(name, nesting)
1096
984
  # If there's no nesting, then we can just return the name as is
1097
985
  return name if nesting.empty?
@@ -1112,18 +1000,7 @@ module RubyIndexer
1112
1000
  name_parts.join("::")
1113
1001
  end
1114
1002
 
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
1003
+ #: (String full_name, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
1127
1004
  def direct_or_aliased_constant(full_name, seen_names)
1128
1005
  entries = @entries[full_name] || @entries[follow_aliased_namespace(full_name)]
1129
1006
 
@@ -1139,13 +1016,7 @@ module RubyIndexer
1139
1016
 
1140
1017
  # Attempt to resolve a given unresolved method alias. This method returns the resolved alias if we managed to
1141
1018
  # 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
1019
+ #: (Entry::UnresolvedMethodAlias entry, String receiver_name, Array[String] seen_names) -> (Entry::MethodAlias | Entry::UnresolvedMethodAlias)
1149
1020
  def resolve_method_alias(entry, receiver_name, seen_names)
1150
1021
  new_name = entry.new_name
1151
1022
  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 &&