ruby-lsp 0.23.11 → 0.23.16

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-launcher +20 -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 +82 -116
  8. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +123 -169
  9. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -7
  10. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +92 -202
  11. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +116 -222
  12. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  13. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +18 -19
  14. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +22 -45
  15. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +47 -61
  16. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +5 -9
  18. data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
  19. data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
  20. data/lib/ruby_indexer/test/configuration_test.rb +48 -7
  21. data/lib/ruby_indexer/test/constant_test.rb +34 -34
  22. data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
  23. data/lib/ruby_indexer/test/index_test.rb +139 -135
  24. data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
  25. data/lib/ruby_indexer/test/method_test.rb +143 -117
  26. data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
  27. data/lib/ruby_indexer/test/rbs_indexer_test.rb +65 -71
  28. data/lib/ruby_indexer/test/test_case.rb +2 -2
  29. data/lib/ruby_indexer/test/uri_test.rb +15 -2
  30. data/lib/ruby_lsp/addon.rb +44 -71
  31. data/lib/ruby_lsp/base_server.rb +29 -32
  32. data/lib/ruby_lsp/client_capabilities.rb +10 -12
  33. data/lib/ruby_lsp/document.rb +39 -45
  34. data/lib/ruby_lsp/erb_document.rb +36 -40
  35. data/lib/ruby_lsp/global_state.rb +52 -57
  36. data/lib/ruby_lsp/internal.rb +2 -0
  37. data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
  38. data/lib/ruby_lsp/listeners/completion.rb +60 -66
  39. data/lib/ruby_lsp/listeners/definition.rb +38 -52
  40. data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
  41. data/lib/ruby_lsp/listeners/document_link.rb +46 -63
  42. data/lib/ruby_lsp/listeners/document_symbol.rb +38 -52
  43. data/lib/ruby_lsp/listeners/folding_ranges.rb +40 -43
  44. data/lib/ruby_lsp/listeners/hover.rb +83 -102
  45. data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
  46. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
  47. data/lib/ruby_lsp/listeners/signature_help.rb +11 -26
  48. data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
  49. data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
  50. data/lib/ruby_lsp/listeners/test_style.rb +160 -88
  51. data/lib/ruby_lsp/node_context.rb +12 -39
  52. data/lib/ruby_lsp/rbs_document.rb +8 -6
  53. data/lib/ruby_lsp/requests/code_action_resolve.rb +24 -25
  54. data/lib/ruby_lsp/requests/code_actions.rb +14 -26
  55. data/lib/ruby_lsp/requests/code_lens.rb +6 -17
  56. data/lib/ruby_lsp/requests/completion.rb +7 -20
  57. data/lib/ruby_lsp/requests/completion_resolve.rb +6 -6
  58. data/lib/ruby_lsp/requests/definition.rb +8 -17
  59. data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
  60. data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
  61. data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
  62. data/lib/ruby_lsp/requests/document_link.rb +6 -17
  63. data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
  64. data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
  65. data/lib/ruby_lsp/requests/formatting.rb +6 -9
  66. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +87 -0
  67. data/lib/ruby_lsp/requests/hover.rb +10 -20
  68. data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
  69. data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
  70. data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
  71. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +5 -15
  72. data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
  73. data/lib/ruby_lsp/requests/references.rb +8 -37
  74. data/lib/ruby_lsp/requests/rename.rb +19 -42
  75. data/lib/ruby_lsp/requests/request.rb +7 -19
  76. data/lib/ruby_lsp/requests/selection_ranges.rb +6 -6
  77. data/lib/ruby_lsp/requests/semantic_highlighting.rb +16 -35
  78. data/lib/ruby_lsp/requests/show_syntax_tree.rb +7 -8
  79. data/lib/ruby_lsp/requests/signature_help.rb +8 -26
  80. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  81. data/lib/ruby_lsp/requests/support/common.rb +16 -51
  82. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
  83. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +11 -14
  84. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
  85. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  86. data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
  87. data/lib/ruby_lsp/requests/support/source_uri.rb +20 -32
  88. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
  89. data/lib/ruby_lsp/requests/support/test_item.rb +10 -14
  90. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
  91. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
  92. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
  93. data/lib/ruby_lsp/response_builders/document_symbol.rb +13 -18
  94. data/lib/ruby_lsp/response_builders/hover.rb +11 -14
  95. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  96. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +60 -88
  97. data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
  98. data/lib/ruby_lsp/response_builders/test_collection.rb +6 -10
  99. data/lib/ruby_lsp/ruby_document.rb +24 -62
  100. data/lib/ruby_lsp/scope.rb +7 -11
  101. data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
  102. data/lib/ruby_lsp/server.rb +147 -79
  103. data/lib/ruby_lsp/setup_bundler.rb +65 -60
  104. data/lib/ruby_lsp/static_docs.rb +11 -7
  105. data/lib/ruby_lsp/store.rb +24 -42
  106. data/lib/ruby_lsp/test_helper.rb +2 -12
  107. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +164 -0
  108. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
  109. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
  110. data/lib/ruby_lsp/type_inferrer.rb +13 -14
  111. data/lib/ruby_lsp/utils.rb +49 -83
  112. metadata +9 -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,16 +10,17 @@ 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: T.nilable(String)).returns(T::Array[String]) }
23
+ #: (Array[String] stack, String? name) -> Array[String]
25
24
  def actual_nesting(stack, name)
26
25
  nesting = name ? stack + [name] : stack
27
26
  corrected_nesting = []
@@ -37,17 +36,7 @@ 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
- Prism::CallNode,
47
- Prism::MissingNode,
48
- ),
49
- ).returns(T.nilable(String))
50
- end
39
+ #: ((Prism::ConstantPathNode | Prism::ConstantReadNode | Prism::ConstantPathTargetNode | Prism::CallNode | Prism::MissingNode) node) -> String?
51
40
  def constant_name(node)
52
41
  case node
53
42
  when Prism::CallNode, Prism::MissingNode
@@ -61,17 +50,17 @@ module RubyIndexer
61
50
  end
62
51
  end
63
52
 
64
- sig { void }
53
+ #: -> void
65
54
  def initialize
66
55
  # Holds all entries in the index using the following format:
67
56
  # {
68
57
  # "Foo" => [#<Entry::Class>, #<Entry::Class>],
69
58
  # "Foo::Bar" => [#<Entry::Class>],
70
59
  # }
71
- @entries = T.let({}, T::Hash[String, T::Array[Entry]])
60
+ @entries = {} #: Hash[String, Array[Entry]]
72
61
 
73
62
  # Holds all entries in the index using a prefix tree for searching based on prefixes to provide autocompletion
74
- @entries_tree = T.let(PrefixTree[T::Array[Entry]].new, PrefixTree[T::Array[Entry]])
63
+ @entries_tree = PrefixTree[T::Array[Entry]].new #: PrefixTree[Array[Entry]]
75
64
 
76
65
  # Holds references to where entries where discovered so that we can easily delete them
77
66
  # {
@@ -79,32 +68,29 @@ module RubyIndexer
79
68
  # "file:///my/project/bar.rb" => [#<Entry::Class>],
80
69
  # "untitled:Untitled-1" => [#<Entry::Class>],
81
70
  # }
82
- @uris_to_entries = T.let({}, T::Hash[String, T::Array[Entry]])
71
+ @uris_to_entries = {} #: Hash[String, Array[Entry]]
83
72
 
84
73
  # Holds all require paths for every indexed item so that we can provide autocomplete for requires
85
- @require_paths_tree = T.let(PrefixTree[URI::Generic].new, PrefixTree[URI::Generic])
74
+ @require_paths_tree = PrefixTree[URI::Generic].new #: PrefixTree[URI::Generic]
86
75
 
87
76
  # Holds the linearized ancestors list for every namespace
88
- @ancestors = T.let({}, T::Hash[String, T::Array[String]])
77
+ @ancestors = {} #: Hash[String, Array[String]]
89
78
 
90
79
  # Map of module name to included hooks that have to be executed when we include the given module
91
- @included_hooks = T.let(
92
- {},
93
- T::Hash[String, T::Array[T.proc.params(index: Index, base: Entry::Namespace).void]],
94
- )
80
+ @included_hooks = {} #: Hash[String, Array[^(Index index, Entry::Namespace base) -> void]]
95
81
 
96
- @configuration = T.let(RubyIndexer::Configuration.new, Configuration)
82
+ @configuration = RubyIndexer::Configuration.new #: Configuration
97
83
 
98
- @initial_indexing_completed = T.let(false, T::Boolean)
84
+ @initial_indexing_completed = false #: bool
99
85
  end
100
86
 
101
87
  # Register an included `hook` that will be executed when `module_name` is included into any namespace
102
- 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
103
89
  def register_included_hook(module_name, &hook)
104
90
  (@included_hooks[module_name] ||= []) << hook
105
91
  end
106
92
 
107
- sig { params(uri: URI::Generic, skip_require_paths_tree: T::Boolean).void }
93
+ #: (URI::Generic uri, ?skip_require_paths_tree: bool) -> void
108
94
  def delete(uri, skip_require_paths_tree: false)
109
95
  key = uri.to_s
110
96
  # For each constant discovered in `path`, delete the associated entry from the index. If there are no entries
@@ -134,37 +120,34 @@ module RubyIndexer
134
120
  @require_paths_tree.delete(require_path) if require_path
135
121
  end
136
122
 
137
- sig { params(entry: Entry, skip_prefix_tree: T::Boolean).void }
123
+ #: (Entry entry, ?skip_prefix_tree: bool) -> void
138
124
  def add(entry, skip_prefix_tree: false)
139
125
  name = entry.name
140
126
 
141
127
  (@entries[name] ||= []) << entry
142
128
  (@uris_to_entries[entry.uri.to_s] ||= []) << entry
143
- @entries_tree.insert(name, T.must(@entries[name])) unless skip_prefix_tree
129
+
130
+ unless skip_prefix_tree
131
+ @entries_tree.insert(
132
+ name,
133
+ @entries[name], #: as !nil
134
+ )
135
+ end
144
136
  end
145
137
 
146
- sig { params(fully_qualified_name: String).returns(T.nilable(T::Array[Entry])) }
138
+ #: (String fully_qualified_name) -> Array[Entry]?
147
139
  def [](fully_qualified_name)
148
140
  @entries[fully_qualified_name.delete_prefix("::")]
149
141
  end
150
142
 
151
- sig { params(query: String).returns(T::Array[URI::Generic]) }
143
+ #: (String query) -> Array[URI::Generic]
152
144
  def search_require_paths(query)
153
145
  @require_paths_tree.search(query)
154
146
  end
155
147
 
156
148
  # Searches for a constant based on an unqualified name and returns the first possible match regardless of whether
157
149
  # there are more possible matching entries
158
- sig do
159
- params(
160
- name: String,
161
- ).returns(T.nilable(T::Array[T.any(
162
- Entry::Namespace,
163
- Entry::ConstantAlias,
164
- Entry::UnresolvedConstantAlias,
165
- Entry::Constant,
166
- )]))
167
- end
150
+ #: (String name) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]?
168
151
  def first_unqualified_const(name)
169
152
  # Look for an exact match first
170
153
  _name, entries = @entries.find do |const_name, _entries|
@@ -202,7 +185,7 @@ module RubyIndexer
202
185
  # [#<Entry::Class name="Foo::Baz">],
203
186
  # ]
204
187
  # ```
205
- sig { params(query: String, nesting: T.nilable(T::Array[String])).returns(T::Array[T::Array[Entry]]) }
188
+ #: (String query, ?Array[String]? nesting) -> Array[Array[Entry]]
206
189
  def prefix_search(query, nesting = nil)
207
190
  unless nesting
208
191
  results = @entries_tree.search(query)
@@ -211,7 +194,8 @@ module RubyIndexer
211
194
  end
212
195
 
213
196
  results = nesting.length.downto(0).flat_map do |i|
214
- prefix = T.must(nesting[0...i]).join("::")
197
+ prefix = nesting[0...i] #: as !nil
198
+ .join("::")
215
199
  namespaced_query = prefix.empty? ? query : "#{prefix}::#{query}"
216
200
  @entries_tree.search(namespaced_query)
217
201
  end
@@ -221,7 +205,7 @@ module RubyIndexer
221
205
  end
222
206
 
223
207
  # Fuzzy searches index entries based on Jaro-Winkler similarity. If no query is provided, all entries are returned
224
- sig { params(query: T.nilable(String)).returns(T::Array[Entry]) }
208
+ #: (String? query) -> Array[Entry]
225
209
  def fuzzy_search(query)
226
210
  unless query
227
211
  entries = @entries.filter_map do |_name, entries|
@@ -245,12 +229,7 @@ module RubyIndexer
245
229
  results.flat_map(&:first)
246
230
  end
247
231
 
248
- sig do
249
- params(
250
- name: T.nilable(String),
251
- receiver_name: String,
252
- ).returns(T::Array[T.any(Entry::Member, Entry::MethodAlias)])
253
- end
232
+ #: (String? name, String receiver_name) -> Array[(Entry::Member | Entry::MethodAlias)]
254
233
  def method_completion_candidates(name, receiver_name)
255
234
  ancestors = linearized_ancestors_of(receiver_name)
256
235
 
@@ -293,17 +272,7 @@ module RubyIndexer
293
272
  completion_items.values.map!(&:first)
294
273
  end
295
274
 
296
- sig do
297
- params(
298
- name: String,
299
- nesting: T::Array[String],
300
- ).returns(T::Array[T::Array[T.any(
301
- Entry::Constant,
302
- Entry::ConstantAlias,
303
- Entry::Namespace,
304
- Entry::UnresolvedConstantAlias,
305
- )]])
306
- end
275
+ #: (String name, Array[String] nesting) -> Array[Array[(Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias)]]
307
276
  def constant_completion_candidates(name, nesting)
308
277
  # If we have a top level reference, then we don't need to include completions inside the current nesting
309
278
  if name.start_with?("::")
@@ -326,7 +295,8 @@ module RubyIndexer
326
295
 
327
296
  # Constants defined in enclosing scopes
328
297
  nesting.length.downto(1) do |i|
329
- namespace = T.must(nesting[0...i]).join("::")
298
+ namespace = nesting[0...i] #: as !nil
299
+ .join("::")
330
300
  entries.concat(@entries_tree.search("#{namespace}::#{name}"))
331
301
  end
332
302
 
@@ -358,17 +328,7 @@ module RubyIndexer
358
328
  # nesting: the nesting structure where the reference was found (e.g.: ["Foo", "Bar"])
359
329
  # seen_names: this parameter should not be used by consumers of the api. It is used to avoid infinite recursion when
360
330
  # resolving circular references
361
- sig do
362
- params(
363
- name: String,
364
- nesting: T::Array[String],
365
- seen_names: T::Array[String],
366
- ).returns(T.nilable(T::Array[T.any(
367
- Entry::Namespace,
368
- Entry::ConstantAlias,
369
- Entry::UnresolvedConstantAlias,
370
- )]))
371
- end
331
+ #: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
372
332
  def resolve(name, nesting, seen_names = [])
373
333
  # If we have a top level reference, then we just search for it straight away ignoring the nesting
374
334
  if name.start_with?("::")
@@ -404,12 +364,7 @@ module RubyIndexer
404
364
  # Index all files for the given URIs, which defaults to what is configured. A block can be used to track and control
405
365
  # indexing progress. That block is invoked with the current progress percentage and should return `true` to continue
406
366
  # indexing or `false` to stop indexing.
407
- sig do
408
- params(
409
- uris: T::Array[URI::Generic],
410
- block: T.nilable(T.proc.params(progress: Integer).returns(T::Boolean)),
411
- ).void
412
- end
367
+ #: (?uris: Array[URI::Generic]) ?{ (Integer progress) -> bool } -> void
413
368
  def index_all(uris: @configuration.indexable_uris, &block)
414
369
  # When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
415
370
  # existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
@@ -419,8 +374,6 @@ module RubyIndexer
419
374
  "The index is not empty. To prevent invalid entries, `index_all` can only be called once."
420
375
  end
421
376
 
422
- @initial_indexing_completed = true
423
-
424
377
  RBSIndexer.new(self).index_ruby_core
425
378
  # Calculate how many paths are worth 1% of progress
426
379
  progress_step = (uris.length / 100.0).ceil
@@ -433,9 +386,11 @@ module RubyIndexer
433
386
 
434
387
  index_file(uri, collect_comments: false)
435
388
  end
389
+
390
+ @initial_indexing_completed = true
436
391
  end
437
392
 
438
- sig { params(uri: URI::Generic, source: String, collect_comments: T::Boolean).void }
393
+ #: (URI::Generic uri, String source, ?collect_comments: bool) -> void
439
394
  def index_single(uri, source, collect_comments: true)
440
395
  dispatcher = Prism::Dispatcher.new
441
396
 
@@ -457,9 +412,10 @@ module RubyIndexer
457
412
  end
458
413
 
459
414
  # Indexes a File URI by reading the contents from disk
460
- sig { params(uri: URI::Generic, collect_comments: T::Boolean).void }
415
+ #: (URI::Generic uri, ?collect_comments: bool) -> void
461
416
  def index_file(uri, collect_comments: true)
462
- index_single(uri, File.read(T.must(uri.full_path)), collect_comments: collect_comments)
417
+ path = uri.full_path #: as !nil
418
+ index_single(uri, File.read(path), collect_comments: collect_comments)
463
419
  rescue Errno::EISDIR, Errno::ENOENT
464
420
  # If `path` is a directory, just ignore it and continue indexing. If the file doesn't exist, then we also ignore
465
421
  # it
@@ -475,13 +431,14 @@ module RubyIndexer
475
431
  # If we find an alias, then we want to follow its target. In the same example, if `Foo::Bar` is an alias to
476
432
  # `Something::Else`, then we first discover `Something::Else::Baz`. But `Something::Else::Baz` might contain other
477
433
  # aliases, so we have to invoke `follow_aliased_namespace` again to check until we only return a real name
478
- sig { params(name: String, seen_names: T::Array[String]).returns(String) }
434
+ #: (String name, ?Array[String] seen_names) -> String
479
435
  def follow_aliased_namespace(name, seen_names = [])
480
436
  parts = name.split("::")
481
437
  real_parts = []
482
438
 
483
439
  (parts.length - 1).downto(0) do |i|
484
- current_name = T.must(parts[0..i]).join("::")
440
+ current_name = parts[0..i] #: as !nil
441
+ .join("::")
485
442
  entry = @entries[current_name]&.first
486
443
 
487
444
  case entry
@@ -498,7 +455,9 @@ module RubyIndexer
498
455
  target = resolved.target
499
456
  return follow_aliased_namespace("#{target}::#{real_parts.join("::")}", seen_names)
500
457
  else
501
- real_parts.unshift(T.must(parts[i]))
458
+ real_parts.unshift(
459
+ parts[i], #: as !nil
460
+ )
502
461
  end
503
462
  end
504
463
 
@@ -508,14 +467,7 @@ module RubyIndexer
508
467
  # Attempts to find methods for a resolved fully qualified receiver name. Do not provide the `seen_names` parameter
509
468
  # as it is used only internally to prevent infinite loops when resolving circular aliases
510
469
  # Returns `nil` if the method does not exist on that receiver
511
- sig do
512
- params(
513
- method_name: String,
514
- receiver_name: String,
515
- seen_names: T::Array[String],
516
- inherited_only: T::Boolean,
517
- ).returns(T.nilable(T::Array[T.any(Entry::Member, Entry::MethodAlias)]))
518
- end
470
+ #: (String method_name, String receiver_name, ?Array[String] seen_names, ?inherited_only: bool) -> Array[(Entry::Member | Entry::MethodAlias)]?
519
471
  def resolve_method(method_name, receiver_name, seen_names = [], inherited_only: false)
520
472
  method_entries = self[method_name]
521
473
  return unless method_entries
@@ -553,7 +505,7 @@ module RubyIndexer
553
505
  # module that prepends another module, then the prepend module appears before the included module.
554
506
  #
555
507
  # The order of ancestors is [linearized_prepends, self, linearized_includes, linearized_superclass]
556
- sig { params(fully_qualified_name: String).returns(T::Array[String]) }
508
+ #: (String fully_qualified_name) -> Array[String]
557
509
  def linearized_ancestors_of(fully_qualified_name)
558
510
  # If we already computed the ancestors for this namespace, return it straight away
559
511
  cached_ancestors = @ancestors[fully_qualified_name]
@@ -602,11 +554,12 @@ module RubyIndexer
602
554
 
603
555
  # The original nesting where we discovered this namespace, so that we resolve the correct names of the
604
556
  # included/prepended/extended modules and parent classes
605
- nesting = T.must(namespaces.first).nesting.flat_map { |n| n.split("::") }
557
+ nesting = namespaces.first #: as !nil
558
+ .nesting.flat_map { |n| n.split("::") }
606
559
 
607
560
  if nesting.any?
608
561
  singleton_levels.times do
609
- nesting << "<Class:#{T.must(nesting.last)}>"
562
+ nesting << "<Class:#{nesting.last}>"
610
563
  end
611
564
  end
612
565
 
@@ -631,7 +584,7 @@ module RubyIndexer
631
584
 
632
585
  # Resolves an instance variable name for a given owner name. This method will linearize the ancestors of the owner
633
586
  # and find inherited instance variables as well
634
- sig { params(variable_name: String, owner_name: String).returns(T.nilable(T::Array[Entry::InstanceVariable])) }
587
+ #: (String variable_name, String owner_name) -> Array[Entry::InstanceVariable]?
635
588
  def resolve_instance_variable(variable_name, owner_name)
636
589
  entries = T.cast(self[variable_name], T.nilable(T::Array[Entry::InstanceVariable]))
637
590
  return unless entries
@@ -642,7 +595,7 @@ module RubyIndexer
642
595
  entries.select { |e| ancestors.include?(e.owner&.name) }
643
596
  end
644
597
 
645
- sig { params(variable_name: String, owner_name: String).returns(T.nilable(T::Array[Entry::ClassVariable])) }
598
+ #: (String variable_name, String owner_name) -> Array[Entry::ClassVariable]?
646
599
  def resolve_class_variable(variable_name, owner_name)
647
600
  entries = self[variable_name]&.grep(Entry::ClassVariable)
648
601
  return unless entries&.any?
@@ -655,9 +608,7 @@ module RubyIndexer
655
608
 
656
609
  # Returns a list of possible candidates for completion of instance variables for a given owner name. The name must
657
610
  # include the `@` prefix
658
- sig do
659
- params(name: String, owner_name: String).returns(T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
660
- end
611
+ #: (String name, String owner_name) -> Array[(Entry::InstanceVariable | Entry::ClassVariable)]
661
612
  def instance_variable_completion_candidates(name, owner_name)
662
613
  entries = T.cast(prefix_search(name).flatten, T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
663
614
  # Avoid wasting time linearizing ancestors if we didn't find anything
@@ -674,7 +625,8 @@ module RubyIndexer
674
625
  name_parts = owner_name.split("::")
675
626
 
676
627
  if name_parts.last&.start_with?("<Class:")
677
- attached_name = T.must(name_parts[0..-2]).join("::")
628
+ attached_name = name_parts[0..-2] #: as !nil
629
+ .join("::")
678
630
  attached_ancestors = linearized_ancestors_of(attached_name)
679
631
  variables.concat(class_variables.select { |e| attached_ancestors.any?(e.owner&.name) })
680
632
  else
@@ -686,7 +638,7 @@ module RubyIndexer
686
638
  variables
687
639
  end
688
640
 
689
- sig { params(name: String, owner_name: String).returns(T::Array[Entry::ClassVariable]) }
641
+ #: (String name, String owner_name) -> Array[Entry::ClassVariable]
690
642
  def class_variable_completion_candidates(name, owner_name)
691
643
  entries = T.cast(prefix_search(name).flatten, T::Array[Entry::ClassVariable])
692
644
  # Avoid wasting time linearizing ancestors if we didn't find anything
@@ -702,9 +654,7 @@ module RubyIndexer
702
654
  # declarations removed and that the ancestor linearization cache is cleared if necessary. If a block is passed, the
703
655
  # consumer of this API has to handle deleting and inserting/updating entries in the index instead of passing the
704
656
  # document's source (used to handle unsaved changes to files)
705
- sig do
706
- params(uri: URI::Generic, source: T.nilable(String), block: T.nilable(T.proc.params(index: Index).void)).void
707
- end
657
+ #: (URI::Generic uri, ?String? source) ?{ (Index index) -> void } -> void
708
658
  def handle_change(uri, source = nil, &block)
709
659
  key = uri.to_s
710
660
  original_entries = @uris_to_entries[key]
@@ -713,7 +663,10 @@ module RubyIndexer
713
663
  block.call(self)
714
664
  else
715
665
  delete(uri)
716
- index_single(uri, T.must(source))
666
+ index_single(
667
+ uri,
668
+ source, #: as !nil
669
+ )
717
670
  end
718
671
 
719
672
  updated_entries = @uris_to_entries[key]
@@ -736,34 +689,34 @@ module RubyIndexer
736
689
  @ancestors.clear if original_map.any? { |name, hash| updated_map[name] != hash }
737
690
  end
738
691
 
739
- sig { returns(T::Boolean) }
692
+ #: -> bool
740
693
  def empty?
741
694
  @entries.empty?
742
695
  end
743
696
 
744
- sig { returns(T::Array[String]) }
697
+ #: -> Array[String]
745
698
  def names
746
699
  @entries.keys
747
700
  end
748
701
 
749
- sig { params(name: String).returns(T::Boolean) }
702
+ #: (String name) -> bool
750
703
  def indexed?(name)
751
704
  @entries.key?(name)
752
705
  end
753
706
 
754
- sig { returns(Integer) }
707
+ #: -> Integer
755
708
  def length
756
709
  @entries.count
757
710
  end
758
711
 
759
- sig { params(name: String).returns(Entry::SingletonClass) }
712
+ #: (String name) -> Entry::SingletonClass
760
713
  def existing_or_new_singleton_class(name)
761
714
  *_namespace, unqualified_name = name.split("::")
762
715
  full_singleton_name = "#{name}::<Class:#{unqualified_name}>"
763
716
  singleton = T.cast(self[full_singleton_name]&.first, T.nilable(Entry::SingletonClass))
764
717
 
765
718
  unless singleton
766
- attached_ancestor = T.must(self[name]&.first)
719
+ attached_ancestor = self[name]&.first #: as !nil
767
720
 
768
721
  singleton = Entry::SingletonClass.new(
769
722
  [full_singleton_name],
@@ -779,12 +732,7 @@ module RubyIndexer
779
732
  singleton
780
733
  end
781
734
 
782
- sig do
783
- type_parameters(:T).params(
784
- uri: String,
785
- type: T.nilable(T::Class[T.all(T.type_parameter(:T), Entry)]),
786
- ).returns(T.nilable(T.any(T::Array[Entry], T::Array[T.type_parameter(:T)])))
787
- end
735
+ #: [T] (String uri, ?Class[(T & Entry)]? type) -> (Array[Entry] | Array[T])?
788
736
  def entries_for(uri, type = nil)
789
737
  entries = @uris_to_entries[uri.to_s]
790
738
  return entries unless type
@@ -796,12 +744,13 @@ module RubyIndexer
796
744
 
797
745
  # Always returns the linearized ancestors for the attached class, regardless of whether `name` refers to a singleton
798
746
  # or attached namespace
799
- sig { params(name: String).returns(T::Array[String]) }
747
+ #: (String name) -> Array[String]
800
748
  def linearized_attached_ancestors(name)
801
749
  name_parts = name.split("::")
802
750
 
803
751
  if name_parts.last&.start_with?("<Class:")
804
- attached_name = T.must(name_parts[0..-2]).join("::")
752
+ attached_name = name_parts[0..-2] #: as !nil
753
+ .join("::")
805
754
  linearized_ancestors_of(attached_name)
806
755
  else
807
756
  linearized_ancestors_of(name)
@@ -809,7 +758,7 @@ module RubyIndexer
809
758
  end
810
759
 
811
760
  # Runs the registered included hooks
812
- sig { params(fully_qualified_name: String, nesting: T::Array[String]).void }
761
+ #: (String fully_qualified_name, Array[String] nesting) -> void
813
762
  def run_included_hooks(fully_qualified_name, nesting)
814
763
  return if @included_hooks.empty?
815
764
 
@@ -824,7 +773,8 @@ module RubyIndexer
824
773
  resolved_modules = resolve(operation.module_name, nesting)
825
774
  next unless resolved_modules
826
775
 
827
- module_name = T.must(resolved_modules.first).name
776
+ module_name = resolved_modules.first #: as !nil
777
+ .name
828
778
 
829
779
  # Then we grab any hooks registered for that module
830
780
  hooks = @included_hooks[module_name]
@@ -838,13 +788,7 @@ module RubyIndexer
838
788
 
839
789
  # Linearize mixins for an array of namespace entries. This method will mutate the `ancestors` array with the
840
790
  # linearized ancestors of the mixins
841
- sig do
842
- params(
843
- ancestors: T::Array[String],
844
- namespace_entries: T::Array[Entry::Namespace],
845
- nesting: T::Array[String],
846
- ).void
847
- end
791
+ #: (Array[String] ancestors, Array[Entry::Namespace] namespace_entries, Array[String] nesting) -> void
848
792
  def linearize_mixins(ancestors, namespace_entries, nesting)
849
793
  mixin_operations = namespace_entries.flat_map(&:mixin_operations)
850
794
  main_namespace_index = 0
@@ -853,7 +797,8 @@ module RubyIndexer
853
797
  resolved_module = resolve(operation.module_name, nesting)
854
798
  next unless resolved_module
855
799
 
856
- module_fully_qualified_name = T.must(resolved_module.first).name
800
+ module_fully_qualified_name = resolved_module.first #: as !nil
801
+ .name
857
802
 
858
803
  case operation
859
804
  when Entry::Prepend
@@ -865,36 +810,27 @@ module RubyIndexer
865
810
  # When there are duplicate prepended modules, we have to insert the new prepends after the existing ones. For
866
811
  # example, if the current ancestors are `["A", "Foo"]` and we try to prepend `["A", "B"]`, then `"B"` has to
867
812
  # be inserted after `"A`
868
- uniq_prepends = linearized_prepends - T.must(ancestors[0...main_namespace_index])
813
+ prepended_ancestors = ancestors[0...main_namespace_index] #: as !nil
814
+ uniq_prepends = linearized_prepends - prepended_ancestors
869
815
  insert_position = linearized_prepends.length - uniq_prepends.length
870
816
 
871
- T.unsafe(ancestors).insert(
872
- insert_position,
873
- *(linearized_prepends - T.must(ancestors[0...main_namespace_index])),
874
- )
817
+ ancestors #: as untyped
818
+ .insert(insert_position, *uniq_prepends)
875
819
 
876
820
  main_namespace_index += linearized_prepends.length
877
821
  when Entry::Include
878
822
  # When including a module, Ruby will always prevent duplicate entries in case the module has already been
879
823
  # prepended or included
880
824
  linearized_includes = linearized_ancestors_of(module_fully_qualified_name)
881
- T.unsafe(ancestors).insert(main_namespace_index + 1, *(linearized_includes - ancestors))
825
+ ancestors #: as untyped
826
+ .insert(main_namespace_index + 1, *(linearized_includes - ancestors))
882
827
  end
883
828
  end
884
829
  end
885
830
 
886
831
  # Linearize the superclass of a given namespace (including modules with the implicit `Module` superclass). This
887
832
  # method will mutate the `ancestors` array with the linearized ancestors of the superclass
888
- sig do
889
- params(
890
- ancestors: T::Array[String],
891
- attached_class_name: String,
892
- fully_qualified_name: String,
893
- namespace_entries: T::Array[Entry::Namespace],
894
- nesting: T::Array[String],
895
- singleton_levels: Integer,
896
- ).void
897
- end
833
+ #: (Array[String] ancestors, String attached_class_name, String fully_qualified_name, Array[Entry::Namespace] namespace_entries, Array[String] nesting, Integer singleton_levels) -> void
898
834
  def linearize_superclass( # rubocop:disable Metrics/ParameterLists
899
835
  ancestors,
900
836
  attached_class_name,
@@ -917,7 +853,7 @@ module RubyIndexer
917
853
  if superclass
918
854
  # If the user makes a mistake and creates a class that inherits from itself, this method would throw a stack
919
855
  # error. We need to ensure that this isn't the case
920
- parent_class = T.must(superclass.parent_class)
856
+ parent_class = superclass.parent_class #: as !nil
921
857
 
922
858
  resolved_parent_class = resolve(parent_class, nesting)
923
859
  parent_class_name = resolved_parent_class&.first&.name
@@ -962,12 +898,7 @@ module RubyIndexer
962
898
 
963
899
  # Attempts to resolve an UnresolvedAlias into a resolved Alias. If the unresolved alias is pointing to a constant
964
900
  # that doesn't exist, then we return the same UnresolvedAlias
965
- sig do
966
- params(
967
- entry: Entry::UnresolvedConstantAlias,
968
- seen_names: T::Array[String],
969
- ).returns(T.any(Entry::ConstantAlias, Entry::UnresolvedConstantAlias))
970
- end
901
+ #: (Entry::UnresolvedConstantAlias entry, Array[String] seen_names) -> (Entry::ConstantAlias | Entry::UnresolvedConstantAlias)
971
902
  def resolve_alias(entry, seen_names)
972
903
  alias_name = entry.name
973
904
  return entry if seen_names.include?(alias_name)
@@ -977,11 +908,12 @@ module RubyIndexer
977
908
  target = resolve(entry.target, entry.nesting, seen_names)
978
909
  return entry unless target
979
910
 
980
- target_name = T.must(target.first).name
911
+ target_name = target.first #: as !nil
912
+ .name
981
913
  resolved_alias = Entry::ConstantAlias.new(target_name, entry)
982
914
 
983
915
  # Replace the UnresolvedAlias by a resolved one so that we don't have to do this again later
984
- original_entries = T.must(@entries[alias_name])
916
+ original_entries = @entries[alias_name] #: as !nil
985
917
  original_entries.delete(entry)
986
918
  original_entries << resolved_alias
987
919
 
@@ -990,20 +922,11 @@ module RubyIndexer
990
922
  resolved_alias
991
923
  end
992
924
 
993
- sig do
994
- params(
995
- name: String,
996
- nesting: T::Array[String],
997
- seen_names: T::Array[String],
998
- ).returns(T.nilable(T::Array[T.any(
999
- Entry::Namespace,
1000
- Entry::ConstantAlias,
1001
- Entry::UnresolvedConstantAlias,
1002
- )]))
1003
- end
925
+ #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
1004
926
  def lookup_enclosing_scopes(name, nesting, seen_names)
1005
927
  nesting.length.downto(1) do |i|
1006
- namespace = T.must(nesting[0...i]).join("::")
928
+ namespace = nesting[0...i] #: as !nil
929
+ .join("::")
1007
930
 
1008
931
  # If we find an entry with `full_name` directly, then we can already return it, even if it contains aliases -
1009
932
  # because the user might be trying to jump to the alias definition.
@@ -1019,17 +942,7 @@ module RubyIndexer
1019
942
  nil
1020
943
  end
1021
944
 
1022
- sig do
1023
- params(
1024
- name: String,
1025
- nesting: T::Array[String],
1026
- seen_names: T::Array[String],
1027
- ).returns(T.nilable(T::Array[T.any(
1028
- Entry::Namespace,
1029
- Entry::ConstantAlias,
1030
- Entry::UnresolvedConstantAlias,
1031
- )]))
1032
- end
945
+ #: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
1033
946
  def lookup_ancestor_chain(name, nesting, seen_names)
1034
947
  *nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
1035
948
  return if nesting_parts.empty?
@@ -1037,7 +950,9 @@ module RubyIndexer
1037
950
  namespace_entries = resolve(nesting_parts.join("::"), [], seen_names)
1038
951
  return unless namespace_entries
1039
952
 
1040
- ancestors = nesting_parts.empty? ? [] : linearized_ancestors_of(T.must(namespace_entries.first).name)
953
+ namespace_name = namespace_entries.first #: as !nil
954
+ .name
955
+ ancestors = nesting_parts.empty? ? [] : linearized_ancestors_of(namespace_name)
1041
956
 
1042
957
  ancestors.each do |ancestor_name|
1043
958
  entries = direct_or_aliased_constant("#{ancestor_name}::#{constant_name}", seen_names)
@@ -1049,17 +964,7 @@ module RubyIndexer
1049
964
  nil
1050
965
  end
1051
966
 
1052
- sig do
1053
- params(
1054
- name: T.nilable(String),
1055
- nesting: T::Array[String],
1056
- ).returns(T::Array[T::Array[T.any(
1057
- Entry::Namespace,
1058
- Entry::ConstantAlias,
1059
- Entry::UnresolvedConstantAlias,
1060
- Entry::Constant,
1061
- )]])
1062
- end
967
+ #: (String? name, Array[String] nesting) -> Array[Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]]
1063
968
  def inherited_constant_completion_candidates(name, nesting)
1064
969
  namespace_entries = if name
1065
970
  *nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
@@ -1071,7 +976,9 @@ module RubyIndexer
1071
976
  end
1072
977
  return [] unless namespace_entries
1073
978
 
1074
- ancestors = linearized_ancestors_of(T.must(namespace_entries.first).name)
979
+ namespace_name = namespace_entries.first #: as !nil
980
+ .name
981
+ ancestors = linearized_ancestors_of(namespace_name)
1075
982
  candidates = ancestors.flat_map do |ancestor_name|
1076
983
  @entries_tree.search("#{ancestor_name}::#{constant_name}")
1077
984
  end
@@ -1079,7 +986,8 @@ module RubyIndexer
1079
986
  # For candidates with the same name, we must only show the first entry in the inheritance chain, since that's the
1080
987
  # one the user will be referring to in completion
1081
988
  completion_items = candidates.each_with_object({}) do |entries, hash|
1082
- *parts, short_name = T.must(entries.first).name.split("::")
989
+ *parts, short_name = entries.first #: as !nil
990
+ .name.split("::")
1083
991
  namespace_name = parts.join("::")
1084
992
  ancestor_index = ancestors.index(namespace_name)
1085
993
  existing_entry, existing_entry_index = hash[short_name]
@@ -1098,7 +1006,7 @@ module RubyIndexer
1098
1006
  # inside of the ["A", "B"] nesting, then we should not concatenate the nesting with the name or else we'll end up
1099
1007
  # with `A::B::A::B::Foo`. This method will remove any redundant parts from the final name based on the reference and
1100
1008
  # the nesting
1101
- sig { params(name: String, nesting: T::Array[String]).returns(String) }
1009
+ #: (String name, Array[String] nesting) -> String
1102
1010
  def build_non_redundant_full_name(name, nesting)
1103
1011
  # If there's no nesting, then we can just return the name as is
1104
1012
  return name if nesting.empty?
@@ -1115,22 +1023,11 @@ module RubyIndexer
1115
1023
  # Otherwise, push all of the leading parts of the nesting that aren't redundant into the name. For example, if we
1116
1024
  # have a reference to `Foo::Bar` inside the `[Namespace, Foo]` nesting, then only the `Foo` part is redundant, but
1117
1025
  # we still need to include the `Namespace` part
1118
- T.unsafe(name_parts).unshift(*nesting[0...first_redundant_part])
1026
+ name_parts.unshift(*nesting[0...first_redundant_part])
1119
1027
  name_parts.join("::")
1120
1028
  end
1121
1029
 
1122
- sig do
1123
- params(
1124
- full_name: String,
1125
- seen_names: T::Array[String],
1126
- ).returns(
1127
- T.nilable(T::Array[T.any(
1128
- Entry::Namespace,
1129
- Entry::ConstantAlias,
1130
- Entry::UnresolvedConstantAlias,
1131
- )]),
1132
- )
1133
- end
1030
+ #: (String full_name, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
1134
1031
  def direct_or_aliased_constant(full_name, seen_names)
1135
1032
  entries = @entries[full_name] || @entries[follow_aliased_namespace(full_name)]
1136
1033
 
@@ -1146,13 +1043,7 @@ module RubyIndexer
1146
1043
 
1147
1044
  # Attempt to resolve a given unresolved method alias. This method returns the resolved alias if we managed to
1148
1045
  # identify the target or the same unresolved alias entry if we couldn't
1149
- sig do
1150
- params(
1151
- entry: Entry::UnresolvedMethodAlias,
1152
- receiver_name: String,
1153
- seen_names: T::Array[String],
1154
- ).returns(T.any(Entry::MethodAlias, Entry::UnresolvedMethodAlias))
1155
- end
1046
+ #: (Entry::UnresolvedMethodAlias entry, String receiver_name, Array[String] seen_names) -> (Entry::MethodAlias | Entry::UnresolvedMethodAlias)
1156
1047
  def resolve_method_alias(entry, receiver_name, seen_names)
1157
1048
  new_name = entry.new_name
1158
1049
  return entry if new_name == entry.old_name
@@ -1163,8 +1054,11 @@ module RubyIndexer
1163
1054
  target_method_entries = resolve_method(entry.old_name, receiver_name, seen_names)
1164
1055
  return entry unless target_method_entries
1165
1056
 
1166
- resolved_alias = Entry::MethodAlias.new(T.must(target_method_entries.first), entry)
1167
- original_entries = T.must(@entries[new_name])
1057
+ resolved_alias = Entry::MethodAlias.new(
1058
+ target_method_entries.first, #: as !nil
1059
+ entry,
1060
+ )
1061
+ original_entries = @entries[new_name] #: as !nil
1168
1062
  original_entries.delete(entry)
1169
1063
  original_entries << resolved_alias
1170
1064
  resolved_alias