ruby-lsp 0.17.6 → 0.17.7
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/index.rb +4 -1
- data/lib/ruby_indexer/test/index_test.rb +37 -0
- data/lib/ruby_lsp/document.rb +14 -24
- data/lib/ruby_lsp/global_state.rb +8 -4
- data/lib/ruby_lsp/listeners/completion.rb +27 -0
- data/lib/ruby_lsp/listeners/definition.rb +27 -3
- data/lib/ruby_lsp/listeners/hover.rb +38 -11
- data/lib/ruby_lsp/node_context.rb +65 -5
- data/lib/ruby_lsp/requests/completion_resolve.rb +2 -0
- data/lib/ruby_lsp/requests/definition.rb +2 -0
- data/lib/ruby_lsp/type_inferrer.rb +17 -19
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 671bab4fdbd77d1980781f55874d6cd448e1dcd11a6f534a176dfb00b098d2eb
|
4
|
+
data.tar.gz: bd12fd2ef58588b3b5386fec48c0f561140efff180988f1971b67f635f0e1042
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3a2a3115e1745ad7263b7e113ef13795f9a1ed1ee118128a9ab2aaad703b17551acbd929f820700e6650efb76421418a13a78270ac8d3aaff080edc46731aee
|
7
|
+
data.tar.gz: d29bb4d6c60727eef1a10905762a6d0c8946b7afc8aac6148ef970c8d752365f1577403497702f52a7211689cde7940b3d7cd1e1e0eb03d038e0dc6f7ceed738
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.17.
|
1
|
+
0.17.7
|
@@ -331,14 +331,17 @@ module RubyIndexer
|
|
331
331
|
params(
|
332
332
|
method_name: String,
|
333
333
|
receiver_name: String,
|
334
|
+
inherited_only: T::Boolean,
|
334
335
|
).returns(T.nilable(T::Array[T.any(Entry::Member, Entry::MethodAlias)]))
|
335
336
|
end
|
336
|
-
def resolve_method(method_name, receiver_name)
|
337
|
+
def resolve_method(method_name, receiver_name, inherited_only: false)
|
337
338
|
method_entries = self[method_name]
|
338
339
|
return unless method_entries
|
339
340
|
|
340
341
|
ancestors = linearized_ancestors_of(receiver_name.delete_prefix("::"))
|
341
342
|
ancestors.each do |ancestor|
|
343
|
+
next if inherited_only && ancestor == receiver_name
|
344
|
+
|
342
345
|
found = method_entries.filter_map do |entry|
|
343
346
|
case entry
|
344
347
|
when Entry::Member, Entry::MethodAlias
|
@@ -285,6 +285,43 @@ module RubyIndexer
|
|
285
285
|
assert_includes(second_entry.comments, "Hello from second `bar`")
|
286
286
|
end
|
287
287
|
|
288
|
+
def test_resolve_method_inherited_only
|
289
|
+
index(<<~RUBY)
|
290
|
+
class Bar
|
291
|
+
def baz; end
|
292
|
+
end
|
293
|
+
|
294
|
+
class Foo < Bar
|
295
|
+
def baz; end
|
296
|
+
end
|
297
|
+
RUBY
|
298
|
+
|
299
|
+
entry = T.must(@index.resolve_method("baz", "Foo", inherited_only: true).first)
|
300
|
+
|
301
|
+
assert_equal("Bar", T.must(entry.owner).name)
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_resolve_method_inherited_only_for_prepended_module
|
305
|
+
index(<<~RUBY)
|
306
|
+
module Bar
|
307
|
+
def baz
|
308
|
+
super
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
class Foo
|
313
|
+
prepend Bar
|
314
|
+
|
315
|
+
def baz; end
|
316
|
+
end
|
317
|
+
RUBY
|
318
|
+
|
319
|
+
# This test is just to document the fact that we don't yet support resolving inherited methods for modules that
|
320
|
+
# are prepended. The only way to support this is to find all namespaces that have the module a subtype, so that we
|
321
|
+
# can show the results for everywhere the module has been prepended.
|
322
|
+
assert_nil(@index.resolve_method("baz", "Bar", inherited_only: true))
|
323
|
+
end
|
324
|
+
|
288
325
|
def test_prefix_search_for_methods
|
289
326
|
index(<<~RUBY)
|
290
327
|
module Foo
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -127,8 +127,18 @@ module RubyLsp
|
|
127
127
|
parent = T.let(nil, T.nilable(Prism::Node))
|
128
128
|
nesting_nodes = T.let(
|
129
129
|
[],
|
130
|
-
T::Array[T.any(
|
130
|
+
T::Array[T.any(
|
131
|
+
Prism::ClassNode,
|
132
|
+
Prism::ModuleNode,
|
133
|
+
Prism::SingletonClassNode,
|
134
|
+
Prism::DefNode,
|
135
|
+
Prism::BlockNode,
|
136
|
+
Prism::LambdaNode,
|
137
|
+
Prism::ProgramNode,
|
138
|
+
)],
|
131
139
|
)
|
140
|
+
|
141
|
+
nesting_nodes << node if node.is_a?(Prism::ProgramNode)
|
132
142
|
call_node = T.let(nil, T.nilable(Prism::CallNode))
|
133
143
|
|
134
144
|
until queue.empty?
|
@@ -158,11 +168,8 @@ module RubyLsp
|
|
158
168
|
# Keep track of the nesting where we found the target. This is used to determine the fully qualified name of the
|
159
169
|
# target when it is a constant
|
160
170
|
case candidate
|
161
|
-
when Prism::ClassNode, Prism::ModuleNode
|
162
|
-
|
163
|
-
when Prism::SingletonClassNode
|
164
|
-
nesting_nodes << candidate
|
165
|
-
when Prism::DefNode
|
171
|
+
when Prism::ClassNode, Prism::ModuleNode, Prism::SingletonClassNode, Prism::DefNode, Prism::BlockNode,
|
172
|
+
Prism::LambdaNode
|
166
173
|
nesting_nodes << candidate
|
167
174
|
end
|
168
175
|
|
@@ -203,24 +210,7 @@ module RubyLsp
|
|
203
210
|
end
|
204
211
|
end
|
205
212
|
|
206
|
-
|
207
|
-
surrounding_method = T.let(nil, T.nilable(String))
|
208
|
-
|
209
|
-
nesting_nodes.each do |node|
|
210
|
-
case node
|
211
|
-
when Prism::ClassNode, Prism::ModuleNode
|
212
|
-
nesting << node.constant_path.slice
|
213
|
-
when Prism::SingletonClassNode
|
214
|
-
nesting << "<Class:#{nesting.last}>"
|
215
|
-
when Prism::DefNode
|
216
|
-
surrounding_method = node.name.to_s
|
217
|
-
next unless node.receiver.is_a?(Prism::SelfNode)
|
218
|
-
|
219
|
-
nesting << "<Class:#{nesting.last}>"
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
NodeContext.new(closest, parent, nesting, call_node, surrounding_method)
|
213
|
+
NodeContext.new(closest, parent, nesting_nodes, call_node)
|
224
214
|
end
|
225
215
|
|
226
216
|
sig { returns(T::Boolean) }
|
@@ -69,7 +69,7 @@ module RubyLsp
|
|
69
69
|
@formatter = detect_formatter(direct_dependencies, all_dependencies) if @formatter == "auto"
|
70
70
|
|
71
71
|
specified_linters = options.dig(:initializationOptions, :linters)
|
72
|
-
@linters = specified_linters || detect_linters(direct_dependencies)
|
72
|
+
@linters = specified_linters || detect_linters(direct_dependencies, all_dependencies)
|
73
73
|
@test_library = detect_test_library(direct_dependencies)
|
74
74
|
@has_type_checker = detect_typechecker(direct_dependencies)
|
75
75
|
|
@@ -127,10 +127,14 @@ module RubyLsp
|
|
127
127
|
|
128
128
|
# Try to detect if there are linters in the project's dependencies. For auto-detection, we always only consider a
|
129
129
|
# single linter. To have multiple linters running, the user must configure them manually
|
130
|
-
sig { params(dependencies: T::Array[String]).returns(T::Array[String]) }
|
131
|
-
def detect_linters(dependencies)
|
130
|
+
sig { params(dependencies: T::Array[String], all_dependencies: T::Array[String]).returns(T::Array[String]) }
|
131
|
+
def detect_linters(dependencies, all_dependencies)
|
132
132
|
linters = []
|
133
|
-
|
133
|
+
|
134
|
+
if dependencies.any?(/^rubocop/) || (all_dependencies.include?("rubocop") && dot_rubocop_yml_present)
|
135
|
+
linters << "rubocop"
|
136
|
+
end
|
137
|
+
|
134
138
|
linters
|
135
139
|
end
|
136
140
|
|
@@ -277,6 +277,8 @@ module RubyLsp
|
|
277
277
|
|
278
278
|
sig { params(node: Prism::CallNode, name: String).void }
|
279
279
|
def complete_methods(node, name)
|
280
|
+
add_local_completions(node, name)
|
281
|
+
|
280
282
|
type = @type_inferrer.infer_receiver_type(@node_context)
|
281
283
|
return unless type
|
282
284
|
|
@@ -322,6 +324,31 @@ module RubyLsp
|
|
322
324
|
# We have not indexed this namespace, so we can't provide any completions
|
323
325
|
end
|
324
326
|
|
327
|
+
sig { params(node: Prism::CallNode, name: String).void }
|
328
|
+
def add_local_completions(node, name)
|
329
|
+
return if @global_state.has_type_checker
|
330
|
+
|
331
|
+
# If the call node has a receiver, then it cannot possibly be a local variable
|
332
|
+
return if node.receiver
|
333
|
+
|
334
|
+
range = range_from_location(T.must(node.message_loc))
|
335
|
+
|
336
|
+
@node_context.locals_for_scope.each do |local|
|
337
|
+
local_name = local.to_s
|
338
|
+
next unless local_name.start_with?(name)
|
339
|
+
|
340
|
+
@response_builder << Interface::CompletionItem.new(
|
341
|
+
label: local_name,
|
342
|
+
filter_text: local_name,
|
343
|
+
text_edit: Interface::TextEdit.new(range: range, new_text: local_name),
|
344
|
+
kind: Constant::CompletionItemKind::VARIABLE,
|
345
|
+
data: {
|
346
|
+
skip_resolve: true,
|
347
|
+
},
|
348
|
+
)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
325
352
|
sig { params(label: String, node: Prism::StringNode).returns(Interface::CompletionItem) }
|
326
353
|
def build_completion(label, node)
|
327
354
|
# We should use the content location as we only replace the content and not the delimiters of the string
|
@@ -46,6 +46,8 @@ module RubyLsp
|
|
46
46
|
:on_instance_variable_or_write_node_enter,
|
47
47
|
:on_instance_variable_target_node_enter,
|
48
48
|
:on_string_node_enter,
|
49
|
+
:on_super_node_enter,
|
50
|
+
:on_forwarding_super_node_enter,
|
49
51
|
)
|
50
52
|
end
|
51
53
|
|
@@ -133,8 +135,30 @@ module RubyLsp
|
|
133
135
|
handle_instance_variable_definition(node.name.to_s)
|
134
136
|
end
|
135
137
|
|
138
|
+
sig { params(node: Prism::SuperNode).void }
|
139
|
+
def on_super_node_enter(node)
|
140
|
+
handle_super_node_definition
|
141
|
+
end
|
142
|
+
|
143
|
+
sig { params(node: Prism::ForwardingSuperNode).void }
|
144
|
+
def on_forwarding_super_node_enter(node)
|
145
|
+
handle_super_node_definition
|
146
|
+
end
|
147
|
+
|
136
148
|
private
|
137
149
|
|
150
|
+
sig { void }
|
151
|
+
def handle_super_node_definition
|
152
|
+
surrounding_method = @node_context.surrounding_method
|
153
|
+
return unless surrounding_method
|
154
|
+
|
155
|
+
handle_method_definition(
|
156
|
+
surrounding_method,
|
157
|
+
@type_inferrer.infer_receiver_type(@node_context),
|
158
|
+
inherited_only: true,
|
159
|
+
)
|
160
|
+
end
|
161
|
+
|
138
162
|
sig { params(name: String).void }
|
139
163
|
def handle_instance_variable_definition(name)
|
140
164
|
type = @type_inferrer.infer_receiver_type(@node_context)
|
@@ -158,10 +182,10 @@ module RubyLsp
|
|
158
182
|
# If by any chance we haven't indexed the owner, then there's no way to find the right declaration
|
159
183
|
end
|
160
184
|
|
161
|
-
sig { params(message: String, receiver_type: T.nilable(String)).void }
|
162
|
-
def handle_method_definition(message, receiver_type)
|
185
|
+
sig { params(message: String, receiver_type: T.nilable(String), inherited_only: T::Boolean).void }
|
186
|
+
def handle_method_definition(message, receiver_type, inherited_only: false)
|
163
187
|
methods = if receiver_type
|
164
|
-
@index.resolve_method(message, receiver_type)
|
188
|
+
@index.resolve_method(message, receiver_type, inherited_only: inherited_only)
|
165
189
|
else
|
166
190
|
# If the method doesn't have a receiver, then we provide a few candidates to jump to
|
167
191
|
# But we don't want to provide too many candidates, as it can be overwhelming
|
@@ -21,6 +21,8 @@ module RubyLsp
|
|
21
21
|
Prism::InstanceVariableWriteNode,
|
22
22
|
Prism::SymbolNode,
|
23
23
|
Prism::StringNode,
|
24
|
+
Prism::SuperNode,
|
25
|
+
Prism::ForwardingSuperNode,
|
24
26
|
],
|
25
27
|
T::Array[T.class_of(Prism::Node)],
|
26
28
|
)
|
@@ -64,6 +66,8 @@ module RubyLsp
|
|
64
66
|
:on_instance_variable_operator_write_node_enter,
|
65
67
|
:on_instance_variable_or_write_node_enter,
|
66
68
|
:on_instance_variable_target_node_enter,
|
69
|
+
:on_super_node_enter,
|
70
|
+
:on_forwarding_super_node_enter,
|
67
71
|
)
|
68
72
|
end
|
69
73
|
|
@@ -106,17 +110,7 @@ module RubyLsp
|
|
106
110
|
message = node.message
|
107
111
|
return unless message
|
108
112
|
|
109
|
-
|
110
|
-
return unless type
|
111
|
-
|
112
|
-
methods = @index.resolve_method(message, type)
|
113
|
-
return unless methods
|
114
|
-
|
115
|
-
title = "#{message}#{T.must(methods.first).decorated_parameters}"
|
116
|
-
|
117
|
-
categorized_markdown_from_index_entries(title, methods).each do |category, content|
|
118
|
-
@response_builder.push(content, category: category)
|
119
|
-
end
|
113
|
+
handle_method_hover(message)
|
120
114
|
end
|
121
115
|
|
122
116
|
sig { params(node: Prism::InstanceVariableReadNode).void }
|
@@ -149,8 +143,41 @@ module RubyLsp
|
|
149
143
|
handle_instance_variable_hover(node.name.to_s)
|
150
144
|
end
|
151
145
|
|
146
|
+
sig { params(node: Prism::SuperNode).void }
|
147
|
+
def on_super_node_enter(node)
|
148
|
+
handle_super_node_hover
|
149
|
+
end
|
150
|
+
|
151
|
+
sig { params(node: Prism::ForwardingSuperNode).void }
|
152
|
+
def on_forwarding_super_node_enter(node)
|
153
|
+
handle_super_node_hover
|
154
|
+
end
|
155
|
+
|
152
156
|
private
|
153
157
|
|
158
|
+
sig { void }
|
159
|
+
def handle_super_node_hover
|
160
|
+
surrounding_method = @node_context.surrounding_method
|
161
|
+
return unless surrounding_method
|
162
|
+
|
163
|
+
handle_method_hover(surrounding_method, inherited_only: true)
|
164
|
+
end
|
165
|
+
|
166
|
+
sig { params(message: String, inherited_only: T::Boolean).void }
|
167
|
+
def handle_method_hover(message, inherited_only: false)
|
168
|
+
type = @type_inferrer.infer_receiver_type(@node_context)
|
169
|
+
return unless type
|
170
|
+
|
171
|
+
methods = @index.resolve_method(message, type, inherited_only: inherited_only)
|
172
|
+
return unless methods
|
173
|
+
|
174
|
+
title = "#{message}#{T.must(methods.first).decorated_parameters}"
|
175
|
+
|
176
|
+
categorized_markdown_from_index_entries(title, methods).each do |category, content|
|
177
|
+
@response_builder.push(content, category: category)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
154
181
|
sig { params(name: String).void }
|
155
182
|
def handle_instance_variable_hover(name)
|
156
183
|
type = @type_inferrer.infer_receiver_type(@node_context)
|
@@ -23,22 +23,82 @@ module RubyLsp
|
|
23
23
|
params(
|
24
24
|
node: T.nilable(Prism::Node),
|
25
25
|
parent: T.nilable(Prism::Node),
|
26
|
-
|
26
|
+
nesting_nodes: T::Array[T.any(
|
27
|
+
Prism::ClassNode,
|
28
|
+
Prism::ModuleNode,
|
29
|
+
Prism::SingletonClassNode,
|
30
|
+
Prism::DefNode,
|
31
|
+
Prism::BlockNode,
|
32
|
+
Prism::LambdaNode,
|
33
|
+
Prism::ProgramNode,
|
34
|
+
)],
|
27
35
|
call_node: T.nilable(Prism::CallNode),
|
28
|
-
surrounding_method: T.nilable(String),
|
29
36
|
).void
|
30
37
|
end
|
31
|
-
def initialize(node, parent,
|
38
|
+
def initialize(node, parent, nesting_nodes, call_node)
|
32
39
|
@node = node
|
33
40
|
@parent = parent
|
34
|
-
@
|
41
|
+
@nesting_nodes = nesting_nodes
|
35
42
|
@call_node = call_node
|
36
|
-
|
43
|
+
|
44
|
+
nesting, surrounding_method = handle_nesting_nodes(nesting_nodes)
|
45
|
+
@nesting = T.let(nesting, T::Array[String])
|
46
|
+
@surrounding_method = T.let(surrounding_method, T.nilable(String))
|
37
47
|
end
|
38
48
|
|
39
49
|
sig { returns(String) }
|
40
50
|
def fully_qualified_name
|
41
51
|
@fully_qualified_name ||= T.let(@nesting.join("::"), T.nilable(String))
|
42
52
|
end
|
53
|
+
|
54
|
+
sig { returns(T::Array[Symbol]) }
|
55
|
+
def locals_for_scope
|
56
|
+
locals = []
|
57
|
+
|
58
|
+
@nesting_nodes.each do |node|
|
59
|
+
if node.is_a?(Prism::ClassNode) || node.is_a?(Prism::ModuleNode) || node.is_a?(Prism::SingletonClassNode) ||
|
60
|
+
node.is_a?(Prism::DefNode)
|
61
|
+
locals.clear
|
62
|
+
end
|
63
|
+
|
64
|
+
locals.concat(node.locals)
|
65
|
+
end
|
66
|
+
|
67
|
+
locals
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
sig do
|
73
|
+
params(nodes: T::Array[T.any(
|
74
|
+
Prism::ClassNode,
|
75
|
+
Prism::ModuleNode,
|
76
|
+
Prism::SingletonClassNode,
|
77
|
+
Prism::DefNode,
|
78
|
+
Prism::BlockNode,
|
79
|
+
Prism::LambdaNode,
|
80
|
+
Prism::ProgramNode,
|
81
|
+
)]).returns([T::Array[String], T.nilable(String)])
|
82
|
+
end
|
83
|
+
def handle_nesting_nodes(nodes)
|
84
|
+
nesting = []
|
85
|
+
surrounding_method = T.let(nil, T.nilable(String))
|
86
|
+
|
87
|
+
@nesting_nodes.each do |node|
|
88
|
+
case node
|
89
|
+
when Prism::ClassNode, Prism::ModuleNode
|
90
|
+
nesting << node.constant_path.slice
|
91
|
+
when Prism::SingletonClassNode
|
92
|
+
nesting << "<Class:#{nesting.last}>"
|
93
|
+
when Prism::DefNode
|
94
|
+
surrounding_method = node.name.to_s
|
95
|
+
next unless node.receiver.is_a?(Prism::SelfNode)
|
96
|
+
|
97
|
+
nesting << "<Class:#{nesting.last}>"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
[nesting, surrounding_method]
|
102
|
+
end
|
43
103
|
end
|
44
104
|
end
|
@@ -38,6 +38,8 @@ module RubyLsp
|
|
38
38
|
|
39
39
|
sig { override.returns(T::Hash[Symbol, T.untyped]) }
|
40
40
|
def perform
|
41
|
+
return @item if @item.dig(:data, :skip_resolve)
|
42
|
+
|
41
43
|
# Based on the spec https://microsoft.github.io/language-server-protocol/specification#textDocument_completion,
|
42
44
|
# a completion resolve request must always return the original completion item without modifying ANY fields
|
43
45
|
# other than detail and documentation (NOT labelDetails). If we modify anything, the completion behaviour might
|
@@ -20,16 +20,9 @@ module RubyLsp
|
|
20
20
|
when Prism::CallNode
|
21
21
|
infer_receiver_for_call_node(node, node_context)
|
22
22
|
when Prism::InstanceVariableReadNode, Prism::InstanceVariableAndWriteNode, Prism::InstanceVariableWriteNode,
|
23
|
-
Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode, Prism::InstanceVariableTargetNode
|
24
|
-
|
25
|
-
|
26
|
-
# inherits from Object
|
27
|
-
return "Object" if nesting.empty?
|
28
|
-
|
29
|
-
fully_qualified_name = node_context.fully_qualified_name
|
30
|
-
return fully_qualified_name if node_context.surrounding_method
|
31
|
-
|
32
|
-
"#{fully_qualified_name}::<Class:#{nesting.last}>"
|
23
|
+
Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode, Prism::InstanceVariableTargetNode,
|
24
|
+
Prism::SuperNode, Prism::ForwardingSuperNode
|
25
|
+
self_receiver_handling(node_context)
|
33
26
|
end
|
34
27
|
end
|
35
28
|
|
@@ -41,15 +34,7 @@ module RubyLsp
|
|
41
34
|
|
42
35
|
case receiver
|
43
36
|
when Prism::SelfNode, nil
|
44
|
-
|
45
|
-
# If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
|
46
|
-
# inherits from Object
|
47
|
-
return "Object" if nesting.empty?
|
48
|
-
return node_context.fully_qualified_name if node_context.surrounding_method
|
49
|
-
|
50
|
-
# If we're not inside a method, then we're inside the body of a class or module, which is a singleton
|
51
|
-
# context
|
52
|
-
"#{nesting.join("::")}::<Class:#{nesting.last}>"
|
37
|
+
self_receiver_handling(node_context)
|
53
38
|
when Prism::ConstantPathNode, Prism::ConstantReadNode
|
54
39
|
# When the receiver is a constant reference, we have to try to resolve it to figure out the right
|
55
40
|
# receiver. But since the invocation is directly on the constant, that's the singleton context of that
|
@@ -68,6 +53,19 @@ module RubyLsp
|
|
68
53
|
end
|
69
54
|
end
|
70
55
|
|
56
|
+
sig { params(node_context: NodeContext).returns(String) }
|
57
|
+
def self_receiver_handling(node_context)
|
58
|
+
nesting = node_context.nesting
|
59
|
+
# If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
|
60
|
+
# inherits from Object
|
61
|
+
return "Object" if nesting.empty?
|
62
|
+
return node_context.fully_qualified_name if node_context.surrounding_method
|
63
|
+
|
64
|
+
# If we're not inside a method, then we're inside the body of a class or module, which is a singleton
|
65
|
+
# context
|
66
|
+
"#{nesting.join("::")}::<Class:#{nesting.last}>"
|
67
|
+
end
|
68
|
+
|
71
69
|
sig do
|
72
70
|
params(
|
73
71
|
node: T.any(
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.17.
|
4
|
+
version: 0.17.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|