ruby-lsp 0.23.15 → 0.26.9
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/VERSION +1 -1
- data/exe/ruby-lsp +17 -14
- data/exe/ruby-lsp-check +0 -4
- data/exe/ruby-lsp-launcher +41 -14
- data/exe/ruby-lsp-test-exec +6 -0
- data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +0 -1
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +0 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -3
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +42 -20
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -7
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +49 -62
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +84 -74
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -9
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +9 -14
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +4 -4
- data/lib/ruby_lsp/addon.rb +44 -15
- data/lib/ruby_lsp/base_server.rb +56 -37
- data/lib/ruby_lsp/client_capabilities.rb +6 -1
- data/lib/ruby_lsp/document.rb +174 -62
- data/lib/ruby_lsp/erb_document.rb +10 -8
- data/lib/ruby_lsp/global_state.rb +86 -33
- data/lib/ruby_lsp/internal.rb +6 -3
- data/lib/ruby_lsp/listeners/completion.rb +22 -11
- data/lib/ruby_lsp/listeners/definition.rb +41 -21
- data/lib/ruby_lsp/listeners/document_highlight.rb +26 -1
- data/lib/ruby_lsp/listeners/document_link.rb +64 -28
- data/lib/ruby_lsp/listeners/hover.rb +27 -16
- data/lib/ruby_lsp/listeners/inlay_hints.rb +5 -3
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +2 -2
- data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
- data/lib/ruby_lsp/listeners/spec_style.rb +155 -79
- data/lib/ruby_lsp/listeners/test_discovery.rb +39 -21
- data/lib/ruby_lsp/listeners/test_style.rb +75 -35
- data/lib/ruby_lsp/rbs_document.rb +3 -6
- data/lib/ruby_lsp/requests/code_action_resolve.rb +83 -58
- data/lib/ruby_lsp/requests/code_actions.rb +20 -5
- data/lib/ruby_lsp/requests/code_lens.rb +27 -6
- data/lib/ruby_lsp/requests/completion.rb +3 -3
- data/lib/ruby_lsp/requests/completion_resolve.rb +8 -6
- data/lib/ruby_lsp/requests/definition.rb +4 -7
- data/lib/ruby_lsp/requests/discover_tests.rb +2 -2
- data/lib/ruby_lsp/requests/document_highlight.rb +2 -2
- data/lib/ruby_lsp/requests/document_link.rb +1 -1
- data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +64 -12
- data/lib/ruby_lsp/requests/hover.rb +3 -6
- data/lib/ruby_lsp/requests/inlay_hints.rb +4 -4
- data/lib/ruby_lsp/requests/on_type_formatting.rb +1 -1
- data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
- data/lib/ruby_lsp/requests/references.rb +10 -21
- data/lib/ruby_lsp/requests/rename.rb +9 -10
- data/lib/ruby_lsp/requests/request.rb +8 -8
- data/lib/ruby_lsp/requests/selection_ranges.rb +2 -2
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +2 -2
- data/lib/ruby_lsp/requests/signature_help.rb +2 -2
- data/lib/ruby_lsp/requests/support/annotation.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +9 -12
- data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
- data/lib/ruby_lsp/requests/support/package_url.rb +414 -0
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +7 -1
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +13 -3
- data/lib/ruby_lsp/requests/support/source_uri.rb +7 -4
- data/lib/ruby_lsp/requests/support/test_item.rb +7 -1
- data/lib/ruby_lsp/requests/workspace_symbol.rb +20 -12
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +1 -4
- data/lib/ruby_lsp/response_builders/document_symbol.rb +2 -3
- data/lib/ruby_lsp/response_builders/hover.rb +1 -4
- data/lib/ruby_lsp/response_builders/response_builder.rb +6 -7
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +4 -5
- data/lib/ruby_lsp/response_builders/signature_help.rb +1 -2
- data/lib/ruby_lsp/response_builders/test_collection.rb +29 -3
- data/lib/ruby_lsp/ruby_document.rb +14 -42
- data/lib/ruby_lsp/scripts/compose_bundle.rb +3 -3
- data/lib/ruby_lsp/scripts/compose_bundle_windows.rb +3 -1
- data/lib/ruby_lsp/server.rb +173 -130
- data/lib/ruby_lsp/setup_bundler.rb +114 -47
- data/lib/ruby_lsp/static_docs.rb +1 -0
- data/lib/ruby_lsp/store.rb +6 -16
- data/lib/ruby_lsp/test_helper.rb +1 -4
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +121 -17
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +65 -25
- data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +16 -18
- data/lib/ruby_lsp/utils.rb +102 -13
- data/static_docs/break.md +103 -0
- metadata +8 -33
- data/lib/ruby_indexer/test/class_variables_test.rb +0 -140
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +0 -770
- data/lib/ruby_indexer/test/configuration_test.rb +0 -280
- data/lib/ruby_indexer/test/constant_test.rb +0 -402
- data/lib/ruby_indexer/test/enhancements_test.rb +0 -325
- data/lib/ruby_indexer/test/global_variable_test.rb +0 -49
- data/lib/ruby_indexer/test/index_test.rb +0 -2190
- data/lib/ruby_indexer/test/instance_variables_test.rb +0 -240
- data/lib/ruby_indexer/test/method_test.rb +0 -973
- data/lib/ruby_indexer/test/prefix_tree_test.rb +0 -150
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +0 -380
- data/lib/ruby_indexer/test/reference_finder_test.rb +0 -330
- data/lib/ruby_indexer/test/test_case.rb +0 -51
- data/lib/ruby_indexer/test/uri_test.rb +0 -85
- data/lib/ruby_lsp/load_sorbet.rb +0 -62
|
@@ -3,13 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
module RubyIndexer
|
|
5
5
|
class Entry
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
PUBLIC = new(:public)
|
|
9
|
-
PROTECTED = new(:protected)
|
|
10
|
-
PRIVATE = new(:private)
|
|
11
|
-
end
|
|
12
|
-
end
|
|
6
|
+
#: Configuration
|
|
7
|
+
attr_reader :configuration
|
|
13
8
|
|
|
14
9
|
#: String
|
|
15
10
|
attr_reader :name
|
|
@@ -22,31 +17,32 @@ module RubyIndexer
|
|
|
22
17
|
|
|
23
18
|
alias_method :name_location, :location
|
|
24
19
|
|
|
25
|
-
#:
|
|
20
|
+
#: Symbol
|
|
26
21
|
attr_accessor :visibility
|
|
27
22
|
|
|
28
|
-
#: (String name, URI::Generic uri, Location location, String? comments) -> void
|
|
29
|
-
def initialize(name, uri, location, comments)
|
|
23
|
+
#: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments) -> void
|
|
24
|
+
def initialize(configuration, name, uri, location, comments)
|
|
25
|
+
@configuration = configuration
|
|
30
26
|
@name = name
|
|
31
27
|
@uri = uri
|
|
32
28
|
@comments = comments
|
|
33
|
-
@visibility =
|
|
29
|
+
@visibility = :public #: Symbol
|
|
34
30
|
@location = location
|
|
35
31
|
end
|
|
36
32
|
|
|
37
33
|
#: -> bool
|
|
38
34
|
def public?
|
|
39
|
-
visibility ==
|
|
35
|
+
@visibility == :public
|
|
40
36
|
end
|
|
41
37
|
|
|
42
38
|
#: -> bool
|
|
43
39
|
def protected?
|
|
44
|
-
visibility ==
|
|
40
|
+
@visibility == :protected
|
|
45
41
|
end
|
|
46
42
|
|
|
47
43
|
#: -> bool
|
|
48
44
|
def private?
|
|
49
|
-
visibility ==
|
|
45
|
+
@visibility == :private
|
|
50
46
|
end
|
|
51
47
|
|
|
52
48
|
#: -> String
|
|
@@ -90,7 +86,7 @@ module RubyIndexer
|
|
|
90
86
|
correct_group.filter_map do |comment|
|
|
91
87
|
content = comment.slice.chomp
|
|
92
88
|
|
|
93
|
-
if content.valid_encoding?
|
|
89
|
+
if content.valid_encoding? && !content.match?(@configuration.magic_comment_regex)
|
|
94
90
|
content.delete_prefix!("#")
|
|
95
91
|
content.delete_prefix!(" ")
|
|
96
92
|
content
|
|
@@ -106,12 +102,8 @@ module RubyIndexer
|
|
|
106
102
|
end
|
|
107
103
|
end
|
|
108
104
|
|
|
105
|
+
# @abstract
|
|
109
106
|
class ModuleOperation
|
|
110
|
-
extend T::Sig
|
|
111
|
-
extend T::Helpers
|
|
112
|
-
|
|
113
|
-
abstract!
|
|
114
|
-
|
|
115
107
|
#: String
|
|
116
108
|
attr_reader :module_name
|
|
117
109
|
|
|
@@ -124,12 +116,8 @@ module RubyIndexer
|
|
|
124
116
|
class Include < ModuleOperation; end
|
|
125
117
|
class Prepend < ModuleOperation; end
|
|
126
118
|
|
|
119
|
+
# @abstract
|
|
127
120
|
class Namespace < Entry
|
|
128
|
-
extend T::Sig
|
|
129
|
-
extend T::Helpers
|
|
130
|
-
|
|
131
|
-
abstract!
|
|
132
|
-
|
|
133
121
|
#: Array[String]
|
|
134
122
|
attr_reader :nesting
|
|
135
123
|
|
|
@@ -137,13 +125,13 @@ module RubyIndexer
|
|
|
137
125
|
#: Location
|
|
138
126
|
attr_reader :name_location
|
|
139
127
|
|
|
140
|
-
#: (Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments) -> void
|
|
141
|
-
def initialize(nesting, uri, location, name_location, comments)
|
|
128
|
+
#: (Configuration configuration, Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments) -> void
|
|
129
|
+
def initialize(configuration, nesting, uri, location, name_location, comments) # rubocop:disable Metrics/ParameterLists
|
|
142
130
|
@name = nesting.join("::") #: String
|
|
143
131
|
# The original nesting where this namespace was discovered
|
|
144
132
|
@nesting = nesting
|
|
145
133
|
|
|
146
|
-
super(@name, uri, location, comments)
|
|
134
|
+
super(configuration, @name, uri, location, comments)
|
|
147
135
|
|
|
148
136
|
@name_location = name_location
|
|
149
137
|
end
|
|
@@ -176,9 +164,9 @@ module RubyIndexer
|
|
|
176
164
|
#: String?
|
|
177
165
|
attr_reader :parent_class
|
|
178
166
|
|
|
179
|
-
#: (Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments, String? parent_class) -> void
|
|
180
|
-
def initialize(nesting, uri, location, name_location, comments, parent_class) # rubocop:disable Metrics/ParameterLists
|
|
181
|
-
super(nesting, uri, location, name_location, comments)
|
|
167
|
+
#: (Configuration configuration, Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments, String? parent_class) -> void
|
|
168
|
+
def initialize(configuration, nesting, uri, location, name_location, comments, parent_class) # rubocop:disable Metrics/ParameterLists
|
|
169
|
+
super(configuration, nesting, uri, location, name_location, comments)
|
|
182
170
|
@parent_class = parent_class
|
|
183
171
|
end
|
|
184
172
|
|
|
@@ -201,12 +189,8 @@ module RubyIndexer
|
|
|
201
189
|
class Constant < Entry
|
|
202
190
|
end
|
|
203
191
|
|
|
192
|
+
# @abstract
|
|
204
193
|
class Parameter
|
|
205
|
-
extend T::Helpers
|
|
206
|
-
extend T::Sig
|
|
207
|
-
|
|
208
|
-
abstract!
|
|
209
|
-
|
|
210
194
|
# Name includes just the name of the parameter, excluding symbols like splats
|
|
211
195
|
#: Symbol
|
|
212
196
|
attr_reader :name
|
|
@@ -300,24 +284,23 @@ module RubyIndexer
|
|
|
300
284
|
end
|
|
301
285
|
end
|
|
302
286
|
|
|
287
|
+
# @abstract
|
|
303
288
|
class Member < Entry
|
|
304
|
-
extend T::Sig
|
|
305
|
-
extend T::Helpers
|
|
306
|
-
|
|
307
|
-
abstract!
|
|
308
|
-
|
|
309
289
|
#: Entry::Namespace?
|
|
310
290
|
attr_reader :owner
|
|
311
291
|
|
|
312
|
-
#: (String name, URI::Generic uri, Location location, String? comments,
|
|
313
|
-
def initialize(name, uri, location, comments, visibility, owner) # rubocop:disable Metrics/ParameterLists
|
|
314
|
-
super(name, uri, location, comments)
|
|
292
|
+
#: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments, Symbol visibility, Entry::Namespace? owner) -> void
|
|
293
|
+
def initialize(configuration, name, uri, location, comments, visibility, owner) # rubocop:disable Metrics/ParameterLists
|
|
294
|
+
super(configuration, name, uri, location, comments)
|
|
315
295
|
@visibility = visibility
|
|
316
296
|
@owner = owner
|
|
317
297
|
end
|
|
318
298
|
|
|
319
|
-
|
|
320
|
-
|
|
299
|
+
# @abstract
|
|
300
|
+
#: -> Array[Signature]
|
|
301
|
+
def signatures
|
|
302
|
+
raise AbstractMethodInvokedError
|
|
303
|
+
end
|
|
321
304
|
|
|
322
305
|
#: -> String
|
|
323
306
|
def decorated_parameters
|
|
@@ -354,6 +337,7 @@ module RubyIndexer
|
|
|
354
337
|
end
|
|
355
338
|
|
|
356
339
|
class Method < Member
|
|
340
|
+
# @override
|
|
357
341
|
#: Array[Signature]
|
|
358
342
|
attr_reader :signatures
|
|
359
343
|
|
|
@@ -361,9 +345,9 @@ module RubyIndexer
|
|
|
361
345
|
#: Location
|
|
362
346
|
attr_reader :name_location
|
|
363
347
|
|
|
364
|
-
#: (String name, URI::Generic uri, Location location, Location name_location, String? comments, Array[Signature] signatures,
|
|
365
|
-
def initialize(name, uri, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists
|
|
366
|
-
super(name, uri, location, comments, visibility, owner)
|
|
348
|
+
#: (Configuration configuration, String name, URI::Generic uri, Location location, Location name_location, String? comments, Array[Signature] signatures, Symbol visibility, Entry::Namespace? owner) -> void
|
|
349
|
+
def initialize(configuration, name, uri, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists
|
|
350
|
+
super(configuration, name, uri, location, comments, visibility, owner)
|
|
367
351
|
@signatures = signatures
|
|
368
352
|
@name_location = name_location
|
|
369
353
|
end
|
|
@@ -386,9 +370,9 @@ module RubyIndexer
|
|
|
386
370
|
#: Array[String]
|
|
387
371
|
attr_reader :nesting
|
|
388
372
|
|
|
389
|
-
#: (String target, Array[String] nesting, String name, URI::Generic uri, Location location, String? comments) -> void
|
|
390
|
-
def initialize(target, nesting, name, uri, location, comments) # rubocop:disable Metrics/ParameterLists
|
|
391
|
-
super(name, uri, location, comments)
|
|
373
|
+
#: (Configuration configuration, String target, Array[String] nesting, String name, URI::Generic uri, Location location, String? comments) -> void
|
|
374
|
+
def initialize(configuration, target, nesting, name, uri, location, comments) # rubocop:disable Metrics/ParameterLists
|
|
375
|
+
super(configuration, name, uri, location, comments)
|
|
392
376
|
|
|
393
377
|
@target = target
|
|
394
378
|
@nesting = nesting
|
|
@@ -403,6 +387,7 @@ module RubyIndexer
|
|
|
403
387
|
#: (String target, UnresolvedConstantAlias unresolved_alias) -> void
|
|
404
388
|
def initialize(target, unresolved_alias)
|
|
405
389
|
super(
|
|
390
|
+
unresolved_alias.configuration,
|
|
406
391
|
unresolved_alias.name,
|
|
407
392
|
unresolved_alias.uri,
|
|
408
393
|
unresolved_alias.location,
|
|
@@ -422,9 +407,9 @@ module RubyIndexer
|
|
|
422
407
|
#: Entry::Namespace?
|
|
423
408
|
attr_reader :owner
|
|
424
409
|
|
|
425
|
-
#: (String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
|
|
426
|
-
def initialize(name, uri, location, comments, owner)
|
|
427
|
-
super(name, uri, location, comments)
|
|
410
|
+
#: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
|
|
411
|
+
def initialize(configuration, name, uri, location, comments, owner) # rubocop:disable Metrics/ParameterLists
|
|
412
|
+
super(configuration, name, uri, location, comments)
|
|
428
413
|
@owner = owner
|
|
429
414
|
end
|
|
430
415
|
end
|
|
@@ -434,9 +419,9 @@ module RubyIndexer
|
|
|
434
419
|
#: Entry::Namespace?
|
|
435
420
|
attr_reader :owner
|
|
436
421
|
|
|
437
|
-
#: (String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
|
|
438
|
-
def initialize(name, uri, location, comments, owner)
|
|
439
|
-
super(name, uri, location, comments)
|
|
422
|
+
#: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
|
|
423
|
+
def initialize(configuration, name, uri, location, comments, owner) # rubocop:disable Metrics/ParameterLists
|
|
424
|
+
super(configuration, name, uri, location, comments)
|
|
440
425
|
@owner = owner
|
|
441
426
|
end
|
|
442
427
|
end
|
|
@@ -451,9 +436,9 @@ module RubyIndexer
|
|
|
451
436
|
#: Entry::Namespace?
|
|
452
437
|
attr_reader :owner
|
|
453
438
|
|
|
454
|
-
#: (String new_name, String old_name, Entry::Namespace? owner, URI::Generic uri, Location location, String? comments) -> void
|
|
455
|
-
def initialize(new_name, old_name, owner, uri, location, comments) # rubocop:disable Metrics/ParameterLists
|
|
456
|
-
super(new_name, uri, location, comments)
|
|
439
|
+
#: (Configuration configuration, String new_name, String old_name, Entry::Namespace? owner, URI::Generic uri, Location location, String? comments) -> void
|
|
440
|
+
def initialize(configuration, new_name, old_name, owner, uri, location, comments) # rubocop:disable Metrics/ParameterLists
|
|
441
|
+
super(configuration, new_name, uri, location, comments)
|
|
457
442
|
|
|
458
443
|
@new_name = new_name
|
|
459
444
|
@old_name = old_name
|
|
@@ -476,6 +461,7 @@ module RubyIndexer
|
|
|
476
461
|
full_comments << target.comments
|
|
477
462
|
|
|
478
463
|
super(
|
|
464
|
+
unresolved_alias.configuration,
|
|
479
465
|
unresolved_alias.new_name,
|
|
480
466
|
unresolved_alias.uri,
|
|
481
467
|
unresolved_alias.location,
|
|
@@ -563,7 +549,8 @@ module RubyIndexer
|
|
|
563
549
|
end
|
|
564
550
|
|
|
565
551
|
keyword_hash_nodes, positional_args = arguments.partition { |arg| arg.is_a?(Prism::KeywordHashNode) }
|
|
566
|
-
keyword_args =
|
|
552
|
+
keyword_args = keyword_hash_nodes.first #: as Prism::KeywordHashNode?
|
|
553
|
+
&.elements
|
|
567
554
|
forwarding_arguments, positionals = positional_args.partition do |arg|
|
|
568
555
|
arg.is_a?(Prism::ForwardingArgumentsNode)
|
|
569
556
|
end
|
|
@@ -36,12 +36,10 @@ module RubyIndexer
|
|
|
36
36
|
|
|
37
37
|
# Returns the unresolved name for a constant reference including all parts of a constant path, or `nil` if the
|
|
38
38
|
# constant contains dynamic or incomplete parts
|
|
39
|
-
#: (
|
|
39
|
+
#: (Prism::Node) -> String?
|
|
40
40
|
def constant_name(node)
|
|
41
41
|
case node
|
|
42
|
-
when Prism::
|
|
43
|
-
nil
|
|
44
|
-
else
|
|
42
|
+
when Prism::ConstantPathNode, Prism::ConstantReadNode, Prism::ConstantPathTargetNode
|
|
45
43
|
node.full_name
|
|
46
44
|
end
|
|
47
45
|
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
|
|
@@ -60,7 +58,7 @@ module RubyIndexer
|
|
|
60
58
|
@entries = {} #: Hash[String, Array[Entry]]
|
|
61
59
|
|
|
62
60
|
# Holds all entries in the index using a prefix tree for searching based on prefixes to provide autocompletion
|
|
63
|
-
@entries_tree = PrefixTree
|
|
61
|
+
@entries_tree = PrefixTree.new #: PrefixTree[Array[Entry]]
|
|
64
62
|
|
|
65
63
|
# Holds references to where entries where discovered so that we can easily delete them
|
|
66
64
|
# {
|
|
@@ -71,7 +69,7 @@ module RubyIndexer
|
|
|
71
69
|
@uris_to_entries = {} #: Hash[String, Array[Entry]]
|
|
72
70
|
|
|
73
71
|
# Holds all require paths for every indexed item so that we can provide autocomplete for requires
|
|
74
|
-
@require_paths_tree = PrefixTree
|
|
72
|
+
@require_paths_tree = PrefixTree.new #: PrefixTree[URI::Generic]
|
|
75
73
|
|
|
76
74
|
# Holds the linearized ancestors list for every namespace
|
|
77
75
|
@ancestors = {} #: Hash[String, Array[String]]
|
|
@@ -147,7 +145,7 @@ module RubyIndexer
|
|
|
147
145
|
|
|
148
146
|
# Searches for a constant based on an unqualified name and returns the first possible match regardless of whether
|
|
149
147
|
# there are more possible matching entries
|
|
150
|
-
#: (String name) -> Array[
|
|
148
|
+
#: (String name) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
|
151
149
|
def first_unqualified_const(name)
|
|
152
150
|
# Look for an exact match first
|
|
153
151
|
_name, entries = @entries.find do |const_name, _entries|
|
|
@@ -161,15 +159,7 @@ module RubyIndexer
|
|
|
161
159
|
end
|
|
162
160
|
end
|
|
163
161
|
|
|
164
|
-
|
|
165
|
-
entries,
|
|
166
|
-
T.nilable(T::Array[T.any(
|
|
167
|
-
Entry::Namespace,
|
|
168
|
-
Entry::ConstantAlias,
|
|
169
|
-
Entry::UnresolvedConstantAlias,
|
|
170
|
-
Entry::Constant,
|
|
171
|
-
)]),
|
|
172
|
-
)
|
|
162
|
+
entries #: as Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
|
173
163
|
end
|
|
174
164
|
|
|
175
165
|
# Searches entries in the index based on an exact prefix, intended for providing autocomplete. All possible matches
|
|
@@ -205,12 +195,13 @@ module RubyIndexer
|
|
|
205
195
|
end
|
|
206
196
|
|
|
207
197
|
# Fuzzy searches index entries based on Jaro-Winkler similarity. If no query is provided, all entries are returned
|
|
208
|
-
#: (String? query) -> Array[Entry]
|
|
209
|
-
def fuzzy_search(query)
|
|
198
|
+
#: (String? query) ?{ (Entry) -> bool? } -> Array[Entry]
|
|
199
|
+
def fuzzy_search(query, &condition)
|
|
210
200
|
unless query
|
|
211
201
|
entries = @entries.filter_map do |_name, entries|
|
|
212
202
|
next if entries.first.is_a?(Entry::SingletonClass)
|
|
213
203
|
|
|
204
|
+
entries = entries.select(&condition) if condition
|
|
214
205
|
entries
|
|
215
206
|
end
|
|
216
207
|
|
|
@@ -222,6 +213,9 @@ module RubyIndexer
|
|
|
222
213
|
results = @entries.filter_map do |name, entries|
|
|
223
214
|
next if entries.first.is_a?(Entry::SingletonClass)
|
|
224
215
|
|
|
216
|
+
entries = entries.select(&condition) if condition
|
|
217
|
+
next if entries.empty?
|
|
218
|
+
|
|
225
219
|
similarity = DidYouMean::JaroWinkler.distance(name.gsub("::", "").downcase, normalized_query)
|
|
226
220
|
[entries, -similarity] if similarity > ENTRY_SIMILARITY_THRESHOLD
|
|
227
221
|
end
|
|
@@ -272,19 +266,11 @@ module RubyIndexer
|
|
|
272
266
|
completion_items.values.map!(&:first)
|
|
273
267
|
end
|
|
274
268
|
|
|
275
|
-
#: (String name, Array[String] nesting) -> Array[Array[
|
|
269
|
+
#: (String name, Array[String] nesting) -> Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]]
|
|
276
270
|
def constant_completion_candidates(name, nesting)
|
|
277
271
|
# If we have a top level reference, then we don't need to include completions inside the current nesting
|
|
278
272
|
if name.start_with?("::")
|
|
279
|
-
return
|
|
280
|
-
@entries_tree.search(name.delete_prefix("::")),
|
|
281
|
-
T::Array[T::Array[T.any(
|
|
282
|
-
Entry::Constant,
|
|
283
|
-
Entry::ConstantAlias,
|
|
284
|
-
Entry::Namespace,
|
|
285
|
-
Entry::UnresolvedConstantAlias,
|
|
286
|
-
)]],
|
|
287
|
-
)
|
|
273
|
+
return @entries_tree.search(name.delete_prefix("::")) #: as Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]]
|
|
288
274
|
end
|
|
289
275
|
|
|
290
276
|
# Otherwise, we have to include every possible constant the user might be referring to. This is essentially the
|
|
@@ -309,16 +295,19 @@ module RubyIndexer
|
|
|
309
295
|
|
|
310
296
|
# Top level constants
|
|
311
297
|
entries.concat(@entries_tree.search(name))
|
|
298
|
+
|
|
299
|
+
# Filter only constants since methods may have names that look like constants
|
|
300
|
+
entries.select! do |definitions|
|
|
301
|
+
definitions.select! do |entry|
|
|
302
|
+
entry.is_a?(Entry::Constant) || entry.is_a?(Entry::ConstantAlias) ||
|
|
303
|
+
entry.is_a?(Entry::Namespace) || entry.is_a?(Entry::UnresolvedConstantAlias)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
definitions.any?
|
|
307
|
+
end
|
|
308
|
+
|
|
312
309
|
entries.uniq!
|
|
313
|
-
|
|
314
|
-
entries,
|
|
315
|
-
T::Array[T::Array[T.any(
|
|
316
|
-
Entry::Constant,
|
|
317
|
-
Entry::ConstantAlias,
|
|
318
|
-
Entry::Namespace,
|
|
319
|
-
Entry::UnresolvedConstantAlias,
|
|
320
|
-
)]],
|
|
321
|
-
)
|
|
310
|
+
entries #: as Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]]
|
|
322
311
|
end
|
|
323
312
|
|
|
324
313
|
# Resolve a constant to its declaration based on its name and the nesting where the reference was found. Parameter
|
|
@@ -328,7 +317,7 @@ module RubyIndexer
|
|
|
328
317
|
# nesting: the nesting structure where the reference was found (e.g.: ["Foo", "Bar"])
|
|
329
318
|
# seen_names: this parameter should not be used by consumers of the api. It is used to avoid infinite recursion when
|
|
330
319
|
# resolving circular references
|
|
331
|
-
#: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[
|
|
320
|
+
#: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
|
332
321
|
def resolve(name, nesting, seen_names = [])
|
|
333
322
|
# If we have a top level reference, then we just search for it straight away ignoring the nesting
|
|
334
323
|
if name.start_with?("::")
|
|
@@ -439,7 +428,10 @@ module RubyIndexer
|
|
|
439
428
|
(parts.length - 1).downto(0) do |i|
|
|
440
429
|
current_name = parts[0..i] #: as !nil
|
|
441
430
|
.join("::")
|
|
442
|
-
|
|
431
|
+
|
|
432
|
+
entry = unless seen_names.include?(current_name)
|
|
433
|
+
@entries[current_name]&.first
|
|
434
|
+
end
|
|
443
435
|
|
|
444
436
|
case entry
|
|
445
437
|
when Entry::ConstantAlias
|
|
@@ -586,7 +578,7 @@ module RubyIndexer
|
|
|
586
578
|
# and find inherited instance variables as well
|
|
587
579
|
#: (String variable_name, String owner_name) -> Array[Entry::InstanceVariable]?
|
|
588
580
|
def resolve_instance_variable(variable_name, owner_name)
|
|
589
|
-
entries =
|
|
581
|
+
entries = self[variable_name] #: as Array[Entry::InstanceVariable]?
|
|
590
582
|
return unless entries
|
|
591
583
|
|
|
592
584
|
ancestors = linearized_ancestors_of(owner_name)
|
|
@@ -610,7 +602,7 @@ module RubyIndexer
|
|
|
610
602
|
# include the `@` prefix
|
|
611
603
|
#: (String name, String owner_name) -> Array[(Entry::InstanceVariable | Entry::ClassVariable)]
|
|
612
604
|
def instance_variable_completion_candidates(name, owner_name)
|
|
613
|
-
entries =
|
|
605
|
+
entries = prefix_search(name).flatten #: as Array[Entry::InstanceVariable | Entry::ClassVariable]
|
|
614
606
|
# Avoid wasting time linearizing ancestors if we didn't find anything
|
|
615
607
|
return entries if entries.empty?
|
|
616
608
|
|
|
@@ -640,7 +632,7 @@ module RubyIndexer
|
|
|
640
632
|
|
|
641
633
|
#: (String name, String owner_name) -> Array[Entry::ClassVariable]
|
|
642
634
|
def class_variable_completion_candidates(name, owner_name)
|
|
643
|
-
entries =
|
|
635
|
+
entries = prefix_search(name).flatten #: as Array[Entry::ClassVariable]
|
|
644
636
|
# Avoid wasting time linearizing ancestors if we didn't find anything
|
|
645
637
|
return entries if entries.empty?
|
|
646
638
|
|
|
@@ -676,19 +668,22 @@ module RubyIndexer
|
|
|
676
668
|
# indirect means like including a module that than includes the ancestor. Trying to figure out exactly which
|
|
677
669
|
# ancestors need to be deleted is too expensive. Therefore, if any of the namespace entries has a change to their
|
|
678
670
|
# ancestor hash, we clear all ancestors and start linearizing lazily again from scratch
|
|
679
|
-
original_map =
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
).to_h { |e| [e.name, e.ancestor_hash] }
|
|
671
|
+
original_map = original_entries
|
|
672
|
+
.select { |e| e.is_a?(Entry::Namespace) } #: as Array[Entry::Namespace]
|
|
673
|
+
.to_h { |e| [e.name, e.ancestor_hash] }
|
|
683
674
|
|
|
684
|
-
updated_map =
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
).to_h { |e| [e.name, e.ancestor_hash] }
|
|
675
|
+
updated_map = updated_entries
|
|
676
|
+
.select { |e| e.is_a?(Entry::Namespace) } #: as Array[Entry::Namespace]
|
|
677
|
+
.to_h { |e| [e.name, e.ancestor_hash] }
|
|
688
678
|
|
|
689
679
|
@ancestors.clear if original_map.any? { |name, hash| updated_map[name] != hash }
|
|
690
680
|
end
|
|
691
681
|
|
|
682
|
+
#: -> void
|
|
683
|
+
def clear_ancestors
|
|
684
|
+
@ancestors.clear
|
|
685
|
+
end
|
|
686
|
+
|
|
692
687
|
#: -> bool
|
|
693
688
|
def empty?
|
|
694
689
|
@entries.empty?
|
|
@@ -713,12 +708,13 @@ module RubyIndexer
|
|
|
713
708
|
def existing_or_new_singleton_class(name)
|
|
714
709
|
*_namespace, unqualified_name = name.split("::")
|
|
715
710
|
full_singleton_name = "#{name}::<Class:#{unqualified_name}>"
|
|
716
|
-
singleton =
|
|
711
|
+
singleton = self[full_singleton_name]&.first #: as Entry::SingletonClass?
|
|
717
712
|
|
|
718
713
|
unless singleton
|
|
719
714
|
attached_ancestor = self[name]&.first #: as !nil
|
|
720
715
|
|
|
721
716
|
singleton = Entry::SingletonClass.new(
|
|
717
|
+
@configuration,
|
|
722
718
|
[full_singleton_name],
|
|
723
719
|
attached_ancestor.uri,
|
|
724
720
|
attached_ancestor.location,
|
|
@@ -841,14 +837,22 @@ module RubyIndexer
|
|
|
841
837
|
)
|
|
842
838
|
# Find the first class entry that has a parent class. Notice that if the developer makes a mistake and inherits
|
|
843
839
|
# from two different classes in different files, we simply ignore it
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
840
|
+
possible_parents = singleton_levels > 0 ? self[attached_class_name] : namespace_entries
|
|
841
|
+
superclass = nil #: Entry::Class?
|
|
842
|
+
|
|
843
|
+
possible_parents&.each do |n|
|
|
844
|
+
# Ignore non class entries
|
|
845
|
+
next unless n.is_a?(Entry::Class)
|
|
846
|
+
|
|
847
|
+
parent_class = n.parent_class
|
|
848
|
+
next unless parent_class
|
|
849
|
+
|
|
850
|
+
# Always set the superclass, but break early if we found one that isn't `::Object` (meaning we found an explicit
|
|
851
|
+
# parent class and not the implicit default). Note that when setting different parents to the same class, which
|
|
852
|
+
# is invalid, we pick whatever is the first one we find
|
|
853
|
+
superclass = n
|
|
854
|
+
break if parent_class != "::Object"
|
|
855
|
+
end
|
|
852
856
|
|
|
853
857
|
if superclass
|
|
854
858
|
# If the user makes a mistake and creates a class that inherits from itself, this method would throw a stack
|
|
@@ -882,7 +886,7 @@ module RubyIndexer
|
|
|
882
886
|
elsif singleton_levels > 0
|
|
883
887
|
# When computing the linearization for a module's singleton class, it inherits from the linearized ancestors of
|
|
884
888
|
# the `Module` class
|
|
885
|
-
mod =
|
|
889
|
+
mod = self[attached_class_name]&.find { |n| n.is_a?(Entry::Module) } #: as Entry::Module?
|
|
886
890
|
|
|
887
891
|
if mod
|
|
888
892
|
module_class_name_parts = ["Module"]
|
|
@@ -908,6 +912,9 @@ module RubyIndexer
|
|
|
908
912
|
target = resolve(entry.target, entry.nesting, seen_names)
|
|
909
913
|
return entry unless target
|
|
910
914
|
|
|
915
|
+
# Self referential alias can be unresolved we should bail out from resolving
|
|
916
|
+
return entry if target.first == entry
|
|
917
|
+
|
|
911
918
|
target_name = target.first #: as !nil
|
|
912
919
|
.name
|
|
913
920
|
resolved_alias = Entry::ConstantAlias.new(target_name, entry)
|
|
@@ -922,7 +929,7 @@ module RubyIndexer
|
|
|
922
929
|
resolved_alias
|
|
923
930
|
end
|
|
924
931
|
|
|
925
|
-
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[
|
|
932
|
+
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
|
926
933
|
def lookup_enclosing_scopes(name, nesting, seen_names)
|
|
927
934
|
nesting.length.downto(1) do |i|
|
|
928
935
|
namespace = nesting[0...i] #: as !nil
|
|
@@ -942,7 +949,7 @@ module RubyIndexer
|
|
|
942
949
|
nil
|
|
943
950
|
end
|
|
944
951
|
|
|
945
|
-
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[
|
|
952
|
+
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
|
946
953
|
def lookup_ancestor_chain(name, nesting, seen_names)
|
|
947
954
|
*nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
|
|
948
955
|
return if nesting_parts.empty?
|
|
@@ -1023,22 +1030,25 @@ module RubyIndexer
|
|
|
1023
1030
|
# Otherwise, push all of the leading parts of the nesting that aren't redundant into the name. For example, if we
|
|
1024
1031
|
# have a reference to `Foo::Bar` inside the `[Namespace, Foo]` nesting, then only the `Foo` part is redundant, but
|
|
1025
1032
|
# we still need to include the `Namespace` part
|
|
1026
|
-
|
|
1033
|
+
name_parts.unshift(*nesting[0...first_redundant_part])
|
|
1027
1034
|
name_parts.join("::")
|
|
1028
1035
|
end
|
|
1029
1036
|
|
|
1030
|
-
|
|
1037
|
+
# Tries to return direct entry from index then non seen canonicalized alias or nil
|
|
1038
|
+
#: (String full_name, Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
|
1031
1039
|
def direct_or_aliased_constant(full_name, seen_names)
|
|
1032
|
-
entries = @entries[full_name]
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1040
|
+
if (entries = @entries[full_name])
|
|
1041
|
+
return entries.map do |e|
|
|
1042
|
+
e.is_a?(Entry::UnresolvedConstantAlias) ? resolve_alias(e, seen_names) : e
|
|
1043
|
+
end #: as Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias])?
|
|
1044
|
+
end
|
|
1045
|
+
|
|
1046
|
+
aliased = follow_aliased_namespace(full_name, seen_names)
|
|
1047
|
+
return if full_name == aliased || seen_names.include?(aliased)
|
|
1048
|
+
|
|
1049
|
+
@entries[aliased]&.map do |e|
|
|
1050
|
+
e.is_a?(Entry::UnresolvedConstantAlias) ? resolve_alias(e, seen_names) : e
|
|
1051
|
+
end #: as Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias])?
|
|
1042
1052
|
end
|
|
1043
1053
|
|
|
1044
1054
|
# Attempt to resolve a given unresolved method alias. This method returns the resolved alias if we managed to
|
|
@@ -32,14 +32,14 @@ module RubyIndexer
|
|
|
32
32
|
# `Value` type.
|
|
33
33
|
#
|
|
34
34
|
# See https://en.wikipedia.org/wiki/Trie for more information
|
|
35
|
+
#: [Value]
|
|
35
36
|
class PrefixTree
|
|
36
|
-
extend T::Generic
|
|
37
|
-
|
|
38
|
-
Value = type_member
|
|
39
|
-
|
|
40
37
|
#: -> void
|
|
41
38
|
def initialize
|
|
42
|
-
@root = Node.new(
|
|
39
|
+
@root = Node.new(
|
|
40
|
+
"",
|
|
41
|
+
"", #: as untyped
|
|
42
|
+
) #: Node[Value]
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# Search the PrefixTree based on a given `prefix`. If `foo` is an entry in the tree, then searching for `fo` will
|
|
@@ -106,11 +106,8 @@ module RubyIndexer
|
|
|
106
106
|
node
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
+
#: [Value]
|
|
109
110
|
class Node
|
|
110
|
-
extend T::Generic
|
|
111
|
-
|
|
112
|
-
Value = type_member
|
|
113
|
-
|
|
114
111
|
#: Hash[String, Node[Value]]
|
|
115
112
|
attr_reader :children
|
|
116
113
|
|