ruby-lsp 0.23.16 → 0.23.17
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/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +16 -19
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +0 -3
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +9 -19
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +32 -68
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +1 -10
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +4 -4
- data/lib/ruby_indexer/test/index_test.rb +7 -0
- data/lib/ruby_indexer/test/method_test.rb +7 -7
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +4 -3
- data/lib/ruby_indexer/test/test_case.rb +7 -1
- data/lib/ruby_lsp/document.rb +1 -9
- data/lib/ruby_lsp/erb_document.rb +2 -2
- data/lib/ruby_lsp/listeners/completion.rb +8 -8
- data/lib/ruby_lsp/listeners/definition.rb +7 -7
- data/lib/ruby_lsp/listeners/document_link.rb +7 -10
- data/lib/ruby_lsp/listeners/hover.rb +10 -9
- data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
- data/lib/ruby_lsp/listeners/spec_style.rb +11 -11
- data/lib/ruby_lsp/listeners/test_style.rb +10 -5
- data/lib/ruby_lsp/rbs_document.rb +2 -2
- data/lib/ruby_lsp/requests/code_action_resolve.rb +44 -39
- data/lib/ruby_lsp/requests/code_lens.rb +15 -3
- data/lib/ruby_lsp/requests/completion.rb +2 -2
- data/lib/ruby_lsp/requests/definition.rb +3 -4
- data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
- 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 +0 -2
- data/lib/ruby_lsp/requests/hover.rb +1 -1
- data/lib/ruby_lsp/requests/inlay_hints.rb +1 -1
- data/lib/ruby_lsp/requests/references.rb +1 -16
- data/lib/ruby_lsp/requests/rename.rb +1 -4
- data/lib/ruby_lsp/requests/request.rb +2 -1
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
- data/lib/ruby_lsp/requests/signature_help.rb +1 -1
- data/lib/ruby_lsp/requests/support/annotation.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +0 -5
- data/lib/ruby_lsp/requests/support/test_item.rb +6 -0
- data/lib/ruby_lsp/response_builders/document_symbol.rb +1 -1
- data/lib/ruby_lsp/response_builders/test_collection.rb +37 -0
- data/lib/ruby_lsp/ruby_document.rb +2 -32
- data/lib/ruby_lsp/server.rb +36 -21
- data/lib/ruby_lsp/store.rb +6 -6
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +31 -4
- data/lib/ruby_lsp/utils.rb +43 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 783a43ad6688b46f4edcb4662a06d9fa9277ecc35475e64189c02547ab4f980b
|
4
|
+
data.tar.gz: 3f4b78c3f7909886d8642d7608d4ef7d358c41ca55fa118380fa2082119864ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb4be502edd93cd9ce01b505486f035733927076138447bd30607dda326bb40432c1ce0c8c50751252acf5098fbed24824a2c7e578b9914206411cbb7e869268
|
7
|
+
data.tar.gz: ce0ec2cdf2311ae7fda5c5c53fd3abcc122a7c6bcf031dd2dd30d8d65555e51e722985fbc58f75cce94b8591e36f6e404283f67d17c8ad58438c8ba5d7b82b39
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.23.
|
1
|
+
0.23.17
|
@@ -132,7 +132,7 @@ module RubyIndexer
|
|
132
132
|
name = (expression.is_a?(Prism::SelfNode) ? "<Class:#{last_name_in_stack}>" : "<Class:#{expression.slice}>")
|
133
133
|
real_nesting = Index.actual_nesting(@stack, name)
|
134
134
|
|
135
|
-
existing_entries =
|
135
|
+
existing_entries = @index[real_nesting.join("::")] #: as Array[Entry::SingletonClass]?
|
136
136
|
|
137
137
|
if existing_entries
|
138
138
|
entry = existing_entries.first #: as !nil
|
@@ -265,11 +265,11 @@ module RubyIndexer
|
|
265
265
|
when :include, :prepend, :extend
|
266
266
|
handle_module_operation(node, message)
|
267
267
|
when :public
|
268
|
-
handle_visibility_change(node,
|
268
|
+
handle_visibility_change(node, :public)
|
269
269
|
when :protected
|
270
|
-
handle_visibility_change(node,
|
270
|
+
handle_visibility_change(node, :protected)
|
271
271
|
when :private
|
272
|
-
handle_visibility_change(node,
|
272
|
+
handle_visibility_change(node, :private)
|
273
273
|
when :module_function
|
274
274
|
handle_module_function(node)
|
275
275
|
when :private_class_method
|
@@ -343,7 +343,7 @@ module RubyIndexer
|
|
343
343
|
name_location,
|
344
344
|
comments,
|
345
345
|
signatures,
|
346
|
-
|
346
|
+
:public,
|
347
347
|
singleton,
|
348
348
|
))
|
349
349
|
end
|
@@ -465,8 +465,8 @@ module RubyIndexer
|
|
465
465
|
handle_class_variable(node, node.name_loc)
|
466
466
|
end
|
467
467
|
|
468
|
-
#: (String name, Prism::Location node_location, Array[Entry::Signature] signatures, ?visibility:
|
469
|
-
def add_method(name, node_location, signatures, visibility:
|
468
|
+
#: (String name, Prism::Location node_location, Array[Entry::Signature] signatures, ?visibility: Symbol, ?comments: String?) -> void
|
469
|
+
def add_method(name, node_location, signatures, visibility: :public, comments: nil)
|
470
470
|
location = Location.from_prism_location(node_location, @code_units_cache)
|
471
471
|
|
472
472
|
@index.add(Entry::Method.new(
|
@@ -621,7 +621,7 @@ module RubyIndexer
|
|
621
621
|
# The private_constant method does not resolve the constant name. It always points to a constant that needs to
|
622
622
|
# exist in the current namespace
|
623
623
|
entries = @index[fully_qualify_name(name)]
|
624
|
-
entries&.each { |entry| entry.visibility =
|
624
|
+
entries&.each { |entry| entry.visibility = :private }
|
625
625
|
end
|
626
626
|
|
627
627
|
#: (Prism::CallNode node) -> void
|
@@ -868,7 +868,7 @@ module RubyIndexer
|
|
868
868
|
entry_owner_name = entry.owner&.name
|
869
869
|
next unless entry_owner_name
|
870
870
|
|
871
|
-
entry.visibility =
|
871
|
+
entry.visibility = :private
|
872
872
|
|
873
873
|
singleton = @index.existing_or_new_singleton_class(entry_owner_name)
|
874
874
|
location = Location.from_prism_location(argument.location, @code_units_cache)
|
@@ -879,7 +879,7 @@ module RubyIndexer
|
|
879
879
|
location,
|
880
880
|
collect_comments(node)&.concat(entry.comments),
|
881
881
|
entry.signatures,
|
882
|
-
|
882
|
+
:public,
|
883
883
|
singleton,
|
884
884
|
))
|
885
885
|
end
|
@@ -894,7 +894,7 @@ module RubyIndexer
|
|
894
894
|
# If we're passing a method definition directly to `private_class_method`, push a new private scope. That will be
|
895
895
|
# applied when the indexer finds the method definition and then popped on `call_node_leave`
|
896
896
|
if arguments.first.is_a?(Prism::DefNode)
|
897
|
-
@visibility_stack.push(VisibilityScope.new(visibility:
|
897
|
+
@visibility_stack.push(VisibilityScope.new(visibility: :private))
|
898
898
|
return
|
899
899
|
end
|
900
900
|
|
@@ -903,10 +903,9 @@ module RubyIndexer
|
|
903
903
|
|
904
904
|
# private_class_method accepts strings, symbols or arrays of strings and symbols as arguments. Here we build a
|
905
905
|
# single list of all of the method names that have to be made private
|
906
|
-
arrays, others =
|
907
|
-
|
908
|
-
|
909
|
-
)
|
906
|
+
arrays, others = arguments.partition do |argument|
|
907
|
+
argument.is_a?(Prism::ArrayNode)
|
908
|
+
end #: as [Array[Prism::ArrayNode], Array[Prism::Node]]
|
910
909
|
arrays.each { |array| others.concat(array.elements) }
|
911
910
|
|
912
911
|
names = others.filter_map do |argument|
|
@@ -922,9 +921,7 @@ module RubyIndexer
|
|
922
921
|
entries = @index.resolve_method(name, @index.existing_or_new_singleton_class(owner_name).name)
|
923
922
|
next unless entries
|
924
923
|
|
925
|
-
entries.each
|
926
|
-
entry.visibility = Entry::Visibility::PRIVATE
|
927
|
-
end
|
924
|
+
entries.each { |entry| entry.visibility = :private }
|
928
925
|
end
|
929
926
|
end
|
930
927
|
|
@@ -1038,7 +1035,7 @@ module RubyIndexer
|
|
1038
1035
|
name.split("::").last
|
1039
1036
|
end
|
1040
1037
|
|
1041
|
-
#: (Prism::CallNode,
|
1038
|
+
#: (Prism::CallNode, Symbol) -> void
|
1042
1039
|
def handle_visibility_change(node, visibility)
|
1043
1040
|
owner = @owner_stack.last
|
1044
1041
|
return unless owner
|
@@ -3,7 +3,6 @@
|
|
3
3
|
|
4
4
|
module RubyIndexer
|
5
5
|
class Enhancement
|
6
|
-
extend T::Sig
|
7
6
|
extend T::Helpers
|
8
7
|
|
9
8
|
abstract!
|
@@ -11,8 +10,6 @@ module RubyIndexer
|
|
11
10
|
@enhancements = [] #: Array[Class[Enhancement]]
|
12
11
|
|
13
12
|
class << self
|
14
|
-
extend T::Sig
|
15
|
-
|
16
13
|
#: (Class[Enhancement] child) -> void
|
17
14
|
def inherited(child)
|
18
15
|
@enhancements << child
|
@@ -3,14 +3,6 @@
|
|
3
3
|
|
4
4
|
module RubyIndexer
|
5
5
|
class Entry
|
6
|
-
class Visibility < T::Enum
|
7
|
-
enums do
|
8
|
-
PUBLIC = new(:public)
|
9
|
-
PROTECTED = new(:protected)
|
10
|
-
PRIVATE = new(:private)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
6
|
#: String
|
15
7
|
attr_reader :name
|
16
8
|
|
@@ -22,7 +14,7 @@ module RubyIndexer
|
|
22
14
|
|
23
15
|
alias_method :name_location, :location
|
24
16
|
|
25
|
-
#:
|
17
|
+
#: Symbol
|
26
18
|
attr_accessor :visibility
|
27
19
|
|
28
20
|
#: (String name, URI::Generic uri, Location location, String? comments) -> void
|
@@ -30,23 +22,23 @@ module RubyIndexer
|
|
30
22
|
@name = name
|
31
23
|
@uri = uri
|
32
24
|
@comments = comments
|
33
|
-
@visibility =
|
25
|
+
@visibility = :public #: Symbol
|
34
26
|
@location = location
|
35
27
|
end
|
36
28
|
|
37
29
|
#: -> bool
|
38
30
|
def public?
|
39
|
-
visibility ==
|
31
|
+
@visibility == :public
|
40
32
|
end
|
41
33
|
|
42
34
|
#: -> bool
|
43
35
|
def protected?
|
44
|
-
visibility ==
|
36
|
+
@visibility == :protected
|
45
37
|
end
|
46
38
|
|
47
39
|
#: -> bool
|
48
40
|
def private?
|
49
|
-
visibility ==
|
41
|
+
@visibility == :private
|
50
42
|
end
|
51
43
|
|
52
44
|
#: -> String
|
@@ -107,7 +99,6 @@ module RubyIndexer
|
|
107
99
|
end
|
108
100
|
|
109
101
|
class ModuleOperation
|
110
|
-
extend T::Sig
|
111
102
|
extend T::Helpers
|
112
103
|
|
113
104
|
abstract!
|
@@ -125,7 +116,6 @@ module RubyIndexer
|
|
125
116
|
class Prepend < ModuleOperation; end
|
126
117
|
|
127
118
|
class Namespace < Entry
|
128
|
-
extend T::Sig
|
129
119
|
extend T::Helpers
|
130
120
|
|
131
121
|
abstract!
|
@@ -203,7 +193,6 @@ module RubyIndexer
|
|
203
193
|
|
204
194
|
class Parameter
|
205
195
|
extend T::Helpers
|
206
|
-
extend T::Sig
|
207
196
|
|
208
197
|
abstract!
|
209
198
|
|
@@ -309,7 +298,7 @@ module RubyIndexer
|
|
309
298
|
#: Entry::Namespace?
|
310
299
|
attr_reader :owner
|
311
300
|
|
312
|
-
#: (String name, URI::Generic uri, Location location, String? comments,
|
301
|
+
#: (String name, URI::Generic uri, Location location, String? comments, Symbol visibility, Entry::Namespace? owner) -> void
|
313
302
|
def initialize(name, uri, location, comments, visibility, owner) # rubocop:disable Metrics/ParameterLists
|
314
303
|
super(name, uri, location, comments)
|
315
304
|
@visibility = visibility
|
@@ -361,7 +350,7 @@ module RubyIndexer
|
|
361
350
|
#: Location
|
362
351
|
attr_reader :name_location
|
363
352
|
|
364
|
-
#: (String name, URI::Generic uri, Location location, Location name_location, String? comments, Array[Signature] signatures,
|
353
|
+
#: (String name, URI::Generic uri, Location location, Location name_location, String? comments, Array[Signature] signatures, Symbol visibility, Entry::Namespace? owner) -> void
|
365
354
|
def initialize(name, uri, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists
|
366
355
|
super(name, uri, location, comments, visibility, owner)
|
367
356
|
@signatures = signatures
|
@@ -563,7 +552,8 @@ module RubyIndexer
|
|
563
552
|
end
|
564
553
|
|
565
554
|
keyword_hash_nodes, positional_args = arguments.partition { |arg| arg.is_a?(Prism::KeywordHashNode) }
|
566
|
-
keyword_args =
|
555
|
+
keyword_args = keyword_hash_nodes.first #: as Prism::KeywordHashNode?
|
556
|
+
&.elements
|
567
557
|
forwarding_arguments, positionals = positional_args.partition do |arg|
|
568
558
|
arg.is_a?(Prism::ForwardingArgumentsNode)
|
569
559
|
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
|
@@ -272,19 +262,11 @@ module RubyIndexer
|
|
272
262
|
completion_items.values.map!(&:first)
|
273
263
|
end
|
274
264
|
|
275
|
-
#: (String name, Array[String] nesting) -> Array[Array[
|
265
|
+
#: (String name, Array[String] nesting) -> Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]]
|
276
266
|
def constant_completion_candidates(name, nesting)
|
277
267
|
# If we have a top level reference, then we don't need to include completions inside the current nesting
|
278
268
|
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
|
-
)
|
269
|
+
return @entries_tree.search(name.delete_prefix("::")) #: as Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]] # rubocop:disable Layout/LineLength
|
288
270
|
end
|
289
271
|
|
290
272
|
# Otherwise, we have to include every possible constant the user might be referring to. This is essentially the
|
@@ -310,15 +292,7 @@ module RubyIndexer
|
|
310
292
|
# Top level constants
|
311
293
|
entries.concat(@entries_tree.search(name))
|
312
294
|
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
|
-
)
|
295
|
+
entries #: as Array[Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]] # rubocop:disable Layout/LineLength
|
322
296
|
end
|
323
297
|
|
324
298
|
# Resolve a constant to its declaration based on its name and the nesting where the reference was found. Parameter
|
@@ -328,7 +302,7 @@ module RubyIndexer
|
|
328
302
|
# nesting: the nesting structure where the reference was found (e.g.: ["Foo", "Bar"])
|
329
303
|
# seen_names: this parameter should not be used by consumers of the api. It is used to avoid infinite recursion when
|
330
304
|
# resolving circular references
|
331
|
-
#: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[
|
305
|
+
#: (String name, Array[String] nesting, ?Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
332
306
|
def resolve(name, nesting, seen_names = [])
|
333
307
|
# If we have a top level reference, then we just search for it straight away ignoring the nesting
|
334
308
|
if name.start_with?("::")
|
@@ -586,7 +560,7 @@ module RubyIndexer
|
|
586
560
|
# and find inherited instance variables as well
|
587
561
|
#: (String variable_name, String owner_name) -> Array[Entry::InstanceVariable]?
|
588
562
|
def resolve_instance_variable(variable_name, owner_name)
|
589
|
-
entries =
|
563
|
+
entries = self[variable_name] #: as Array[Entry::InstanceVariable]?
|
590
564
|
return unless entries
|
591
565
|
|
592
566
|
ancestors = linearized_ancestors_of(owner_name)
|
@@ -610,7 +584,7 @@ module RubyIndexer
|
|
610
584
|
# include the `@` prefix
|
611
585
|
#: (String name, String owner_name) -> Array[(Entry::InstanceVariable | Entry::ClassVariable)]
|
612
586
|
def instance_variable_completion_candidates(name, owner_name)
|
613
|
-
entries =
|
587
|
+
entries = prefix_search(name).flatten #: as Array[Entry::InstanceVariable | Entry::ClassVariable]
|
614
588
|
# Avoid wasting time linearizing ancestors if we didn't find anything
|
615
589
|
return entries if entries.empty?
|
616
590
|
|
@@ -640,7 +614,7 @@ module RubyIndexer
|
|
640
614
|
|
641
615
|
#: (String name, String owner_name) -> Array[Entry::ClassVariable]
|
642
616
|
def class_variable_completion_candidates(name, owner_name)
|
643
|
-
entries =
|
617
|
+
entries = prefix_search(name).flatten #: as Array[Entry::ClassVariable]
|
644
618
|
# Avoid wasting time linearizing ancestors if we didn't find anything
|
645
619
|
return entries if entries.empty?
|
646
620
|
|
@@ -676,15 +650,13 @@ module RubyIndexer
|
|
676
650
|
# indirect means like including a module that than includes the ancestor. Trying to figure out exactly which
|
677
651
|
# ancestors need to be deleted is too expensive. Therefore, if any of the namespace entries has a change to their
|
678
652
|
# 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] }
|
653
|
+
original_map = original_entries
|
654
|
+
.select { |e| e.is_a?(Entry::Namespace) } #: as Array[Entry::Namespace]
|
655
|
+
.to_h { |e| [e.name, e.ancestor_hash] }
|
683
656
|
|
684
|
-
updated_map =
|
685
|
-
|
686
|
-
|
687
|
-
).to_h { |e| [e.name, e.ancestor_hash] }
|
657
|
+
updated_map = updated_entries
|
658
|
+
.select { |e| e.is_a?(Entry::Namespace) } #: as Array[Entry::Namespace]
|
659
|
+
.to_h { |e| [e.name, e.ancestor_hash] }
|
688
660
|
|
689
661
|
@ancestors.clear if original_map.any? { |name, hash| updated_map[name] != hash }
|
690
662
|
end
|
@@ -713,7 +685,7 @@ module RubyIndexer
|
|
713
685
|
def existing_or_new_singleton_class(name)
|
714
686
|
*_namespace, unqualified_name = name.split("::")
|
715
687
|
full_singleton_name = "#{name}::<Class:#{unqualified_name}>"
|
716
|
-
singleton =
|
688
|
+
singleton = self[full_singleton_name]&.first #: as Entry::SingletonClass?
|
717
689
|
|
718
690
|
unless singleton
|
719
691
|
attached_ancestor = self[name]&.first #: as !nil
|
@@ -841,14 +813,11 @@ module RubyIndexer
|
|
841
813
|
)
|
842
814
|
# Find the first class entry that has a parent class. Notice that if the developer makes a mistake and inherits
|
843
815
|
# from two different classes in different files, we simply ignore it
|
844
|
-
superclass =
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
end,
|
850
|
-
T.nilable(Entry::Class),
|
851
|
-
)
|
816
|
+
superclass = if singleton_levels > 0
|
817
|
+
self[attached_class_name]&.find { |n| n.is_a?(Entry::Class) && n.parent_class }
|
818
|
+
else
|
819
|
+
namespace_entries.find { |n| n.is_a?(Entry::Class) && n.parent_class }
|
820
|
+
end #: as Entry::Class?
|
852
821
|
|
853
822
|
if superclass
|
854
823
|
# If the user makes a mistake and creates a class that inherits from itself, this method would throw a stack
|
@@ -882,7 +851,7 @@ module RubyIndexer
|
|
882
851
|
elsif singleton_levels > 0
|
883
852
|
# When computing the linearization for a module's singleton class, it inherits from the linearized ancestors of
|
884
853
|
# the `Module` class
|
885
|
-
mod =
|
854
|
+
mod = self[attached_class_name]&.find { |n| n.is_a?(Entry::Module) } #: as Entry::Module?
|
886
855
|
|
887
856
|
if mod
|
888
857
|
module_class_name_parts = ["Module"]
|
@@ -922,7 +891,7 @@ module RubyIndexer
|
|
922
891
|
resolved_alias
|
923
892
|
end
|
924
893
|
|
925
|
-
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[
|
894
|
+
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
926
895
|
def lookup_enclosing_scopes(name, nesting, seen_names)
|
927
896
|
nesting.length.downto(1) do |i|
|
928
897
|
namespace = nesting[0...i] #: as !nil
|
@@ -942,7 +911,7 @@ module RubyIndexer
|
|
942
911
|
nil
|
943
912
|
end
|
944
913
|
|
945
|
-
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[
|
914
|
+
#: (String name, Array[String] nesting, Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
946
915
|
def lookup_ancestor_chain(name, nesting, seen_names)
|
947
916
|
*nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
|
948
917
|
return if nesting_parts.empty?
|
@@ -1027,18 +996,13 @@ module RubyIndexer
|
|
1027
996
|
name_parts.join("::")
|
1028
997
|
end
|
1029
998
|
|
1030
|
-
#: (String full_name, Array[String] seen_names) -> Array[
|
999
|
+
#: (String full_name, Array[String] seen_names) -> Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias]?
|
1031
1000
|
def direct_or_aliased_constant(full_name, seen_names)
|
1032
1001
|
entries = @entries[full_name] || @entries[follow_aliased_namespace(full_name)]
|
1033
1002
|
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
Entry::Namespace,
|
1038
|
-
Entry::ConstantAlias,
|
1039
|
-
Entry::UnresolvedConstantAlias,
|
1040
|
-
)]),
|
1041
|
-
)
|
1003
|
+
entries&.map do |e|
|
1004
|
+
e.is_a?(Entry::UnresolvedConstantAlias) ? resolve_alias(e, seen_names) : e
|
1005
|
+
end #: as Array[Entry::Constant | Entry::ConstantAlias | Entry::Namespace | Entry::UnresolvedConstantAlias])?
|
1042
1006
|
end
|
1043
1007
|
|
1044
1008
|
# Attempt to resolve a given unresolved method alias. This method returns the resolved alias if we managed to
|
@@ -107,15 +107,6 @@ module RubyIndexer
|
|
107
107
|
location = to_ruby_indexer_location(member.location)
|
108
108
|
comments = comments_to_string(member)
|
109
109
|
|
110
|
-
visibility = case member.visibility
|
111
|
-
when :private
|
112
|
-
Entry::Visibility::PRIVATE
|
113
|
-
when :protected
|
114
|
-
Entry::Visibility::PROTECTED
|
115
|
-
else
|
116
|
-
Entry::Visibility::PUBLIC
|
117
|
-
end
|
118
|
-
|
119
110
|
real_owner = member.singleton? ? @index.existing_or_new_singleton_class(owner.name) : owner
|
120
111
|
signatures = signatures(member)
|
121
112
|
@index.add(Entry::Method.new(
|
@@ -125,7 +116,7 @@ module RubyIndexer
|
|
125
116
|
location,
|
126
117
|
comments,
|
127
118
|
signatures,
|
128
|
-
visibility,
|
119
|
+
member.visibility || :public,
|
129
120
|
real_owner,
|
130
121
|
))
|
131
122
|
end
|
@@ -8,7 +8,7 @@ module RubyIndexer
|
|
8
8
|
class << self
|
9
9
|
#: -> instance
|
10
10
|
def module_function_scope
|
11
|
-
new(module_func: true, visibility:
|
11
|
+
new(module_func: true, visibility: :private)
|
12
12
|
end
|
13
13
|
|
14
14
|
#: -> instance
|
@@ -17,14 +17,14 @@ module RubyIndexer
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
#:
|
20
|
+
#: Symbol
|
21
21
|
attr_reader :visibility
|
22
22
|
|
23
23
|
#: bool
|
24
24
|
attr_reader :module_func
|
25
25
|
|
26
|
-
#: (?visibility:
|
27
|
-
def initialize(visibility:
|
26
|
+
#: (?visibility: Symbol, ?module_func: bool) -> void
|
27
|
+
def initialize(visibility: :public, module_func: false)
|
28
28
|
@visibility = visibility
|
29
29
|
@module_func = module_func
|
30
30
|
end
|
@@ -2185,6 +2185,13 @@ module RubyIndexer
|
|
2185
2185
|
|
2186
2186
|
node = Prism.parse("class Foo; end").value.statements.body.first.constant_path
|
2187
2187
|
assert_equal("Foo", Index.constant_name(node))
|
2188
|
+
|
2189
|
+
node = Prism.parse(<<~RUBY).value.statements.body.first.constant_path
|
2190
|
+
class class Foo
|
2191
|
+
end
|
2192
|
+
end
|
2193
|
+
RUBY
|
2194
|
+
assert_nil(Index.constant_name(node))
|
2188
2195
|
end
|
2189
2196
|
end
|
2190
2197
|
end
|
@@ -100,9 +100,9 @@ module RubyIndexer
|
|
100
100
|
end
|
101
101
|
RUBY
|
102
102
|
|
103
|
-
assert_entry("foo", Entry::Method, "/fake/path/foo.rb:1-10:2-5", visibility:
|
104
|
-
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:4-2:4-14", visibility:
|
105
|
-
assert_entry("baz", Entry::Method, "/fake/path/foo.rb:8-2:8-14", visibility:
|
103
|
+
assert_entry("foo", Entry::Method, "/fake/path/foo.rb:1-10:2-5", visibility: :private)
|
104
|
+
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:4-2:4-14", visibility: :public)
|
105
|
+
assert_entry("baz", Entry::Method, "/fake/path/foo.rb:8-2:8-14", visibility: :protected)
|
106
106
|
end
|
107
107
|
|
108
108
|
def test_visibility_tracking_with_nested_class_or_modules
|
@@ -120,9 +120,9 @@ module RubyIndexer
|
|
120
120
|
end
|
121
121
|
RUBY
|
122
122
|
|
123
|
-
assert_entry("foo", Entry::Method, "/fake/path/foo.rb:3-2:3-14", visibility:
|
124
|
-
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:6-4:6-16", visibility:
|
125
|
-
assert_entry("baz", Entry::Method, "/fake/path/foo.rb:9-2:9-14", visibility:
|
123
|
+
assert_entry("foo", Entry::Method, "/fake/path/foo.rb:3-2:3-14", visibility: :private)
|
124
|
+
assert_entry("bar", Entry::Method, "/fake/path/foo.rb:6-4:6-16", visibility: :public)
|
125
|
+
assert_entry("baz", Entry::Method, "/fake/path/foo.rb:9-2:9-14", visibility: :private)
|
126
126
|
end
|
127
127
|
|
128
128
|
def test_visibility_tracking_with_module_function
|
@@ -147,7 +147,7 @@ module RubyIndexer
|
|
147
147
|
# The second entry points to the public singleton method
|
148
148
|
assert_equal("Test::<Class:Test>", second_entry&.owner&.name)
|
149
149
|
assert_instance_of(Entry::SingletonClass, second_entry&.owner)
|
150
|
-
assert_equal(
|
150
|
+
assert_equal(:public, second_entry&.visibility)
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
@@ -60,7 +60,7 @@ module RubyIndexer
|
|
60
60
|
entry = entries.find { |entry| entry.owner&.name == "Array" } #: as Entry::Method
|
61
61
|
assert_match(%r{/gems/rbs-.*/core/array.rbs}, entry.file_path)
|
62
62
|
assert_equal("array.rbs", entry.file_name)
|
63
|
-
assert_equal(
|
63
|
+
assert_equal(:public, entry.visibility)
|
64
64
|
|
65
65
|
# Using fixed positions would be fragile, so let's just check some basics.
|
66
66
|
assert_operator(entry.location.start_line, :>, 0)
|
@@ -373,8 +373,9 @@ module RubyIndexer
|
|
373
373
|
pathname = Pathname.new("/file.rbs")
|
374
374
|
indexer.process_signature(pathname, declarations)
|
375
375
|
entry = index[method_name] #: as !nil
|
376
|
-
.first
|
377
|
-
|
376
|
+
.first #: as Entry::Method
|
377
|
+
|
378
|
+
entry.signatures
|
378
379
|
end
|
379
380
|
end
|
380
381
|
end
|
@@ -11,6 +11,13 @@ module RubyIndexer
|
|
11
11
|
@default_indexed_entries = @index.instance_variable_get(:@entries).dup
|
12
12
|
end
|
13
13
|
|
14
|
+
def teardown
|
15
|
+
entries = @index.instance_variable_get(:@entries).values.flatten
|
16
|
+
entries.each do |entry|
|
17
|
+
assert_includes([:public, :private, :protected], entry.visibility)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
14
21
|
private
|
15
22
|
|
16
23
|
def index(source, uri: URI::Generic.from_path(path: "/fake/path/foo.rb"))
|
@@ -31,7 +38,6 @@ module RubyIndexer
|
|
31
38
|
":#{location.end_line - 1}-#{location.end_column}"
|
32
39
|
|
33
40
|
assert_equal(expected_location, location_string)
|
34
|
-
|
35
41
|
assert_equal(visibility, entry.visibility) if visibility
|
36
42
|
end
|
37
43
|
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -3,14 +3,6 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
class Document
|
6
|
-
class LanguageId < T::Enum
|
7
|
-
enums do
|
8
|
-
Ruby = new("ruby")
|
9
|
-
ERB = new("erb")
|
10
|
-
RBS = new("rbs")
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
6
|
extend T::Sig
|
15
7
|
extend T::Helpers
|
16
8
|
extend T::Generic
|
@@ -71,7 +63,7 @@ module RubyLsp
|
|
71
63
|
self.class == other.class && uri == other.uri && @source == other.source
|
72
64
|
end
|
73
65
|
|
74
|
-
sig { abstract.returns(
|
66
|
+
sig { abstract.returns(Symbol) }
|
75
67
|
def language_id; end
|
76
68
|
|
77
69
|
#: [T] (String request_name) { (Document[ParseResultType] document) -> T } -> T
|