ruby-lsp 0.23.11 → 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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp-launcher +12 -11
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +52 -77
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +61 -144
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +8 -6
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +73 -182
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +48 -181
- data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +12 -14
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +21 -44
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +40 -58
- data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +9 -16
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +5 -9
- data/lib/ruby_indexer/test/configuration_test.rb +32 -2
- data/lib/ruby_indexer/test/method_test.rb +2 -2
- data/lib/ruby_lsp/addon.rb +32 -67
- data/lib/ruby_lsp/base_server.rb +10 -10
- data/lib/ruby_lsp/client_capabilities.rb +4 -6
- data/lib/ruby_lsp/document.rb +21 -32
- data/lib/ruby_lsp/erb_document.rb +17 -27
- data/lib/ruby_lsp/global_state.rb +30 -32
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listeners/code_lens.rb +21 -39
- data/lib/ruby_lsp/listeners/completion.rb +34 -53
- data/lib/ruby_lsp/listeners/definition.rb +35 -49
- data/lib/ruby_lsp/listeners/document_highlight.rb +60 -69
- data/lib/ruby_lsp/listeners/document_link.rb +9 -19
- data/lib/ruby_lsp/listeners/document_symbol.rb +34 -48
- data/lib/ruby_lsp/listeners/folding_ranges.rb +31 -38
- data/lib/ruby_lsp/listeners/hover.rb +37 -47
- data/lib/ruby_lsp/listeners/inlay_hints.rb +3 -10
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +29 -35
- data/lib/ruby_lsp/listeners/signature_help.rb +4 -23
- data/lib/ruby_lsp/listeners/spec_style.rb +199 -0
- data/lib/ruby_lsp/listeners/test_style.rb +136 -30
- data/lib/ruby_lsp/node_context.rb +8 -35
- data/lib/ruby_lsp/rbs_document.rb +7 -5
- data/lib/ruby_lsp/requests/code_action_resolve.rb +10 -10
- data/lib/ruby_lsp/requests/code_actions.rb +5 -14
- data/lib/ruby_lsp/requests/code_lens.rb +4 -13
- data/lib/ruby_lsp/requests/completion.rb +4 -15
- data/lib/ruby_lsp/requests/completion_resolve.rb +4 -4
- data/lib/ruby_lsp/requests/definition.rb +4 -12
- data/lib/ruby_lsp/requests/diagnostics.rb +6 -9
- data/lib/ruby_lsp/requests/discover_tests.rb +15 -3
- data/lib/ruby_lsp/requests/document_highlight.rb +3 -11
- data/lib/ruby_lsp/requests/document_link.rb +4 -13
- data/lib/ruby_lsp/requests/document_symbol.rb +4 -7
- data/lib/ruby_lsp/requests/folding_ranges.rb +4 -7
- data/lib/ruby_lsp/requests/formatting.rb +4 -7
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +87 -0
- data/lib/ruby_lsp/requests/hover.rb +6 -16
- data/lib/ruby_lsp/requests/inlay_hints.rb +4 -13
- data/lib/ruby_lsp/requests/on_type_formatting.rb +17 -24
- data/lib/ruby_lsp/requests/prepare_rename.rb +3 -8
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +4 -13
- data/lib/ruby_lsp/requests/range_formatting.rb +3 -4
- data/lib/ruby_lsp/requests/references.rb +5 -35
- data/lib/ruby_lsp/requests/rename.rb +9 -35
- data/lib/ruby_lsp/requests/request.rb +5 -17
- data/lib/ruby_lsp/requests/selection_ranges.rb +3 -3
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +6 -23
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +4 -5
- data/lib/ruby_lsp/requests/signature_help.rb +6 -24
- data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
- data/lib/ruby_lsp/requests/support/common.rb +12 -49
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -14
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +7 -10
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +9 -15
- data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
- data/lib/ruby_lsp/requests/support/sorbet.rb +1 -7
- data/lib/ruby_lsp/requests/support/source_uri.rb +5 -16
- data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +7 -10
- data/lib/ruby_lsp/requests/support/test_item.rb +14 -13
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +4 -5
- data/lib/ruby_lsp/requests/workspace_symbol.rb +3 -3
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +4 -4
- data/lib/ruby_lsp/response_builders/document_symbol.rb +8 -11
- data/lib/ruby_lsp/response_builders/hover.rb +5 -5
- data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +18 -40
- data/lib/ruby_lsp/response_builders/signature_help.rb +4 -5
- data/lib/ruby_lsp/response_builders/test_collection.rb +5 -9
- data/lib/ruby_lsp/ruby_document.rb +15 -40
- data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +106 -0
- data/lib/ruby_lsp/scope.rb +6 -10
- data/lib/ruby_lsp/server.rb +125 -74
- data/lib/ruby_lsp/setup_bundler.rb +22 -15
- data/lib/ruby_lsp/store.rb +12 -28
- data/lib/ruby_lsp/test_helper.rb +3 -12
- data/lib/ruby_lsp/test_reporter.rb +71 -0
- data/lib/ruby_lsp/test_unit_test_runner.rb +96 -0
- data/lib/ruby_lsp/type_inferrer.rb +9 -13
- data/lib/ruby_lsp/utils.rb +27 -65
- metadata +8 -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
|
-
|
13
|
+
#: Configuration
|
16
14
|
attr_reader :configuration
|
17
15
|
|
18
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
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,7 +50,7 @@ module RubyIndexer
|
|
61
50
|
end
|
62
51
|
end
|
63
52
|
|
64
|
-
|
53
|
+
#: -> void
|
65
54
|
def initialize
|
66
55
|
# Holds all entries in the index using the following format:
|
67
56
|
# {
|
@@ -99,12 +88,12 @@ module RubyIndexer
|
|
99
88
|
end
|
100
89
|
|
101
90
|
# Register an included `hook` that will be executed when `module_name` is included into any namespace
|
102
|
-
|
91
|
+
#: (String module_name) { (Index index, Entry::Namespace base) -> void } -> void
|
103
92
|
def register_included_hook(module_name, &hook)
|
104
93
|
(@included_hooks[module_name] ||= []) << hook
|
105
94
|
end
|
106
95
|
|
107
|
-
|
96
|
+
#: (URI::Generic uri, ?skip_require_paths_tree: bool) -> void
|
108
97
|
def delete(uri, skip_require_paths_tree: false)
|
109
98
|
key = uri.to_s
|
110
99
|
# For each constant discovered in `path`, delete the associated entry from the index. If there are no entries
|
@@ -134,7 +123,7 @@ module RubyIndexer
|
|
134
123
|
@require_paths_tree.delete(require_path) if require_path
|
135
124
|
end
|
136
125
|
|
137
|
-
|
126
|
+
#: (Entry entry, ?skip_prefix_tree: bool) -> void
|
138
127
|
def add(entry, skip_prefix_tree: false)
|
139
128
|
name = entry.name
|
140
129
|
|
@@ -143,28 +132,19 @@ module RubyIndexer
|
|
143
132
|
@entries_tree.insert(name, T.must(@entries[name])) unless skip_prefix_tree
|
144
133
|
end
|
145
134
|
|
146
|
-
|
135
|
+
#: (String fully_qualified_name) -> Array[Entry]?
|
147
136
|
def [](fully_qualified_name)
|
148
137
|
@entries[fully_qualified_name.delete_prefix("::")]
|
149
138
|
end
|
150
139
|
|
151
|
-
|
140
|
+
#: (String query) -> Array[URI::Generic]
|
152
141
|
def search_require_paths(query)
|
153
142
|
@require_paths_tree.search(query)
|
154
143
|
end
|
155
144
|
|
156
145
|
# Searches for a constant based on an unqualified name and returns the first possible match regardless of whether
|
157
146
|
# there are more possible matching entries
|
158
|
-
|
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
|
147
|
+
#: (String name) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]?
|
168
148
|
def first_unqualified_const(name)
|
169
149
|
# Look for an exact match first
|
170
150
|
_name, entries = @entries.find do |const_name, _entries|
|
@@ -202,7 +182,7 @@ module RubyIndexer
|
|
202
182
|
# [#<Entry::Class name="Foo::Baz">],
|
203
183
|
# ]
|
204
184
|
# ```
|
205
|
-
|
185
|
+
#: (String query, ?Array[String]? nesting) -> Array[Array[Entry]]
|
206
186
|
def prefix_search(query, nesting = nil)
|
207
187
|
unless nesting
|
208
188
|
results = @entries_tree.search(query)
|
@@ -221,7 +201,7 @@ module RubyIndexer
|
|
221
201
|
end
|
222
202
|
|
223
203
|
# Fuzzy searches index entries based on Jaro-Winkler similarity. If no query is provided, all entries are returned
|
224
|
-
|
204
|
+
#: (String? query) -> Array[Entry]
|
225
205
|
def fuzzy_search(query)
|
226
206
|
unless query
|
227
207
|
entries = @entries.filter_map do |_name, entries|
|
@@ -245,12 +225,7 @@ module RubyIndexer
|
|
245
225
|
results.flat_map(&:first)
|
246
226
|
end
|
247
227
|
|
248
|
-
|
249
|
-
params(
|
250
|
-
name: T.nilable(String),
|
251
|
-
receiver_name: String,
|
252
|
-
).returns(T::Array[T.any(Entry::Member, Entry::MethodAlias)])
|
253
|
-
end
|
228
|
+
#: (String? name, String receiver_name) -> Array[(Entry::Member | Entry::MethodAlias)]
|
254
229
|
def method_completion_candidates(name, receiver_name)
|
255
230
|
ancestors = linearized_ancestors_of(receiver_name)
|
256
231
|
|
@@ -293,17 +268,7 @@ module RubyIndexer
|
|
293
268
|
completion_items.values.map!(&:first)
|
294
269
|
end
|
295
270
|
|
296
|
-
|
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
|
271
|
+
#: (String name, Array[String] nesting) -> Array[Array[(Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias)]]
|
307
272
|
def constant_completion_candidates(name, nesting)
|
308
273
|
# If we have a top level reference, then we don't need to include completions inside the current nesting
|
309
274
|
if name.start_with?("::")
|
@@ -358,17 +323,7 @@ module RubyIndexer
|
|
358
323
|
# nesting: the nesting structure where the reference was found (e.g.: ["Foo", "Bar"])
|
359
324
|
# seen_names: this parameter should not be used by consumers of the api. It is used to avoid infinite recursion when
|
360
325
|
# resolving circular references
|
361
|
-
|
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
|
326
|
+
#: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
|
372
327
|
def resolve(name, nesting, seen_names = [])
|
373
328
|
# If we have a top level reference, then we just search for it straight away ignoring the nesting
|
374
329
|
if name.start_with?("::")
|
@@ -404,12 +359,7 @@ module RubyIndexer
|
|
404
359
|
# Index all files for the given URIs, which defaults to what is configured. A block can be used to track and control
|
405
360
|
# indexing progress. That block is invoked with the current progress percentage and should return `true` to continue
|
406
361
|
# indexing or `false` to stop indexing.
|
407
|
-
|
408
|
-
params(
|
409
|
-
uris: T::Array[URI::Generic],
|
410
|
-
block: T.nilable(T.proc.params(progress: Integer).returns(T::Boolean)),
|
411
|
-
).void
|
412
|
-
end
|
362
|
+
#: (?uris: Array[URI::Generic]) ?{ (Integer progress) -> bool } -> void
|
413
363
|
def index_all(uris: @configuration.indexable_uris, &block)
|
414
364
|
# When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
|
415
365
|
# existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
|
@@ -419,8 +369,6 @@ module RubyIndexer
|
|
419
369
|
"The index is not empty. To prevent invalid entries, `index_all` can only be called once."
|
420
370
|
end
|
421
371
|
|
422
|
-
@initial_indexing_completed = true
|
423
|
-
|
424
372
|
RBSIndexer.new(self).index_ruby_core
|
425
373
|
# Calculate how many paths are worth 1% of progress
|
426
374
|
progress_step = (uris.length / 100.0).ceil
|
@@ -433,9 +381,11 @@ module RubyIndexer
|
|
433
381
|
|
434
382
|
index_file(uri, collect_comments: false)
|
435
383
|
end
|
384
|
+
|
385
|
+
@initial_indexing_completed = true
|
436
386
|
end
|
437
387
|
|
438
|
-
|
388
|
+
#: (URI::Generic uri, String source, ?collect_comments: bool) -> void
|
439
389
|
def index_single(uri, source, collect_comments: true)
|
440
390
|
dispatcher = Prism::Dispatcher.new
|
441
391
|
|
@@ -457,7 +407,7 @@ module RubyIndexer
|
|
457
407
|
end
|
458
408
|
|
459
409
|
# Indexes a File URI by reading the contents from disk
|
460
|
-
|
410
|
+
#: (URI::Generic uri, ?collect_comments: bool) -> void
|
461
411
|
def index_file(uri, collect_comments: true)
|
462
412
|
index_single(uri, File.read(T.must(uri.full_path)), collect_comments: collect_comments)
|
463
413
|
rescue Errno::EISDIR, Errno::ENOENT
|
@@ -475,7 +425,7 @@ module RubyIndexer
|
|
475
425
|
# If we find an alias, then we want to follow its target. In the same example, if `Foo::Bar` is an alias to
|
476
426
|
# `Something::Else`, then we first discover `Something::Else::Baz`. But `Something::Else::Baz` might contain other
|
477
427
|
# aliases, so we have to invoke `follow_aliased_namespace` again to check until we only return a real name
|
478
|
-
|
428
|
+
#: (String name, ?Array[String] seen_names) -> String
|
479
429
|
def follow_aliased_namespace(name, seen_names = [])
|
480
430
|
parts = name.split("::")
|
481
431
|
real_parts = []
|
@@ -508,14 +458,7 @@ module RubyIndexer
|
|
508
458
|
# Attempts to find methods for a resolved fully qualified receiver name. Do not provide the `seen_names` parameter
|
509
459
|
# as it is used only internally to prevent infinite loops when resolving circular aliases
|
510
460
|
# Returns `nil` if the method does not exist on that receiver
|
511
|
-
|
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
|
461
|
+
#: (String method_name, String receiver_name, ?Array[String] seen_names, ?inherited_only: bool) -> Array[(Entry::Member | Entry::MethodAlias)]?
|
519
462
|
def resolve_method(method_name, receiver_name, seen_names = [], inherited_only: false)
|
520
463
|
method_entries = self[method_name]
|
521
464
|
return unless method_entries
|
@@ -553,7 +496,7 @@ module RubyIndexer
|
|
553
496
|
# module that prepends another module, then the prepend module appears before the included module.
|
554
497
|
#
|
555
498
|
# The order of ancestors is [linearized_prepends, self, linearized_includes, linearized_superclass]
|
556
|
-
|
499
|
+
#: (String fully_qualified_name) -> Array[String]
|
557
500
|
def linearized_ancestors_of(fully_qualified_name)
|
558
501
|
# If we already computed the ancestors for this namespace, return it straight away
|
559
502
|
cached_ancestors = @ancestors[fully_qualified_name]
|
@@ -631,7 +574,7 @@ module RubyIndexer
|
|
631
574
|
|
632
575
|
# Resolves an instance variable name for a given owner name. This method will linearize the ancestors of the owner
|
633
576
|
# and find inherited instance variables as well
|
634
|
-
|
577
|
+
#: (String variable_name, String owner_name) -> Array[Entry::InstanceVariable]?
|
635
578
|
def resolve_instance_variable(variable_name, owner_name)
|
636
579
|
entries = T.cast(self[variable_name], T.nilable(T::Array[Entry::InstanceVariable]))
|
637
580
|
return unless entries
|
@@ -642,7 +585,7 @@ module RubyIndexer
|
|
642
585
|
entries.select { |e| ancestors.include?(e.owner&.name) }
|
643
586
|
end
|
644
587
|
|
645
|
-
|
588
|
+
#: (String variable_name, String owner_name) -> Array[Entry::ClassVariable]?
|
646
589
|
def resolve_class_variable(variable_name, owner_name)
|
647
590
|
entries = self[variable_name]&.grep(Entry::ClassVariable)
|
648
591
|
return unless entries&.any?
|
@@ -655,9 +598,7 @@ module RubyIndexer
|
|
655
598
|
|
656
599
|
# Returns a list of possible candidates for completion of instance variables for a given owner name. The name must
|
657
600
|
# include the `@` prefix
|
658
|
-
|
659
|
-
params(name: String, owner_name: String).returns(T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
|
660
|
-
end
|
601
|
+
#: (String name, String owner_name) -> Array[(Entry::InstanceVariable | Entry::ClassVariable)]
|
661
602
|
def instance_variable_completion_candidates(name, owner_name)
|
662
603
|
entries = T.cast(prefix_search(name).flatten, T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
|
663
604
|
# Avoid wasting time linearizing ancestors if we didn't find anything
|
@@ -686,7 +627,7 @@ module RubyIndexer
|
|
686
627
|
variables
|
687
628
|
end
|
688
629
|
|
689
|
-
|
630
|
+
#: (String name, String owner_name) -> Array[Entry::ClassVariable]
|
690
631
|
def class_variable_completion_candidates(name, owner_name)
|
691
632
|
entries = T.cast(prefix_search(name).flatten, T::Array[Entry::ClassVariable])
|
692
633
|
# Avoid wasting time linearizing ancestors if we didn't find anything
|
@@ -702,9 +643,7 @@ module RubyIndexer
|
|
702
643
|
# declarations removed and that the ancestor linearization cache is cleared if necessary. If a block is passed, the
|
703
644
|
# consumer of this API has to handle deleting and inserting/updating entries in the index instead of passing the
|
704
645
|
# document's source (used to handle unsaved changes to files)
|
705
|
-
|
706
|
-
params(uri: URI::Generic, source: T.nilable(String), block: T.nilable(T.proc.params(index: Index).void)).void
|
707
|
-
end
|
646
|
+
#: (URI::Generic uri, ?String? source) ?{ (Index index) -> void } -> void
|
708
647
|
def handle_change(uri, source = nil, &block)
|
709
648
|
key = uri.to_s
|
710
649
|
original_entries = @uris_to_entries[key]
|
@@ -736,27 +675,27 @@ module RubyIndexer
|
|
736
675
|
@ancestors.clear if original_map.any? { |name, hash| updated_map[name] != hash }
|
737
676
|
end
|
738
677
|
|
739
|
-
|
678
|
+
#: -> bool
|
740
679
|
def empty?
|
741
680
|
@entries.empty?
|
742
681
|
end
|
743
682
|
|
744
|
-
|
683
|
+
#: -> Array[String]
|
745
684
|
def names
|
746
685
|
@entries.keys
|
747
686
|
end
|
748
687
|
|
749
|
-
|
688
|
+
#: (String name) -> bool
|
750
689
|
def indexed?(name)
|
751
690
|
@entries.key?(name)
|
752
691
|
end
|
753
692
|
|
754
|
-
|
693
|
+
#: -> Integer
|
755
694
|
def length
|
756
695
|
@entries.count
|
757
696
|
end
|
758
697
|
|
759
|
-
|
698
|
+
#: (String name) -> Entry::SingletonClass
|
760
699
|
def existing_or_new_singleton_class(name)
|
761
700
|
*_namespace, unqualified_name = name.split("::")
|
762
701
|
full_singleton_name = "#{name}::<Class:#{unqualified_name}>"
|
@@ -779,12 +718,7 @@ module RubyIndexer
|
|
779
718
|
singleton
|
780
719
|
end
|
781
720
|
|
782
|
-
|
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
|
721
|
+
#: [T] (String uri, ?Class[(T & Entry)]? type) -> (Array[Entry] | Array[T])?
|
788
722
|
def entries_for(uri, type = nil)
|
789
723
|
entries = @uris_to_entries[uri.to_s]
|
790
724
|
return entries unless type
|
@@ -796,7 +730,7 @@ module RubyIndexer
|
|
796
730
|
|
797
731
|
# Always returns the linearized ancestors for the attached class, regardless of whether `name` refers to a singleton
|
798
732
|
# or attached namespace
|
799
|
-
|
733
|
+
#: (String name) -> Array[String]
|
800
734
|
def linearized_attached_ancestors(name)
|
801
735
|
name_parts = name.split("::")
|
802
736
|
|
@@ -809,7 +743,7 @@ module RubyIndexer
|
|
809
743
|
end
|
810
744
|
|
811
745
|
# Runs the registered included hooks
|
812
|
-
|
746
|
+
#: (String fully_qualified_name, Array[String] nesting) -> void
|
813
747
|
def run_included_hooks(fully_qualified_name, nesting)
|
814
748
|
return if @included_hooks.empty?
|
815
749
|
|
@@ -838,13 +772,7 @@ module RubyIndexer
|
|
838
772
|
|
839
773
|
# Linearize mixins for an array of namespace entries. This method will mutate the `ancestors` array with the
|
840
774
|
# linearized ancestors of the mixins
|
841
|
-
|
842
|
-
params(
|
843
|
-
ancestors: T::Array[String],
|
844
|
-
namespace_entries: T::Array[Entry::Namespace],
|
845
|
-
nesting: T::Array[String],
|
846
|
-
).void
|
847
|
-
end
|
775
|
+
#: (Array[String] ancestors, Array[Entry::Namespace] namespace_entries, Array[String] nesting) -> void
|
848
776
|
def linearize_mixins(ancestors, namespace_entries, nesting)
|
849
777
|
mixin_operations = namespace_entries.flat_map(&:mixin_operations)
|
850
778
|
main_namespace_index = 0
|
@@ -885,16 +813,7 @@ module RubyIndexer
|
|
885
813
|
|
886
814
|
# Linearize the superclass of a given namespace (including modules with the implicit `Module` superclass). This
|
887
815
|
# method will mutate the `ancestors` array with the linearized ancestors of the superclass
|
888
|
-
|
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
|
816
|
+
#: (Array[String] ancestors, String attached_class_name, String fully_qualified_name, Array[Entry::Namespace] namespace_entries, Array[String] nesting, Integer singleton_levels) -> void
|
898
817
|
def linearize_superclass( # rubocop:disable Metrics/ParameterLists
|
899
818
|
ancestors,
|
900
819
|
attached_class_name,
|
@@ -962,12 +881,7 @@ module RubyIndexer
|
|
962
881
|
|
963
882
|
# Attempts to resolve an UnresolvedAlias into a resolved Alias. If the unresolved alias is pointing to a constant
|
964
883
|
# that doesn't exist, then we return the same UnresolvedAlias
|
965
|
-
|
966
|
-
params(
|
967
|
-
entry: Entry::UnresolvedConstantAlias,
|
968
|
-
seen_names: T::Array[String],
|
969
|
-
).returns(T.any(Entry::ConstantAlias, Entry::UnresolvedConstantAlias))
|
970
|
-
end
|
884
|
+
#: (Entry::UnresolvedConstantAlias entry, Array[String] seen_names) -> (Entry::ConstantAlias | Entry::UnresolvedConstantAlias)
|
971
885
|
def resolve_alias(entry, seen_names)
|
972
886
|
alias_name = entry.name
|
973
887
|
return entry if seen_names.include?(alias_name)
|
@@ -990,17 +904,7 @@ module RubyIndexer
|
|
990
904
|
resolved_alias
|
991
905
|
end
|
992
906
|
|
993
|
-
|
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
|
907
|
+
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
|
1004
908
|
def lookup_enclosing_scopes(name, nesting, seen_names)
|
1005
909
|
nesting.length.downto(1) do |i|
|
1006
910
|
namespace = T.must(nesting[0...i]).join("::")
|
@@ -1019,17 +923,7 @@ module RubyIndexer
|
|
1019
923
|
nil
|
1020
924
|
end
|
1021
925
|
|
1022
|
-
|
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
|
926
|
+
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
|
1033
927
|
def lookup_ancestor_chain(name, nesting, seen_names)
|
1034
928
|
*nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
|
1035
929
|
return if nesting_parts.empty?
|
@@ -1049,17 +943,7 @@ module RubyIndexer
|
|
1049
943
|
nil
|
1050
944
|
end
|
1051
945
|
|
1052
|
-
|
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
|
946
|
+
#: (String? name, Array[String] nesting) -> Array[Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]]
|
1063
947
|
def inherited_constant_completion_candidates(name, nesting)
|
1064
948
|
namespace_entries = if name
|
1065
949
|
*nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
|
@@ -1098,7 +982,7 @@ module RubyIndexer
|
|
1098
982
|
# inside of the ["A", "B"] nesting, then we should not concatenate the nesting with the name or else we'll end up
|
1099
983
|
# with `A::B::A::B::Foo`. This method will remove any redundant parts from the final name based on the reference and
|
1100
984
|
# the nesting
|
1101
|
-
|
985
|
+
#: (String name, Array[String] nesting) -> String
|
1102
986
|
def build_non_redundant_full_name(name, nesting)
|
1103
987
|
# If there's no nesting, then we can just return the name as is
|
1104
988
|
return name if nesting.empty?
|
@@ -1119,18 +1003,7 @@ module RubyIndexer
|
|
1119
1003
|
name_parts.join("::")
|
1120
1004
|
end
|
1121
1005
|
|
1122
|
-
|
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
|
1006
|
+
#: (String full_name, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
|
1134
1007
|
def direct_or_aliased_constant(full_name, seen_names)
|
1135
1008
|
entries = @entries[full_name] || @entries[follow_aliased_namespace(full_name)]
|
1136
1009
|
|
@@ -1146,13 +1019,7 @@ module RubyIndexer
|
|
1146
1019
|
|
1147
1020
|
# Attempt to resolve a given unresolved method alias. This method returns the resolved alias if we managed to
|
1148
1021
|
# identify the target or the same unresolved alias entry if we couldn't
|
1149
|
-
|
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
|
1022
|
+
#: (Entry::UnresolvedMethodAlias entry, String receiver_name, Array[String] seen_names) -> (Entry::MethodAlias | Entry::UnresolvedMethodAlias)
|
1156
1023
|
def resolve_method_alias(entry, receiver_name, seen_names)
|
1157
1024
|
new_name = entry.new_name
|
1158
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
|
-
|
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
|
-
|
18
|
+
#: Integer
|
31
19
|
attr_reader :start_line, :end_line, :start_column, :end_column
|
32
20
|
|
33
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
114
|
+
#: Hash[String, Node[Value]]
|
117
115
|
attr_reader :children
|
118
116
|
|
119
|
-
|
117
|
+
#: String
|
120
118
|
attr_reader :key
|
121
119
|
|
122
|
-
|
120
|
+
#: Value
|
123
121
|
attr_accessor :value
|
124
122
|
|
125
|
-
|
123
|
+
#: bool
|
126
124
|
attr_accessor :leaf
|
127
125
|
|
128
|
-
|
126
|
+
#: Node[Value]?
|
129
127
|
attr_reader :parent
|
130
128
|
|
131
|
-
|
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
|
-
|
138
|
+
#: -> Array[Value]
|
141
139
|
def collect
|
142
140
|
result = []
|
143
141
|
result << @value if @leaf
|