ruby-lsp 0.23.11 → 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.
- 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_language_server_aliases.rb +1 -1
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +81 -115
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +117 -166
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -7
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +88 -200
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +56 -192
- data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +14 -16
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +22 -45
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +42 -60
- 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 +42 -3
- data/lib/ruby_indexer/test/method_test.rb +28 -2
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +1 -1
- data/lib/ruby_lsp/addon.rb +44 -71
- data/lib/ruby_lsp/base_server.rb +29 -32
- data/lib/ruby_lsp/client_capabilities.rb +10 -12
- data/lib/ruby_lsp/document.rb +34 -45
- data/lib/ruby_lsp/erb_document.rb +24 -36
- data/lib/ruby_lsp/global_state.rb +51 -56
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listeners/code_lens.rb +81 -88
- data/lib/ruby_lsp/listeners/completion.rb +36 -55
- data/lib/ruby_lsp/listeners/definition.rb +37 -51
- data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
- data/lib/ruby_lsp/listeners/document_link.rb +43 -62
- data/lib/ruby_lsp/listeners/document_symbol.rb +35 -49
- data/lib/ruby_lsp/listeners/folding_ranges.rb +32 -39
- data/lib/ruby_lsp/listeners/hover.rb +81 -100
- data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +42 -51
- data/lib/ruby_lsp/listeners/signature_help.rb +6 -25
- data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
- data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
- data/lib/ruby_lsp/listeners/test_style.rb +160 -88
- data/lib/ruby_lsp/node_context.rb +12 -39
- data/lib/ruby_lsp/rbs_document.rb +8 -6
- data/lib/ruby_lsp/requests/code_action_resolve.rb +10 -10
- data/lib/ruby_lsp/requests/code_actions.rb +14 -26
- data/lib/ruby_lsp/requests/code_lens.rb +6 -17
- data/lib/ruby_lsp/requests/completion.rb +7 -20
- data/lib/ruby_lsp/requests/completion_resolve.rb +5 -5
- data/lib/ruby_lsp/requests/definition.rb +8 -17
- data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
- data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
- data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
- data/lib/ruby_lsp/requests/document_link.rb +6 -17
- data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
- data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
- data/lib/ruby_lsp/requests/formatting.rb +6 -9
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +87 -0
- data/lib/ruby_lsp/requests/hover.rb +8 -18
- data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
- data/lib/ruby_lsp/requests/on_type_formatting.rb +28 -38
- data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +4 -13
- data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
- data/lib/ruby_lsp/requests/references.rb +6 -36
- data/lib/ruby_lsp/requests/rename.rb +11 -37
- data/lib/ruby_lsp/requests/request.rb +7 -19
- data/lib/ruby_lsp/requests/selection_ranges.rb +5 -5
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +12 -31
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +5 -6
- data/lib/ruby_lsp/requests/signature_help.rb +8 -26
- data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
- data/lib/ruby_lsp/requests/support/common.rb +13 -50
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +9 -12
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
- data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
- data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
- data/lib/ruby_lsp/requests/support/source_uri.rb +16 -30
- data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
- data/lib/ruby_lsp/requests/support/test_item.rb +10 -14
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
- data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
- data/lib/ruby_lsp/response_builders/document_symbol.rb +10 -16
- data/lib/ruby_lsp/response_builders/hover.rb +10 -13
- data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +59 -87
- data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
- data/lib/ruby_lsp/response_builders/test_collection.rb +6 -10
- data/lib/ruby_lsp/ruby_document.rb +22 -60
- data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +109 -0
- data/lib/ruby_lsp/scope.rb +7 -11
- data/lib/ruby_lsp/server.rb +133 -74
- data/lib/ruby_lsp/setup_bundler.rb +58 -57
- data/lib/ruby_lsp/static_docs.rb +4 -7
- data/lib/ruby_lsp/store.rb +21 -40
- data/lib/ruby_lsp/test_helper.rb +3 -12
- data/lib/ruby_lsp/test_reporter.rb +207 -0
- data/lib/ruby_lsp/test_unit_test_runner.rb +98 -0
- data/lib/ruby_lsp/type_inferrer.rb +9 -13
- data/lib/ruby_lsp/utils.rb +37 -81
- 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
|
-
|
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,17 +50,17 @@ 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
|
# {
|
68
57
|
# "Foo" => [#<Entry::Class>, #<Entry::Class>],
|
69
58
|
# "Foo::Bar" => [#<Entry::Class>],
|
70
59
|
# }
|
71
|
-
@entries =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
82
|
+
@configuration = RubyIndexer::Configuration.new #: Configuration
|
97
83
|
|
98
|
-
@initial_indexing_completed =
|
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
|
-
|
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
|
-
|
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,7 +120,7 @@ module RubyIndexer
|
|
134
120
|
@require_paths_tree.delete(require_path) if require_path
|
135
121
|
end
|
136
122
|
|
137
|
-
|
123
|
+
#: (Entry entry, ?skip_prefix_tree: bool) -> void
|
138
124
|
def add(entry, skip_prefix_tree: false)
|
139
125
|
name = entry.name
|
140
126
|
|
@@ -143,28 +129,19 @@ module RubyIndexer
|
|
143
129
|
@entries_tree.insert(name, T.must(@entries[name])) unless skip_prefix_tree
|
144
130
|
end
|
145
131
|
|
146
|
-
|
132
|
+
#: (String fully_qualified_name) -> Array[Entry]?
|
147
133
|
def [](fully_qualified_name)
|
148
134
|
@entries[fully_qualified_name.delete_prefix("::")]
|
149
135
|
end
|
150
136
|
|
151
|
-
|
137
|
+
#: (String query) -> Array[URI::Generic]
|
152
138
|
def search_require_paths(query)
|
153
139
|
@require_paths_tree.search(query)
|
154
140
|
end
|
155
141
|
|
156
142
|
# Searches for a constant based on an unqualified name and returns the first possible match regardless of whether
|
157
143
|
# 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
|
144
|
+
#: (String name) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]?
|
168
145
|
def first_unqualified_const(name)
|
169
146
|
# Look for an exact match first
|
170
147
|
_name, entries = @entries.find do |const_name, _entries|
|
@@ -202,7 +179,7 @@ module RubyIndexer
|
|
202
179
|
# [#<Entry::Class name="Foo::Baz">],
|
203
180
|
# ]
|
204
181
|
# ```
|
205
|
-
|
182
|
+
#: (String query, ?Array[String]? nesting) -> Array[Array[Entry]]
|
206
183
|
def prefix_search(query, nesting = nil)
|
207
184
|
unless nesting
|
208
185
|
results = @entries_tree.search(query)
|
@@ -221,7 +198,7 @@ module RubyIndexer
|
|
221
198
|
end
|
222
199
|
|
223
200
|
# Fuzzy searches index entries based on Jaro-Winkler similarity. If no query is provided, all entries are returned
|
224
|
-
|
201
|
+
#: (String? query) -> Array[Entry]
|
225
202
|
def fuzzy_search(query)
|
226
203
|
unless query
|
227
204
|
entries = @entries.filter_map do |_name, entries|
|
@@ -245,12 +222,7 @@ module RubyIndexer
|
|
245
222
|
results.flat_map(&:first)
|
246
223
|
end
|
247
224
|
|
248
|
-
|
249
|
-
params(
|
250
|
-
name: T.nilable(String),
|
251
|
-
receiver_name: String,
|
252
|
-
).returns(T::Array[T.any(Entry::Member, Entry::MethodAlias)])
|
253
|
-
end
|
225
|
+
#: (String? name, String receiver_name) -> Array[(Entry::Member | Entry::MethodAlias)]
|
254
226
|
def method_completion_candidates(name, receiver_name)
|
255
227
|
ancestors = linearized_ancestors_of(receiver_name)
|
256
228
|
|
@@ -293,17 +265,7 @@ module RubyIndexer
|
|
293
265
|
completion_items.values.map!(&:first)
|
294
266
|
end
|
295
267
|
|
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
|
268
|
+
#: (String name, Array[String] nesting) -> Array[Array[(Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias)]]
|
307
269
|
def constant_completion_candidates(name, nesting)
|
308
270
|
# If we have a top level reference, then we don't need to include completions inside the current nesting
|
309
271
|
if name.start_with?("::")
|
@@ -358,17 +320,7 @@ module RubyIndexer
|
|
358
320
|
# nesting: the nesting structure where the reference was found (e.g.: ["Foo", "Bar"])
|
359
321
|
# seen_names: this parameter should not be used by consumers of the api. It is used to avoid infinite recursion when
|
360
322
|
# 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
|
323
|
+
#: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
|
372
324
|
def resolve(name, nesting, seen_names = [])
|
373
325
|
# If we have a top level reference, then we just search for it straight away ignoring the nesting
|
374
326
|
if name.start_with?("::")
|
@@ -404,12 +356,7 @@ module RubyIndexer
|
|
404
356
|
# Index all files for the given URIs, which defaults to what is configured. A block can be used to track and control
|
405
357
|
# indexing progress. That block is invoked with the current progress percentage and should return `true` to continue
|
406
358
|
# 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
|
359
|
+
#: (?uris: Array[URI::Generic]) ?{ (Integer progress) -> bool } -> void
|
413
360
|
def index_all(uris: @configuration.indexable_uris, &block)
|
414
361
|
# When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
|
415
362
|
# existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
|
@@ -419,8 +366,6 @@ module RubyIndexer
|
|
419
366
|
"The index is not empty. To prevent invalid entries, `index_all` can only be called once."
|
420
367
|
end
|
421
368
|
|
422
|
-
@initial_indexing_completed = true
|
423
|
-
|
424
369
|
RBSIndexer.new(self).index_ruby_core
|
425
370
|
# Calculate how many paths are worth 1% of progress
|
426
371
|
progress_step = (uris.length / 100.0).ceil
|
@@ -433,9 +378,11 @@ module RubyIndexer
|
|
433
378
|
|
434
379
|
index_file(uri, collect_comments: false)
|
435
380
|
end
|
381
|
+
|
382
|
+
@initial_indexing_completed = true
|
436
383
|
end
|
437
384
|
|
438
|
-
|
385
|
+
#: (URI::Generic uri, String source, ?collect_comments: bool) -> void
|
439
386
|
def index_single(uri, source, collect_comments: true)
|
440
387
|
dispatcher = Prism::Dispatcher.new
|
441
388
|
|
@@ -457,7 +404,7 @@ module RubyIndexer
|
|
457
404
|
end
|
458
405
|
|
459
406
|
# Indexes a File URI by reading the contents from disk
|
460
|
-
|
407
|
+
#: (URI::Generic uri, ?collect_comments: bool) -> void
|
461
408
|
def index_file(uri, collect_comments: true)
|
462
409
|
index_single(uri, File.read(T.must(uri.full_path)), collect_comments: collect_comments)
|
463
410
|
rescue Errno::EISDIR, Errno::ENOENT
|
@@ -475,7 +422,7 @@ module RubyIndexer
|
|
475
422
|
# If we find an alias, then we want to follow its target. In the same example, if `Foo::Bar` is an alias to
|
476
423
|
# `Something::Else`, then we first discover `Something::Else::Baz`. But `Something::Else::Baz` might contain other
|
477
424
|
# aliases, so we have to invoke `follow_aliased_namespace` again to check until we only return a real name
|
478
|
-
|
425
|
+
#: (String name, ?Array[String] seen_names) -> String
|
479
426
|
def follow_aliased_namespace(name, seen_names = [])
|
480
427
|
parts = name.split("::")
|
481
428
|
real_parts = []
|
@@ -508,14 +455,7 @@ module RubyIndexer
|
|
508
455
|
# Attempts to find methods for a resolved fully qualified receiver name. Do not provide the `seen_names` parameter
|
509
456
|
# as it is used only internally to prevent infinite loops when resolving circular aliases
|
510
457
|
# 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
|
458
|
+
#: (String method_name, String receiver_name, ?Array[String] seen_names, ?inherited_only: bool) -> Array[(Entry::Member | Entry::MethodAlias)]?
|
519
459
|
def resolve_method(method_name, receiver_name, seen_names = [], inherited_only: false)
|
520
460
|
method_entries = self[method_name]
|
521
461
|
return unless method_entries
|
@@ -553,7 +493,7 @@ module RubyIndexer
|
|
553
493
|
# module that prepends another module, then the prepend module appears before the included module.
|
554
494
|
#
|
555
495
|
# The order of ancestors is [linearized_prepends, self, linearized_includes, linearized_superclass]
|
556
|
-
|
496
|
+
#: (String fully_qualified_name) -> Array[String]
|
557
497
|
def linearized_ancestors_of(fully_qualified_name)
|
558
498
|
# If we already computed the ancestors for this namespace, return it straight away
|
559
499
|
cached_ancestors = @ancestors[fully_qualified_name]
|
@@ -631,7 +571,7 @@ module RubyIndexer
|
|
631
571
|
|
632
572
|
# Resolves an instance variable name for a given owner name. This method will linearize the ancestors of the owner
|
633
573
|
# and find inherited instance variables as well
|
634
|
-
|
574
|
+
#: (String variable_name, String owner_name) -> Array[Entry::InstanceVariable]?
|
635
575
|
def resolve_instance_variable(variable_name, owner_name)
|
636
576
|
entries = T.cast(self[variable_name], T.nilable(T::Array[Entry::InstanceVariable]))
|
637
577
|
return unless entries
|
@@ -642,7 +582,7 @@ module RubyIndexer
|
|
642
582
|
entries.select { |e| ancestors.include?(e.owner&.name) }
|
643
583
|
end
|
644
584
|
|
645
|
-
|
585
|
+
#: (String variable_name, String owner_name) -> Array[Entry::ClassVariable]?
|
646
586
|
def resolve_class_variable(variable_name, owner_name)
|
647
587
|
entries = self[variable_name]&.grep(Entry::ClassVariable)
|
648
588
|
return unless entries&.any?
|
@@ -655,9 +595,7 @@ module RubyIndexer
|
|
655
595
|
|
656
596
|
# Returns a list of possible candidates for completion of instance variables for a given owner name. The name must
|
657
597
|
# include the `@` prefix
|
658
|
-
|
659
|
-
params(name: String, owner_name: String).returns(T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
|
660
|
-
end
|
598
|
+
#: (String name, String owner_name) -> Array[(Entry::InstanceVariable | Entry::ClassVariable)]
|
661
599
|
def instance_variable_completion_candidates(name, owner_name)
|
662
600
|
entries = T.cast(prefix_search(name).flatten, T::Array[T.any(Entry::InstanceVariable, Entry::ClassVariable)])
|
663
601
|
# Avoid wasting time linearizing ancestors if we didn't find anything
|
@@ -686,7 +624,7 @@ module RubyIndexer
|
|
686
624
|
variables
|
687
625
|
end
|
688
626
|
|
689
|
-
|
627
|
+
#: (String name, String owner_name) -> Array[Entry::ClassVariable]
|
690
628
|
def class_variable_completion_candidates(name, owner_name)
|
691
629
|
entries = T.cast(prefix_search(name).flatten, T::Array[Entry::ClassVariable])
|
692
630
|
# Avoid wasting time linearizing ancestors if we didn't find anything
|
@@ -702,9 +640,7 @@ module RubyIndexer
|
|
702
640
|
# declarations removed and that the ancestor linearization cache is cleared if necessary. If a block is passed, the
|
703
641
|
# consumer of this API has to handle deleting and inserting/updating entries in the index instead of passing the
|
704
642
|
# 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
|
643
|
+
#: (URI::Generic uri, ?String? source) ?{ (Index index) -> void } -> void
|
708
644
|
def handle_change(uri, source = nil, &block)
|
709
645
|
key = uri.to_s
|
710
646
|
original_entries = @uris_to_entries[key]
|
@@ -736,27 +672,27 @@ module RubyIndexer
|
|
736
672
|
@ancestors.clear if original_map.any? { |name, hash| updated_map[name] != hash }
|
737
673
|
end
|
738
674
|
|
739
|
-
|
675
|
+
#: -> bool
|
740
676
|
def empty?
|
741
677
|
@entries.empty?
|
742
678
|
end
|
743
679
|
|
744
|
-
|
680
|
+
#: -> Array[String]
|
745
681
|
def names
|
746
682
|
@entries.keys
|
747
683
|
end
|
748
684
|
|
749
|
-
|
685
|
+
#: (String name) -> bool
|
750
686
|
def indexed?(name)
|
751
687
|
@entries.key?(name)
|
752
688
|
end
|
753
689
|
|
754
|
-
|
690
|
+
#: -> Integer
|
755
691
|
def length
|
756
692
|
@entries.count
|
757
693
|
end
|
758
694
|
|
759
|
-
|
695
|
+
#: (String name) -> Entry::SingletonClass
|
760
696
|
def existing_or_new_singleton_class(name)
|
761
697
|
*_namespace, unqualified_name = name.split("::")
|
762
698
|
full_singleton_name = "#{name}::<Class:#{unqualified_name}>"
|
@@ -779,12 +715,7 @@ module RubyIndexer
|
|
779
715
|
singleton
|
780
716
|
end
|
781
717
|
|
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
|
718
|
+
#: [T] (String uri, ?Class[(T & Entry)]? type) -> (Array[Entry] | Array[T])?
|
788
719
|
def entries_for(uri, type = nil)
|
789
720
|
entries = @uris_to_entries[uri.to_s]
|
790
721
|
return entries unless type
|
@@ -796,7 +727,7 @@ module RubyIndexer
|
|
796
727
|
|
797
728
|
# Always returns the linearized ancestors for the attached class, regardless of whether `name` refers to a singleton
|
798
729
|
# or attached namespace
|
799
|
-
|
730
|
+
#: (String name) -> Array[String]
|
800
731
|
def linearized_attached_ancestors(name)
|
801
732
|
name_parts = name.split("::")
|
802
733
|
|
@@ -809,7 +740,7 @@ module RubyIndexer
|
|
809
740
|
end
|
810
741
|
|
811
742
|
# Runs the registered included hooks
|
812
|
-
|
743
|
+
#: (String fully_qualified_name, Array[String] nesting) -> void
|
813
744
|
def run_included_hooks(fully_qualified_name, nesting)
|
814
745
|
return if @included_hooks.empty?
|
815
746
|
|
@@ -838,13 +769,7 @@ module RubyIndexer
|
|
838
769
|
|
839
770
|
# Linearize mixins for an array of namespace entries. This method will mutate the `ancestors` array with the
|
840
771
|
# 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
|
772
|
+
#: (Array[String] ancestors, Array[Entry::Namespace] namespace_entries, Array[String] nesting) -> void
|
848
773
|
def linearize_mixins(ancestors, namespace_entries, nesting)
|
849
774
|
mixin_operations = namespace_entries.flat_map(&:mixin_operations)
|
850
775
|
main_namespace_index = 0
|
@@ -885,16 +810,7 @@ module RubyIndexer
|
|
885
810
|
|
886
811
|
# Linearize the superclass of a given namespace (including modules with the implicit `Module` superclass). This
|
887
812
|
# 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
|
813
|
+
#: (Array[String] ancestors, String attached_class_name, String fully_qualified_name, Array[Entry::Namespace] namespace_entries, Array[String] nesting, Integer singleton_levels) -> void
|
898
814
|
def linearize_superclass( # rubocop:disable Metrics/ParameterLists
|
899
815
|
ancestors,
|
900
816
|
attached_class_name,
|
@@ -962,12 +878,7 @@ module RubyIndexer
|
|
962
878
|
|
963
879
|
# Attempts to resolve an UnresolvedAlias into a resolved Alias. If the unresolved alias is pointing to a constant
|
964
880
|
# 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
|
881
|
+
#: (Entry::UnresolvedConstantAlias entry, Array[String] seen_names) -> (Entry::ConstantAlias | Entry::UnresolvedConstantAlias)
|
971
882
|
def resolve_alias(entry, seen_names)
|
972
883
|
alias_name = entry.name
|
973
884
|
return entry if seen_names.include?(alias_name)
|
@@ -990,17 +901,7 @@ module RubyIndexer
|
|
990
901
|
resolved_alias
|
991
902
|
end
|
992
903
|
|
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
|
904
|
+
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
|
1004
905
|
def lookup_enclosing_scopes(name, nesting, seen_names)
|
1005
906
|
nesting.length.downto(1) do |i|
|
1006
907
|
namespace = T.must(nesting[0...i]).join("::")
|
@@ -1019,17 +920,7 @@ module RubyIndexer
|
|
1019
920
|
nil
|
1020
921
|
end
|
1021
922
|
|
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
|
923
|
+
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
|
1033
924
|
def lookup_ancestor_chain(name, nesting, seen_names)
|
1034
925
|
*nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
|
1035
926
|
return if nesting_parts.empty?
|
@@ -1049,17 +940,7 @@ module RubyIndexer
|
|
1049
940
|
nil
|
1050
941
|
end
|
1051
942
|
|
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
|
943
|
+
#: (String? name, Array[String] nesting) -> Array[Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias | Entry::Constant)]]
|
1063
944
|
def inherited_constant_completion_candidates(name, nesting)
|
1064
945
|
namespace_entries = if name
|
1065
946
|
*nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
|
@@ -1098,7 +979,7 @@ module RubyIndexer
|
|
1098
979
|
# inside of the ["A", "B"] nesting, then we should not concatenate the nesting with the name or else we'll end up
|
1099
980
|
# with `A::B::A::B::Foo`. This method will remove any redundant parts from the final name based on the reference and
|
1100
981
|
# the nesting
|
1101
|
-
|
982
|
+
#: (String name, Array[String] nesting) -> String
|
1102
983
|
def build_non_redundant_full_name(name, nesting)
|
1103
984
|
# If there's no nesting, then we can just return the name as is
|
1104
985
|
return name if nesting.empty?
|
@@ -1119,18 +1000,7 @@ module RubyIndexer
|
|
1119
1000
|
name_parts.join("::")
|
1120
1001
|
end
|
1121
1002
|
|
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
|
1003
|
+
#: (String full_name, Array[String] seen_names) -> Array[(Entry::Namespace | Entry::ConstantAlias | Entry::UnresolvedConstantAlias)]?
|
1134
1004
|
def direct_or_aliased_constant(full_name, seen_names)
|
1135
1005
|
entries = @entries[full_name] || @entries[follow_aliased_namespace(full_name)]
|
1136
1006
|
|
@@ -1146,13 +1016,7 @@ module RubyIndexer
|
|
1146
1016
|
|
1147
1017
|
# Attempt to resolve a given unresolved method alias. This method returns the resolved alias if we managed to
|
1148
1018
|
# 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
|
1019
|
+
#: (Entry::UnresolvedMethodAlias entry, String receiver_name, Array[String] seen_names) -> (Entry::MethodAlias | Entry::UnresolvedMethodAlias)
|
1156
1020
|
def resolve_method_alias(entry, receiver_name, seen_names)
|
1157
1021
|
new_name = entry.new_name
|
1158
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
|
-
|
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 &&
|