ruby-lsp 0.27.0.beta1 → 0.27.0.beta3
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 +0 -46
- data/exe/ruby-lsp-check +0 -15
- data/lib/ruby_lsp/addon.rb +19 -19
- data/lib/ruby_lsp/global_state.rb +1 -6
- data/lib/ruby_lsp/internal.rb +3 -2
- data/lib/ruby_lsp/listeners/code_lens.rb +1 -1
- data/lib/ruby_lsp/listeners/completion.rb +246 -382
- data/lib/ruby_lsp/listeners/definition.rb +7 -10
- data/lib/ruby_lsp/listeners/document_link.rb +4 -0
- data/lib/ruby_lsp/listeners/hover.rb +234 -82
- data/lib/ruby_lsp/listeners/signature_help.rb +11 -12
- data/lib/ruby_lsp/listeners/spec_style.rb +6 -1
- data/lib/ruby_lsp/listeners/test_discovery.rb +38 -15
- data/lib/ruby_lsp/listeners/test_style.rb +21 -9
- data/lib/ruby_lsp/node_context.rb +31 -8
- data/lib/ruby_lsp/requests/completion_resolve.rb +55 -39
- data/lib/ruby_lsp/requests/discover_tests.rb +5 -41
- data/lib/ruby_lsp/requests/hover.rb +2 -5
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +66 -22
- data/lib/ruby_lsp/requests/references.rb +180 -66
- data/lib/ruby_lsp/requests/rename.rb +1 -1
- data/lib/ruby_lsp/requests/request.rb +3 -33
- data/lib/ruby_lsp/requests/support/common.rb +82 -68
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +82 -46
- data/lib/ruby_lsp/ruby_document.rb +0 -73
- data/lib/ruby_lsp/rubydex/declaration.rb +174 -0
- data/lib/ruby_lsp/rubydex/definition.rb +73 -0
- data/lib/ruby_lsp/rubydex/reference.rb +6 -1
- data/lib/ruby_lsp/rubydex/signature.rb +107 -0
- data/lib/ruby_lsp/scripts/compose_bundle.rb +1 -1
- data/lib/ruby_lsp/server.rb +56 -171
- data/lib/ruby_lsp/test_helper.rb +0 -1
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +1 -1
- data/lib/ruby_lsp/type_inferrer.rb +89 -11
- metadata +12 -18
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +0 -276
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +0 -1101
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +0 -44
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +0 -605
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +0 -1077
- data/lib/ruby_indexer/lib/ruby_indexer/location.rb +0 -37
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +0 -149
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +0 -294
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +0 -335
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +0 -32
- data/lib/ruby_indexer/ruby_indexer.rb +0 -20
- data/lib/ruby_lsp/static_docs.rb +0 -20
- data/static_docs/break.md +0 -103
- data/static_docs/yield.md +0 -81
- /data/lib/{ruby_indexer/lib/ruby_indexer → ruby_lsp}/uri.rb +0 -0
|
@@ -1,1101 +0,0 @@
|
|
|
1
|
-
# typed: strict
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
module RubyIndexer
|
|
5
|
-
class DeclarationListener
|
|
6
|
-
OBJECT_NESTING = ["Object"].freeze #: Array[String]
|
|
7
|
-
BASIC_OBJECT_NESTING = ["BasicObject"].freeze #: Array[String]
|
|
8
|
-
|
|
9
|
-
#: Array[String]
|
|
10
|
-
attr_reader :indexing_errors
|
|
11
|
-
|
|
12
|
-
#: (Index index, Prism::Dispatcher dispatcher, Prism::ParseLexResult | Prism::ParseResult parse_result, URI::Generic uri, ?collect_comments: bool) -> void
|
|
13
|
-
def initialize(index, dispatcher, parse_result, uri, collect_comments: false)
|
|
14
|
-
@index = index
|
|
15
|
-
@uri = uri
|
|
16
|
-
@enhancements = Enhancement.all(self) #: Array[Enhancement]
|
|
17
|
-
@visibility_stack = [VisibilityScope.public_scope] #: Array[VisibilityScope]
|
|
18
|
-
@comments_by_line = parse_result.comments.to_h do |c|
|
|
19
|
-
[c.location.start_line, c]
|
|
20
|
-
end #: Hash[Integer, Prism::Comment]
|
|
21
|
-
@inside_def = false #: bool
|
|
22
|
-
@code_units_cache = parse_result
|
|
23
|
-
.code_units_cache(@index.configuration.encoding) #: (^(Integer arg0) -> Integer | Prism::CodeUnitsCache)
|
|
24
|
-
|
|
25
|
-
@source_lines = parse_result.source.lines #: Array[String]
|
|
26
|
-
|
|
27
|
-
# The nesting stack we're currently inside. Used to determine the fully qualified name of constants, but only
|
|
28
|
-
# stored by unresolved aliases which need the original nesting to be lazily resolved
|
|
29
|
-
@stack = [] #: Array[String]
|
|
30
|
-
|
|
31
|
-
# A stack of namespace entries that represent where we currently are. Used to properly assign methods to an owner
|
|
32
|
-
@owner_stack = [] #: Array[Entry::Namespace]
|
|
33
|
-
@indexing_errors = [] #: Array[String]
|
|
34
|
-
@collect_comments = collect_comments
|
|
35
|
-
|
|
36
|
-
dispatcher.register(
|
|
37
|
-
self,
|
|
38
|
-
:on_class_node_enter,
|
|
39
|
-
:on_class_node_leave,
|
|
40
|
-
:on_module_node_enter,
|
|
41
|
-
:on_module_node_leave,
|
|
42
|
-
:on_singleton_class_node_enter,
|
|
43
|
-
:on_singleton_class_node_leave,
|
|
44
|
-
:on_def_node_enter,
|
|
45
|
-
:on_def_node_leave,
|
|
46
|
-
:on_call_node_enter,
|
|
47
|
-
:on_call_node_leave,
|
|
48
|
-
:on_multi_write_node_enter,
|
|
49
|
-
:on_constant_path_write_node_enter,
|
|
50
|
-
:on_constant_path_or_write_node_enter,
|
|
51
|
-
:on_constant_path_operator_write_node_enter,
|
|
52
|
-
:on_constant_path_and_write_node_enter,
|
|
53
|
-
:on_constant_write_node_enter,
|
|
54
|
-
:on_constant_or_write_node_enter,
|
|
55
|
-
:on_constant_and_write_node_enter,
|
|
56
|
-
:on_constant_operator_write_node_enter,
|
|
57
|
-
:on_global_variable_and_write_node_enter,
|
|
58
|
-
:on_global_variable_operator_write_node_enter,
|
|
59
|
-
:on_global_variable_or_write_node_enter,
|
|
60
|
-
:on_global_variable_target_node_enter,
|
|
61
|
-
:on_global_variable_write_node_enter,
|
|
62
|
-
:on_instance_variable_write_node_enter,
|
|
63
|
-
:on_instance_variable_and_write_node_enter,
|
|
64
|
-
:on_instance_variable_operator_write_node_enter,
|
|
65
|
-
:on_instance_variable_or_write_node_enter,
|
|
66
|
-
:on_instance_variable_target_node_enter,
|
|
67
|
-
:on_alias_method_node_enter,
|
|
68
|
-
:on_class_variable_and_write_node_enter,
|
|
69
|
-
:on_class_variable_operator_write_node_enter,
|
|
70
|
-
:on_class_variable_or_write_node_enter,
|
|
71
|
-
:on_class_variable_target_node_enter,
|
|
72
|
-
:on_class_variable_write_node_enter,
|
|
73
|
-
)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
#: (Prism::ClassNode node) -> void
|
|
77
|
-
def on_class_node_enter(node)
|
|
78
|
-
constant_path = node.constant_path
|
|
79
|
-
superclass = node.superclass
|
|
80
|
-
nesting = Index.actual_nesting(@stack, constant_path.slice)
|
|
81
|
-
|
|
82
|
-
parent_class = case superclass
|
|
83
|
-
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
|
84
|
-
superclass.slice
|
|
85
|
-
else
|
|
86
|
-
case nesting
|
|
87
|
-
when OBJECT_NESTING
|
|
88
|
-
# When Object is reopened, its parent class should still be the top-level BasicObject
|
|
89
|
-
"::BasicObject"
|
|
90
|
-
when BASIC_OBJECT_NESTING
|
|
91
|
-
# When BasicObject is reopened, its parent class should still be nil
|
|
92
|
-
nil
|
|
93
|
-
else
|
|
94
|
-
# Otherwise, the parent class should be the top-level Object
|
|
95
|
-
"::Object"
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
add_class(
|
|
100
|
-
nesting,
|
|
101
|
-
node.location,
|
|
102
|
-
constant_path.location,
|
|
103
|
-
parent_class_name: parent_class,
|
|
104
|
-
comments: collect_comments(node),
|
|
105
|
-
)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
#: (Prism::ClassNode node) -> void
|
|
109
|
-
def on_class_node_leave(node)
|
|
110
|
-
pop_namespace_stack
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
#: (Prism::ModuleNode node) -> void
|
|
114
|
-
def on_module_node_enter(node)
|
|
115
|
-
constant_path = node.constant_path
|
|
116
|
-
add_module(constant_path.slice, node.location, constant_path.location, comments: collect_comments(node))
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
#: (Prism::ModuleNode node) -> void
|
|
120
|
-
def on_module_node_leave(node)
|
|
121
|
-
pop_namespace_stack
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
#: (Prism::SingletonClassNode node) -> void
|
|
125
|
-
def on_singleton_class_node_enter(node)
|
|
126
|
-
@visibility_stack.push(VisibilityScope.public_scope)
|
|
127
|
-
|
|
128
|
-
current_owner = @owner_stack.last
|
|
129
|
-
|
|
130
|
-
if current_owner
|
|
131
|
-
expression = node.expression
|
|
132
|
-
name = (expression.is_a?(Prism::SelfNode) ? "<#{last_name_in_stack}>" : "<#{expression.slice}>")
|
|
133
|
-
real_nesting = Index.actual_nesting(@stack, name)
|
|
134
|
-
|
|
135
|
-
existing_entries = @index[real_nesting.join("::")] #: as Array[Entry::SingletonClass]?
|
|
136
|
-
|
|
137
|
-
if existing_entries
|
|
138
|
-
entry = existing_entries.first #: as !nil
|
|
139
|
-
entry.update_singleton_information(
|
|
140
|
-
Location.from_prism_location(node.location, @code_units_cache),
|
|
141
|
-
Location.from_prism_location(expression.location, @code_units_cache),
|
|
142
|
-
collect_comments(node),
|
|
143
|
-
)
|
|
144
|
-
else
|
|
145
|
-
entry = Entry::SingletonClass.new(
|
|
146
|
-
@index.configuration,
|
|
147
|
-
real_nesting,
|
|
148
|
-
@uri,
|
|
149
|
-
Location.from_prism_location(node.location, @code_units_cache),
|
|
150
|
-
Location.from_prism_location(expression.location, @code_units_cache),
|
|
151
|
-
collect_comments(node),
|
|
152
|
-
nil,
|
|
153
|
-
)
|
|
154
|
-
@index.add(entry, skip_prefix_tree: true)
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
@owner_stack << entry
|
|
158
|
-
@stack << name
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
#: (Prism::SingletonClassNode node) -> void
|
|
163
|
-
def on_singleton_class_node_leave(node)
|
|
164
|
-
pop_namespace_stack
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
#: (Prism::MultiWriteNode node) -> void
|
|
168
|
-
def on_multi_write_node_enter(node)
|
|
169
|
-
value = node.value
|
|
170
|
-
values = value.is_a?(Prism::ArrayNode) && value.opening_loc ? value.elements : []
|
|
171
|
-
|
|
172
|
-
[*node.lefts, *node.rest, *node.rights].each_with_index do |target, i|
|
|
173
|
-
current_value = values[i]
|
|
174
|
-
# The moment we find a splat on the right hand side of the assignment, we can no longer figure out which value
|
|
175
|
-
# gets assigned to what
|
|
176
|
-
values.clear if current_value.is_a?(Prism::SplatNode)
|
|
177
|
-
|
|
178
|
-
case target
|
|
179
|
-
when Prism::ConstantTargetNode
|
|
180
|
-
add_constant(target, fully_qualify_name(target.name.to_s), current_value)
|
|
181
|
-
when Prism::ConstantPathTargetNode
|
|
182
|
-
add_constant(target, fully_qualify_name(target.slice), current_value)
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
#: (Prism::ConstantPathWriteNode node) -> void
|
|
188
|
-
def on_constant_path_write_node_enter(node)
|
|
189
|
-
# ignore variable constants like `var::FOO` or `self.class::FOO`
|
|
190
|
-
target = node.target
|
|
191
|
-
return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
|
|
192
|
-
|
|
193
|
-
name = fully_qualify_name(target.location.slice)
|
|
194
|
-
add_constant(node, name)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
#: (Prism::ConstantPathOrWriteNode node) -> void
|
|
198
|
-
def on_constant_path_or_write_node_enter(node)
|
|
199
|
-
# ignore variable constants like `var::FOO` or `self.class::FOO`
|
|
200
|
-
target = node.target
|
|
201
|
-
return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
|
|
202
|
-
|
|
203
|
-
name = fully_qualify_name(target.location.slice)
|
|
204
|
-
add_constant(node, name)
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
#: (Prism::ConstantPathOperatorWriteNode node) -> void
|
|
208
|
-
def on_constant_path_operator_write_node_enter(node)
|
|
209
|
-
# ignore variable constants like `var::FOO` or `self.class::FOO`
|
|
210
|
-
target = node.target
|
|
211
|
-
return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
|
|
212
|
-
|
|
213
|
-
name = fully_qualify_name(target.location.slice)
|
|
214
|
-
add_constant(node, name)
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
#: (Prism::ConstantPathAndWriteNode node) -> void
|
|
218
|
-
def on_constant_path_and_write_node_enter(node)
|
|
219
|
-
# ignore variable constants like `var::FOO` or `self.class::FOO`
|
|
220
|
-
target = node.target
|
|
221
|
-
return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
|
|
222
|
-
|
|
223
|
-
name = fully_qualify_name(target.location.slice)
|
|
224
|
-
add_constant(node, name)
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
#: (Prism::ConstantWriteNode node) -> void
|
|
228
|
-
def on_constant_write_node_enter(node)
|
|
229
|
-
name = fully_qualify_name(node.name.to_s)
|
|
230
|
-
add_constant(node, name)
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
#: (Prism::ConstantOrWriteNode node) -> void
|
|
234
|
-
def on_constant_or_write_node_enter(node)
|
|
235
|
-
name = fully_qualify_name(node.name.to_s)
|
|
236
|
-
add_constant(node, name)
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
#: (Prism::ConstantAndWriteNode node) -> void
|
|
240
|
-
def on_constant_and_write_node_enter(node)
|
|
241
|
-
name = fully_qualify_name(node.name.to_s)
|
|
242
|
-
add_constant(node, name)
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
#: (Prism::ConstantOperatorWriteNode node) -> void
|
|
246
|
-
def on_constant_operator_write_node_enter(node)
|
|
247
|
-
name = fully_qualify_name(node.name.to_s)
|
|
248
|
-
add_constant(node, name)
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
#: (Prism::CallNode node) -> void
|
|
252
|
-
def on_call_node_enter(node)
|
|
253
|
-
message = node.name
|
|
254
|
-
|
|
255
|
-
case message
|
|
256
|
-
when :private_constant
|
|
257
|
-
handle_private_constant(node)
|
|
258
|
-
when :attr_reader
|
|
259
|
-
handle_attribute(node, reader: true, writer: false)
|
|
260
|
-
when :attr_writer
|
|
261
|
-
handle_attribute(node, reader: false, writer: true)
|
|
262
|
-
when :attr_accessor
|
|
263
|
-
handle_attribute(node, reader: true, writer: true)
|
|
264
|
-
when :attr
|
|
265
|
-
has_writer = node.arguments&.arguments&.last&.is_a?(Prism::TrueNode) || false
|
|
266
|
-
handle_attribute(node, reader: true, writer: has_writer)
|
|
267
|
-
when :alias_method
|
|
268
|
-
handle_alias_method(node)
|
|
269
|
-
when :include, :prepend, :extend
|
|
270
|
-
handle_module_operation(node, message)
|
|
271
|
-
when :public
|
|
272
|
-
handle_visibility_change(node, :public)
|
|
273
|
-
when :protected
|
|
274
|
-
handle_visibility_change(node, :protected)
|
|
275
|
-
when :private
|
|
276
|
-
handle_visibility_change(node, :private)
|
|
277
|
-
when :module_function
|
|
278
|
-
handle_module_function(node)
|
|
279
|
-
when :private_class_method
|
|
280
|
-
handle_private_class_method(node)
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
@enhancements.each do |enhancement|
|
|
284
|
-
enhancement.on_call_node_enter(node)
|
|
285
|
-
rescue StandardError => e
|
|
286
|
-
@indexing_errors << <<~MSG
|
|
287
|
-
Indexing error in #{@uri} with '#{enhancement.class.name}' on call node enter enhancement: #{e.message}
|
|
288
|
-
MSG
|
|
289
|
-
end
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
#: (Prism::CallNode node) -> void
|
|
293
|
-
def on_call_node_leave(node)
|
|
294
|
-
message = node.name
|
|
295
|
-
case message
|
|
296
|
-
when :public, :protected, :private, :private_class_method
|
|
297
|
-
# We want to restore the visibility stack when we leave a method definition with a visibility modifier
|
|
298
|
-
# e.g. `private def foo; end`
|
|
299
|
-
if node.arguments&.arguments&.first&.is_a?(Prism::DefNode)
|
|
300
|
-
@visibility_stack.pop
|
|
301
|
-
end
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
@enhancements.each do |enhancement|
|
|
305
|
-
enhancement.on_call_node_leave(node)
|
|
306
|
-
rescue StandardError => e
|
|
307
|
-
@indexing_errors << <<~MSG
|
|
308
|
-
Indexing error in #{@uri} with '#{enhancement.class.name}' on call node leave enhancement: #{e.message}
|
|
309
|
-
MSG
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
#: (Prism::DefNode node) -> void
|
|
314
|
-
def on_def_node_enter(node)
|
|
315
|
-
owner = @owner_stack.last
|
|
316
|
-
return unless owner
|
|
317
|
-
|
|
318
|
-
@inside_def = true
|
|
319
|
-
method_name = node.name.to_s
|
|
320
|
-
comments = collect_comments(node)
|
|
321
|
-
scope = current_visibility_scope
|
|
322
|
-
|
|
323
|
-
case node.receiver
|
|
324
|
-
when nil
|
|
325
|
-
location = Location.from_prism_location(node.location, @code_units_cache)
|
|
326
|
-
name_location = Location.from_prism_location(node.name_loc, @code_units_cache)
|
|
327
|
-
signatures = [Entry::Signature.new(list_params(node.parameters))]
|
|
328
|
-
|
|
329
|
-
@index.add(Entry::Method.new(
|
|
330
|
-
@index.configuration,
|
|
331
|
-
method_name,
|
|
332
|
-
@uri,
|
|
333
|
-
location,
|
|
334
|
-
name_location,
|
|
335
|
-
comments,
|
|
336
|
-
signatures,
|
|
337
|
-
scope.visibility,
|
|
338
|
-
owner,
|
|
339
|
-
))
|
|
340
|
-
|
|
341
|
-
if scope.module_func
|
|
342
|
-
singleton = @index.existing_or_new_singleton_class(owner.name)
|
|
343
|
-
|
|
344
|
-
@index.add(Entry::Method.new(
|
|
345
|
-
@index.configuration,
|
|
346
|
-
method_name,
|
|
347
|
-
@uri,
|
|
348
|
-
location,
|
|
349
|
-
name_location,
|
|
350
|
-
comments,
|
|
351
|
-
signatures,
|
|
352
|
-
:public,
|
|
353
|
-
singleton,
|
|
354
|
-
))
|
|
355
|
-
end
|
|
356
|
-
when Prism::SelfNode
|
|
357
|
-
singleton = @index.existing_or_new_singleton_class(owner.name)
|
|
358
|
-
|
|
359
|
-
@index.add(Entry::Method.new(
|
|
360
|
-
@index.configuration,
|
|
361
|
-
method_name,
|
|
362
|
-
@uri,
|
|
363
|
-
Location.from_prism_location(node.location, @code_units_cache),
|
|
364
|
-
Location.from_prism_location(node.name_loc, @code_units_cache),
|
|
365
|
-
comments,
|
|
366
|
-
[Entry::Signature.new(list_params(node.parameters))],
|
|
367
|
-
scope.visibility,
|
|
368
|
-
singleton,
|
|
369
|
-
))
|
|
370
|
-
|
|
371
|
-
@owner_stack << singleton
|
|
372
|
-
end
|
|
373
|
-
end
|
|
374
|
-
|
|
375
|
-
#: (Prism::DefNode node) -> void
|
|
376
|
-
def on_def_node_leave(node)
|
|
377
|
-
@inside_def = false
|
|
378
|
-
|
|
379
|
-
if node.receiver.is_a?(Prism::SelfNode)
|
|
380
|
-
@owner_stack.pop
|
|
381
|
-
end
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
#: (Prism::GlobalVariableAndWriteNode node) -> void
|
|
385
|
-
def on_global_variable_and_write_node_enter(node)
|
|
386
|
-
handle_global_variable(node, node.name_loc)
|
|
387
|
-
end
|
|
388
|
-
|
|
389
|
-
#: (Prism::GlobalVariableOperatorWriteNode node) -> void
|
|
390
|
-
def on_global_variable_operator_write_node_enter(node)
|
|
391
|
-
handle_global_variable(node, node.name_loc)
|
|
392
|
-
end
|
|
393
|
-
|
|
394
|
-
#: (Prism::GlobalVariableOrWriteNode node) -> void
|
|
395
|
-
def on_global_variable_or_write_node_enter(node)
|
|
396
|
-
handle_global_variable(node, node.name_loc)
|
|
397
|
-
end
|
|
398
|
-
|
|
399
|
-
#: (Prism::GlobalVariableTargetNode node) -> void
|
|
400
|
-
def on_global_variable_target_node_enter(node)
|
|
401
|
-
handle_global_variable(node, node.location)
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
#: (Prism::GlobalVariableWriteNode node) -> void
|
|
405
|
-
def on_global_variable_write_node_enter(node)
|
|
406
|
-
handle_global_variable(node, node.name_loc)
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
#: (Prism::InstanceVariableWriteNode node) -> void
|
|
410
|
-
def on_instance_variable_write_node_enter(node)
|
|
411
|
-
handle_instance_variable(node, node.name_loc)
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
#: (Prism::InstanceVariableAndWriteNode node) -> void
|
|
415
|
-
def on_instance_variable_and_write_node_enter(node)
|
|
416
|
-
handle_instance_variable(node, node.name_loc)
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
#: (Prism::InstanceVariableOperatorWriteNode node) -> void
|
|
420
|
-
def on_instance_variable_operator_write_node_enter(node)
|
|
421
|
-
handle_instance_variable(node, node.name_loc)
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
#: (Prism::InstanceVariableOrWriteNode node) -> void
|
|
425
|
-
def on_instance_variable_or_write_node_enter(node)
|
|
426
|
-
handle_instance_variable(node, node.name_loc)
|
|
427
|
-
end
|
|
428
|
-
|
|
429
|
-
#: (Prism::InstanceVariableTargetNode node) -> void
|
|
430
|
-
def on_instance_variable_target_node_enter(node)
|
|
431
|
-
handle_instance_variable(node, node.location)
|
|
432
|
-
end
|
|
433
|
-
|
|
434
|
-
#: (Prism::AliasMethodNode node) -> void
|
|
435
|
-
def on_alias_method_node_enter(node)
|
|
436
|
-
method_name = node.new_name.slice
|
|
437
|
-
comments = collect_comments(node)
|
|
438
|
-
@index.add(
|
|
439
|
-
Entry::UnresolvedMethodAlias.new(
|
|
440
|
-
@index.configuration,
|
|
441
|
-
method_name,
|
|
442
|
-
node.old_name.slice,
|
|
443
|
-
@owner_stack.last,
|
|
444
|
-
@uri,
|
|
445
|
-
Location.from_prism_location(node.new_name.location, @code_units_cache),
|
|
446
|
-
comments,
|
|
447
|
-
),
|
|
448
|
-
)
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
#: (Prism::ClassVariableAndWriteNode node) -> void
|
|
452
|
-
def on_class_variable_and_write_node_enter(node)
|
|
453
|
-
handle_class_variable(node, node.name_loc)
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
#: (Prism::ClassVariableOperatorWriteNode node) -> void
|
|
457
|
-
def on_class_variable_operator_write_node_enter(node)
|
|
458
|
-
handle_class_variable(node, node.name_loc)
|
|
459
|
-
end
|
|
460
|
-
|
|
461
|
-
#: (Prism::ClassVariableOrWriteNode node) -> void
|
|
462
|
-
def on_class_variable_or_write_node_enter(node)
|
|
463
|
-
handle_class_variable(node, node.name_loc)
|
|
464
|
-
end
|
|
465
|
-
|
|
466
|
-
#: (Prism::ClassVariableTargetNode node) -> void
|
|
467
|
-
def on_class_variable_target_node_enter(node)
|
|
468
|
-
handle_class_variable(node, node.location)
|
|
469
|
-
end
|
|
470
|
-
|
|
471
|
-
#: (Prism::ClassVariableWriteNode node) -> void
|
|
472
|
-
def on_class_variable_write_node_enter(node)
|
|
473
|
-
handle_class_variable(node, node.name_loc)
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
#: (String name, Prism::Location node_location, Array[Entry::Signature] signatures, ?visibility: Symbol, ?comments: String?) -> void
|
|
477
|
-
def add_method(name, node_location, signatures, visibility: :public, comments: nil)
|
|
478
|
-
location = Location.from_prism_location(node_location, @code_units_cache)
|
|
479
|
-
|
|
480
|
-
@index.add(Entry::Method.new(
|
|
481
|
-
@index.configuration,
|
|
482
|
-
name,
|
|
483
|
-
@uri,
|
|
484
|
-
location,
|
|
485
|
-
location,
|
|
486
|
-
comments,
|
|
487
|
-
signatures,
|
|
488
|
-
visibility,
|
|
489
|
-
@owner_stack.last,
|
|
490
|
-
))
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
#: (String name, Prism::Location full_location, Prism::Location name_location, ?comments: String?) -> void
|
|
494
|
-
def add_module(name, full_location, name_location, comments: nil)
|
|
495
|
-
location = Location.from_prism_location(full_location, @code_units_cache)
|
|
496
|
-
name_loc = Location.from_prism_location(name_location, @code_units_cache)
|
|
497
|
-
|
|
498
|
-
entry = Entry::Module.new(
|
|
499
|
-
@index.configuration,
|
|
500
|
-
Index.actual_nesting(@stack, name),
|
|
501
|
-
@uri,
|
|
502
|
-
location,
|
|
503
|
-
name_loc,
|
|
504
|
-
comments,
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
advance_namespace_stack(name, entry)
|
|
508
|
-
end
|
|
509
|
-
|
|
510
|
-
#: ((String | Array[String]) name_or_nesting, Prism::Location full_location, Prism::Location name_location, ?parent_class_name: String?, ?comments: String?) -> void
|
|
511
|
-
def add_class(name_or_nesting, full_location, name_location, parent_class_name: nil, comments: nil)
|
|
512
|
-
nesting = name_or_nesting.is_a?(Array) ? name_or_nesting : Index.actual_nesting(@stack, name_or_nesting)
|
|
513
|
-
entry = Entry::Class.new(
|
|
514
|
-
@index.configuration,
|
|
515
|
-
nesting,
|
|
516
|
-
@uri,
|
|
517
|
-
Location.from_prism_location(full_location, @code_units_cache),
|
|
518
|
-
Location.from_prism_location(name_location, @code_units_cache),
|
|
519
|
-
comments,
|
|
520
|
-
parent_class_name,
|
|
521
|
-
)
|
|
522
|
-
|
|
523
|
-
advance_namespace_stack(
|
|
524
|
-
nesting.last, #: as !nil
|
|
525
|
-
entry,
|
|
526
|
-
)
|
|
527
|
-
end
|
|
528
|
-
|
|
529
|
-
#: { (Index index, Entry::Namespace base) -> void } -> void
|
|
530
|
-
def register_included_hook(&block)
|
|
531
|
-
owner = @owner_stack.last
|
|
532
|
-
return unless owner
|
|
533
|
-
|
|
534
|
-
@index.register_included_hook(owner.name) do |index, base|
|
|
535
|
-
block.call(index, base)
|
|
536
|
-
end
|
|
537
|
-
end
|
|
538
|
-
|
|
539
|
-
#: -> void
|
|
540
|
-
def pop_namespace_stack
|
|
541
|
-
@stack.pop
|
|
542
|
-
@owner_stack.pop
|
|
543
|
-
@visibility_stack.pop
|
|
544
|
-
end
|
|
545
|
-
|
|
546
|
-
#: -> Entry::Namespace?
|
|
547
|
-
def current_owner
|
|
548
|
-
@owner_stack.last
|
|
549
|
-
end
|
|
550
|
-
|
|
551
|
-
private
|
|
552
|
-
|
|
553
|
-
#: ((Prism::GlobalVariableAndWriteNode | Prism::GlobalVariableOperatorWriteNode | Prism::GlobalVariableOrWriteNode | Prism::GlobalVariableTargetNode | Prism::GlobalVariableWriteNode) node, Prism::Location loc) -> void
|
|
554
|
-
def handle_global_variable(node, loc)
|
|
555
|
-
name = node.name.to_s
|
|
556
|
-
comments = collect_comments(node)
|
|
557
|
-
|
|
558
|
-
@index.add(Entry::GlobalVariable.new(
|
|
559
|
-
@index.configuration,
|
|
560
|
-
name,
|
|
561
|
-
@uri,
|
|
562
|
-
Location.from_prism_location(loc, @code_units_cache),
|
|
563
|
-
comments,
|
|
564
|
-
))
|
|
565
|
-
end
|
|
566
|
-
|
|
567
|
-
#: ((Prism::ClassVariableAndWriteNode | Prism::ClassVariableOperatorWriteNode | Prism::ClassVariableOrWriteNode | Prism::ClassVariableTargetNode | Prism::ClassVariableWriteNode) node, Prism::Location loc) -> void
|
|
568
|
-
def handle_class_variable(node, loc)
|
|
569
|
-
name = node.name.to_s
|
|
570
|
-
# Ignore incomplete class variable names, which aren't valid Ruby syntax.
|
|
571
|
-
# This could occur if the code is in an incomplete or temporary state.
|
|
572
|
-
return if name == "@@"
|
|
573
|
-
|
|
574
|
-
comments = collect_comments(node)
|
|
575
|
-
|
|
576
|
-
owner = @owner_stack.last
|
|
577
|
-
|
|
578
|
-
# set the class variable's owner to the attached context when defined within a singleton scope.
|
|
579
|
-
if owner.is_a?(Entry::SingletonClass)
|
|
580
|
-
owner = @owner_stack.reverse.find { |entry| !entry.name.include?("<") }
|
|
581
|
-
end
|
|
582
|
-
|
|
583
|
-
@index.add(Entry::ClassVariable.new(
|
|
584
|
-
@index.configuration,
|
|
585
|
-
name,
|
|
586
|
-
@uri,
|
|
587
|
-
Location.from_prism_location(loc, @code_units_cache),
|
|
588
|
-
comments,
|
|
589
|
-
owner,
|
|
590
|
-
))
|
|
591
|
-
end
|
|
592
|
-
|
|
593
|
-
#: ((Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode) node, Prism::Location loc) -> void
|
|
594
|
-
def handle_instance_variable(node, loc)
|
|
595
|
-
name = node.name.to_s
|
|
596
|
-
return if name == "@"
|
|
597
|
-
|
|
598
|
-
# When instance variables are declared inside the class body, they turn into class instance variables rather than
|
|
599
|
-
# regular instance variables
|
|
600
|
-
owner = @owner_stack.last
|
|
601
|
-
|
|
602
|
-
if owner && !@inside_def
|
|
603
|
-
owner = @index.existing_or_new_singleton_class(owner.name)
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
@index.add(Entry::InstanceVariable.new(
|
|
607
|
-
@index.configuration,
|
|
608
|
-
name,
|
|
609
|
-
@uri,
|
|
610
|
-
Location.from_prism_location(loc, @code_units_cache),
|
|
611
|
-
collect_comments(node),
|
|
612
|
-
owner,
|
|
613
|
-
))
|
|
614
|
-
end
|
|
615
|
-
|
|
616
|
-
#: (Prism::CallNode node) -> void
|
|
617
|
-
def handle_private_constant(node)
|
|
618
|
-
arguments = node.arguments&.arguments
|
|
619
|
-
return unless arguments
|
|
620
|
-
|
|
621
|
-
first_argument = arguments.first
|
|
622
|
-
|
|
623
|
-
name = case first_argument
|
|
624
|
-
when Prism::StringNode
|
|
625
|
-
first_argument.content
|
|
626
|
-
when Prism::SymbolNode
|
|
627
|
-
first_argument.value
|
|
628
|
-
end
|
|
629
|
-
|
|
630
|
-
return unless name
|
|
631
|
-
|
|
632
|
-
receiver = node.receiver
|
|
633
|
-
name = "#{receiver.slice}::#{name}" if receiver
|
|
634
|
-
|
|
635
|
-
# The private_constant method does not resolve the constant name. It always points to a constant that needs to
|
|
636
|
-
# exist in the current namespace
|
|
637
|
-
entries = @index[fully_qualify_name(name)]
|
|
638
|
-
entries&.each { |entry| entry.visibility = :private }
|
|
639
|
-
end
|
|
640
|
-
|
|
641
|
-
#: (Prism::CallNode node) -> void
|
|
642
|
-
def handle_alias_method(node)
|
|
643
|
-
arguments = node.arguments&.arguments
|
|
644
|
-
return unless arguments
|
|
645
|
-
|
|
646
|
-
new_name, old_name = arguments
|
|
647
|
-
return unless new_name && old_name
|
|
648
|
-
|
|
649
|
-
new_name_value = case new_name
|
|
650
|
-
when Prism::StringNode
|
|
651
|
-
new_name.content
|
|
652
|
-
when Prism::SymbolNode
|
|
653
|
-
new_name.value
|
|
654
|
-
end
|
|
655
|
-
|
|
656
|
-
return unless new_name_value
|
|
657
|
-
|
|
658
|
-
old_name_value = case old_name
|
|
659
|
-
when Prism::StringNode
|
|
660
|
-
old_name.content
|
|
661
|
-
when Prism::SymbolNode
|
|
662
|
-
old_name.value
|
|
663
|
-
end
|
|
664
|
-
|
|
665
|
-
return unless old_name_value
|
|
666
|
-
|
|
667
|
-
comments = collect_comments(node)
|
|
668
|
-
@index.add(
|
|
669
|
-
Entry::UnresolvedMethodAlias.new(
|
|
670
|
-
@index.configuration,
|
|
671
|
-
new_name_value,
|
|
672
|
-
old_name_value,
|
|
673
|
-
@owner_stack.last,
|
|
674
|
-
@uri,
|
|
675
|
-
Location.from_prism_location(new_name.location, @code_units_cache),
|
|
676
|
-
comments,
|
|
677
|
-
),
|
|
678
|
-
)
|
|
679
|
-
end
|
|
680
|
-
|
|
681
|
-
#: ((Prism::ConstantWriteNode | Prism::ConstantOrWriteNode | Prism::ConstantAndWriteNode | Prism::ConstantOperatorWriteNode | Prism::ConstantPathWriteNode | Prism::ConstantPathOrWriteNode | Prism::ConstantPathOperatorWriteNode | Prism::ConstantPathAndWriteNode | Prism::ConstantTargetNode | Prism::ConstantPathTargetNode) node, String name, ?Prism::Node? value) -> void
|
|
682
|
-
def add_constant(node, name, value = nil)
|
|
683
|
-
value = node.value unless node.is_a?(Prism::ConstantTargetNode) || node.is_a?(Prism::ConstantPathTargetNode)
|
|
684
|
-
comments = collect_comments(node)
|
|
685
|
-
|
|
686
|
-
@index.add(
|
|
687
|
-
case value
|
|
688
|
-
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
|
689
|
-
Entry::UnresolvedConstantAlias.new(
|
|
690
|
-
@index.configuration,
|
|
691
|
-
value.slice,
|
|
692
|
-
@stack.dup,
|
|
693
|
-
name,
|
|
694
|
-
@uri,
|
|
695
|
-
Location.from_prism_location(node.location, @code_units_cache),
|
|
696
|
-
comments,
|
|
697
|
-
)
|
|
698
|
-
when Prism::ConstantWriteNode, Prism::ConstantAndWriteNode, Prism::ConstantOrWriteNode,
|
|
699
|
-
Prism::ConstantOperatorWriteNode
|
|
700
|
-
|
|
701
|
-
# If the right hand side is another constant assignment, we need to visit it because that constant has to be
|
|
702
|
-
# indexed too
|
|
703
|
-
Entry::UnresolvedConstantAlias.new(
|
|
704
|
-
@index.configuration,
|
|
705
|
-
value.name.to_s,
|
|
706
|
-
@stack.dup,
|
|
707
|
-
name,
|
|
708
|
-
@uri,
|
|
709
|
-
Location.from_prism_location(node.location, @code_units_cache),
|
|
710
|
-
comments,
|
|
711
|
-
)
|
|
712
|
-
when Prism::ConstantPathWriteNode, Prism::ConstantPathOrWriteNode, Prism::ConstantPathOperatorWriteNode,
|
|
713
|
-
Prism::ConstantPathAndWriteNode
|
|
714
|
-
|
|
715
|
-
Entry::UnresolvedConstantAlias.new(
|
|
716
|
-
@index.configuration,
|
|
717
|
-
value.target.slice,
|
|
718
|
-
@stack.dup,
|
|
719
|
-
name,
|
|
720
|
-
@uri,
|
|
721
|
-
Location.from_prism_location(node.location, @code_units_cache),
|
|
722
|
-
comments,
|
|
723
|
-
)
|
|
724
|
-
else
|
|
725
|
-
Entry::Constant.new(
|
|
726
|
-
@index.configuration,
|
|
727
|
-
name,
|
|
728
|
-
@uri,
|
|
729
|
-
Location.from_prism_location(node.location, @code_units_cache),
|
|
730
|
-
comments,
|
|
731
|
-
)
|
|
732
|
-
end,
|
|
733
|
-
)
|
|
734
|
-
end
|
|
735
|
-
|
|
736
|
-
#: (Prism::Node node) -> String?
|
|
737
|
-
def collect_comments(node)
|
|
738
|
-
return unless @collect_comments
|
|
739
|
-
|
|
740
|
-
comments = +""
|
|
741
|
-
|
|
742
|
-
start_line = node.location.start_line - 1
|
|
743
|
-
start_line -= 1 unless comment_exists_at?(start_line)
|
|
744
|
-
start_line.downto(1) do |line|
|
|
745
|
-
comment = @comments_by_line[line]
|
|
746
|
-
break unless comment
|
|
747
|
-
|
|
748
|
-
# a trailing comment from a previous line is not a comment for this node
|
|
749
|
-
break if comment.trailing?
|
|
750
|
-
|
|
751
|
-
comment_content = comment.location.slice
|
|
752
|
-
|
|
753
|
-
# invalid encodings would raise an "invalid byte sequence" exception
|
|
754
|
-
if !comment_content.valid_encoding? || comment_content.match?(@index.configuration.magic_comment_regex)
|
|
755
|
-
next
|
|
756
|
-
end
|
|
757
|
-
|
|
758
|
-
comment_content.delete_prefix!("#")
|
|
759
|
-
comment_content.delete_prefix!(" ")
|
|
760
|
-
comments.prepend("#{comment_content}\n")
|
|
761
|
-
end
|
|
762
|
-
|
|
763
|
-
comments.chomp!
|
|
764
|
-
comments
|
|
765
|
-
end
|
|
766
|
-
|
|
767
|
-
#: (Integer line) -> bool
|
|
768
|
-
def comment_exists_at?(line)
|
|
769
|
-
@comments_by_line.key?(line) || !@source_lines[line - 1].to_s.strip.empty?
|
|
770
|
-
end
|
|
771
|
-
|
|
772
|
-
#: (String name) -> String
|
|
773
|
-
def fully_qualify_name(name)
|
|
774
|
-
if @stack.empty? || name.start_with?("::")
|
|
775
|
-
name
|
|
776
|
-
else
|
|
777
|
-
"#{@stack.join("::")}::#{name}"
|
|
778
|
-
end.delete_prefix("::")
|
|
779
|
-
end
|
|
780
|
-
|
|
781
|
-
#: (Prism::CallNode node, reader: bool, writer: bool) -> void
|
|
782
|
-
def handle_attribute(node, reader:, writer:)
|
|
783
|
-
arguments = node.arguments&.arguments
|
|
784
|
-
return unless arguments
|
|
785
|
-
|
|
786
|
-
receiver = node.receiver
|
|
787
|
-
return unless receiver.nil? || receiver.is_a?(Prism::SelfNode)
|
|
788
|
-
|
|
789
|
-
comments = collect_comments(node)
|
|
790
|
-
scope = current_visibility_scope
|
|
791
|
-
|
|
792
|
-
arguments.each do |argument|
|
|
793
|
-
name, loc = case argument
|
|
794
|
-
when Prism::SymbolNode
|
|
795
|
-
[argument.value, argument.value_loc]
|
|
796
|
-
when Prism::StringNode
|
|
797
|
-
[argument.content, argument.content_loc]
|
|
798
|
-
end
|
|
799
|
-
|
|
800
|
-
next unless name && loc
|
|
801
|
-
|
|
802
|
-
if reader
|
|
803
|
-
@index.add(Entry::Accessor.new(
|
|
804
|
-
@index.configuration,
|
|
805
|
-
name,
|
|
806
|
-
@uri,
|
|
807
|
-
Location.from_prism_location(loc, @code_units_cache),
|
|
808
|
-
comments,
|
|
809
|
-
scope.visibility,
|
|
810
|
-
@owner_stack.last,
|
|
811
|
-
))
|
|
812
|
-
end
|
|
813
|
-
|
|
814
|
-
next unless writer
|
|
815
|
-
|
|
816
|
-
@index.add(Entry::Accessor.new(
|
|
817
|
-
@index.configuration,
|
|
818
|
-
"#{name}=",
|
|
819
|
-
@uri,
|
|
820
|
-
Location.from_prism_location(loc, @code_units_cache),
|
|
821
|
-
comments,
|
|
822
|
-
scope.visibility,
|
|
823
|
-
@owner_stack.last,
|
|
824
|
-
))
|
|
825
|
-
end
|
|
826
|
-
end
|
|
827
|
-
|
|
828
|
-
#: (Prism::CallNode node, Symbol operation) -> void
|
|
829
|
-
def handle_module_operation(node, operation)
|
|
830
|
-
return if @inside_def
|
|
831
|
-
|
|
832
|
-
owner = @owner_stack.last
|
|
833
|
-
return unless owner
|
|
834
|
-
|
|
835
|
-
arguments = node.arguments&.arguments
|
|
836
|
-
return unless arguments
|
|
837
|
-
|
|
838
|
-
arguments.each do |node|
|
|
839
|
-
next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode) ||
|
|
840
|
-
(node.is_a?(Prism::SelfNode) && operation == :extend)
|
|
841
|
-
|
|
842
|
-
if node.is_a?(Prism::SelfNode)
|
|
843
|
-
singleton = @index.existing_or_new_singleton_class(owner.name)
|
|
844
|
-
singleton.mixin_operations << Entry::Include.new(owner.name)
|
|
845
|
-
else
|
|
846
|
-
case operation
|
|
847
|
-
when :include
|
|
848
|
-
owner.mixin_operations << Entry::Include.new(node.full_name)
|
|
849
|
-
when :prepend
|
|
850
|
-
owner.mixin_operations << Entry::Prepend.new(node.full_name)
|
|
851
|
-
when :extend
|
|
852
|
-
singleton = @index.existing_or_new_singleton_class(owner.name)
|
|
853
|
-
singleton.mixin_operations << Entry::Include.new(node.full_name)
|
|
854
|
-
end
|
|
855
|
-
end
|
|
856
|
-
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
|
|
857
|
-
Prism::ConstantPathNode::MissingNodesInConstantPathError
|
|
858
|
-
# Do nothing
|
|
859
|
-
end
|
|
860
|
-
end
|
|
861
|
-
|
|
862
|
-
#: (Prism::CallNode node) -> void
|
|
863
|
-
def handle_module_function(node)
|
|
864
|
-
# Invoking `module_function` in a class raises
|
|
865
|
-
owner = @owner_stack.last
|
|
866
|
-
return unless owner.is_a?(Entry::Module)
|
|
867
|
-
|
|
868
|
-
arguments_node = node.arguments
|
|
869
|
-
|
|
870
|
-
# If `module_function` is invoked without arguments, all methods defined after it become singleton methods and the
|
|
871
|
-
# visibility for instance methods changes to private
|
|
872
|
-
unless arguments_node
|
|
873
|
-
@visibility_stack.push(VisibilityScope.module_function_scope)
|
|
874
|
-
return
|
|
875
|
-
end
|
|
876
|
-
|
|
877
|
-
owner_name = owner.name
|
|
878
|
-
|
|
879
|
-
arguments_node.arguments.each do |argument|
|
|
880
|
-
method_name = case argument
|
|
881
|
-
when Prism::StringNode
|
|
882
|
-
argument.content
|
|
883
|
-
when Prism::SymbolNode
|
|
884
|
-
argument.value
|
|
885
|
-
end
|
|
886
|
-
next unless method_name
|
|
887
|
-
|
|
888
|
-
entries = @index.resolve_method(method_name, owner_name)
|
|
889
|
-
next unless entries
|
|
890
|
-
|
|
891
|
-
entries.each do |entry|
|
|
892
|
-
entry_owner_name = entry.owner&.name
|
|
893
|
-
next unless entry_owner_name
|
|
894
|
-
|
|
895
|
-
entry.visibility = :private
|
|
896
|
-
|
|
897
|
-
singleton = @index.existing_or_new_singleton_class(entry_owner_name)
|
|
898
|
-
location = Location.from_prism_location(argument.location, @code_units_cache)
|
|
899
|
-
@index.add(Entry::Method.new(
|
|
900
|
-
@index.configuration,
|
|
901
|
-
method_name,
|
|
902
|
-
@uri,
|
|
903
|
-
location,
|
|
904
|
-
location,
|
|
905
|
-
collect_comments(node)&.concat(entry.comments),
|
|
906
|
-
entry.signatures,
|
|
907
|
-
:public,
|
|
908
|
-
singleton,
|
|
909
|
-
))
|
|
910
|
-
end
|
|
911
|
-
end
|
|
912
|
-
end
|
|
913
|
-
|
|
914
|
-
#: (Prism::CallNode node) -> void
|
|
915
|
-
def handle_private_class_method(node)
|
|
916
|
-
arguments = node.arguments&.arguments
|
|
917
|
-
return unless arguments
|
|
918
|
-
|
|
919
|
-
# If we're passing a method definition directly to `private_class_method`, push a new private scope. That will be
|
|
920
|
-
# applied when the indexer finds the method definition and then popped on `call_node_leave`
|
|
921
|
-
if arguments.first.is_a?(Prism::DefNode)
|
|
922
|
-
@visibility_stack.push(VisibilityScope.new(visibility: :private))
|
|
923
|
-
return
|
|
924
|
-
end
|
|
925
|
-
|
|
926
|
-
owner_name = @owner_stack.last&.name
|
|
927
|
-
return unless owner_name
|
|
928
|
-
|
|
929
|
-
# private_class_method accepts strings, symbols or arrays of strings and symbols as arguments. Here we build a
|
|
930
|
-
# single list of all of the method names that have to be made private
|
|
931
|
-
arrays, others = arguments.partition do |argument|
|
|
932
|
-
argument.is_a?(Prism::ArrayNode)
|
|
933
|
-
end #: as [Array[Prism::ArrayNode], Array[Prism::Node]]
|
|
934
|
-
arrays.each { |array| others.concat(array.elements) }
|
|
935
|
-
|
|
936
|
-
names = others.filter_map do |argument|
|
|
937
|
-
case argument
|
|
938
|
-
when Prism::StringNode
|
|
939
|
-
argument.unescaped
|
|
940
|
-
when Prism::SymbolNode
|
|
941
|
-
argument.value
|
|
942
|
-
end
|
|
943
|
-
end
|
|
944
|
-
|
|
945
|
-
names.each do |name|
|
|
946
|
-
entries = @index.resolve_method(name, @index.existing_or_new_singleton_class(owner_name).name)
|
|
947
|
-
next unless entries
|
|
948
|
-
|
|
949
|
-
entries.each { |entry| entry.visibility = :private }
|
|
950
|
-
end
|
|
951
|
-
end
|
|
952
|
-
|
|
953
|
-
#: -> VisibilityScope
|
|
954
|
-
def current_visibility_scope
|
|
955
|
-
@visibility_stack.last #: as !nil
|
|
956
|
-
end
|
|
957
|
-
|
|
958
|
-
#: (Prism::ParametersNode? parameters_node) -> Array[Entry::Parameter]
|
|
959
|
-
def list_params(parameters_node)
|
|
960
|
-
return [] unless parameters_node
|
|
961
|
-
|
|
962
|
-
parameters = []
|
|
963
|
-
|
|
964
|
-
parameters_node.requireds.each do |required|
|
|
965
|
-
name = parameter_name(required)
|
|
966
|
-
next unless name
|
|
967
|
-
|
|
968
|
-
parameters << Entry::RequiredParameter.new(name: name)
|
|
969
|
-
end
|
|
970
|
-
|
|
971
|
-
parameters_node.optionals.each do |optional|
|
|
972
|
-
name = parameter_name(optional)
|
|
973
|
-
next unless name
|
|
974
|
-
|
|
975
|
-
parameters << Entry::OptionalParameter.new(name: name)
|
|
976
|
-
end
|
|
977
|
-
|
|
978
|
-
rest = parameters_node.rest
|
|
979
|
-
|
|
980
|
-
if rest.is_a?(Prism::RestParameterNode)
|
|
981
|
-
rest_name = rest.name || Entry::RestParameter::DEFAULT_NAME
|
|
982
|
-
parameters << Entry::RestParameter.new(name: rest_name)
|
|
983
|
-
end
|
|
984
|
-
|
|
985
|
-
parameters_node.keywords.each do |keyword|
|
|
986
|
-
name = parameter_name(keyword)
|
|
987
|
-
next unless name
|
|
988
|
-
|
|
989
|
-
case keyword
|
|
990
|
-
when Prism::RequiredKeywordParameterNode
|
|
991
|
-
parameters << Entry::KeywordParameter.new(name: name)
|
|
992
|
-
when Prism::OptionalKeywordParameterNode
|
|
993
|
-
parameters << Entry::OptionalKeywordParameter.new(name: name)
|
|
994
|
-
end
|
|
995
|
-
end
|
|
996
|
-
|
|
997
|
-
keyword_rest = parameters_node.keyword_rest
|
|
998
|
-
|
|
999
|
-
case keyword_rest
|
|
1000
|
-
when Prism::KeywordRestParameterNode
|
|
1001
|
-
keyword_rest_name = parameter_name(keyword_rest) || Entry::KeywordRestParameter::DEFAULT_NAME
|
|
1002
|
-
parameters << Entry::KeywordRestParameter.new(name: keyword_rest_name)
|
|
1003
|
-
when Prism::ForwardingParameterNode
|
|
1004
|
-
parameters << Entry::ForwardingParameter.new
|
|
1005
|
-
end
|
|
1006
|
-
|
|
1007
|
-
parameters_node.posts.each do |post|
|
|
1008
|
-
name = parameter_name(post)
|
|
1009
|
-
next unless name
|
|
1010
|
-
|
|
1011
|
-
parameters << Entry::RequiredParameter.new(name: name)
|
|
1012
|
-
end
|
|
1013
|
-
|
|
1014
|
-
block = parameters_node.block
|
|
1015
|
-
parameters << Entry::BlockParameter.new(name: block.name || Entry::BlockParameter::DEFAULT_NAME) if block
|
|
1016
|
-
|
|
1017
|
-
parameters
|
|
1018
|
-
end
|
|
1019
|
-
|
|
1020
|
-
#: (Prism::Node? node) -> Symbol?
|
|
1021
|
-
def parameter_name(node)
|
|
1022
|
-
case node
|
|
1023
|
-
when Prism::RequiredParameterNode, Prism::OptionalParameterNode,
|
|
1024
|
-
Prism::RequiredKeywordParameterNode, Prism::OptionalKeywordParameterNode,
|
|
1025
|
-
Prism::RestParameterNode, Prism::KeywordRestParameterNode
|
|
1026
|
-
node.name
|
|
1027
|
-
when Prism::MultiTargetNode
|
|
1028
|
-
names = node.lefts.map { |parameter_node| parameter_name(parameter_node) }
|
|
1029
|
-
|
|
1030
|
-
rest = node.rest
|
|
1031
|
-
if rest.is_a?(Prism::SplatNode)
|
|
1032
|
-
name = rest.expression&.slice
|
|
1033
|
-
names << (rest.operator == "*" ? "*#{name}".to_sym : name&.to_sym)
|
|
1034
|
-
end
|
|
1035
|
-
|
|
1036
|
-
names << nil if rest.is_a?(Prism::ImplicitRestNode)
|
|
1037
|
-
|
|
1038
|
-
names.concat(node.rights.map { |parameter_node| parameter_name(parameter_node) })
|
|
1039
|
-
|
|
1040
|
-
names_with_commas = names.join(", ")
|
|
1041
|
-
:"(#{names_with_commas})"
|
|
1042
|
-
end
|
|
1043
|
-
end
|
|
1044
|
-
|
|
1045
|
-
#: (String short_name, Entry::Namespace entry) -> void
|
|
1046
|
-
def advance_namespace_stack(short_name, entry)
|
|
1047
|
-
@visibility_stack.push(VisibilityScope.public_scope)
|
|
1048
|
-
@owner_stack << entry
|
|
1049
|
-
@index.add(entry)
|
|
1050
|
-
@stack << short_name
|
|
1051
|
-
end
|
|
1052
|
-
|
|
1053
|
-
# Returns the last name in the stack not as we found it, but in terms of declared constants. For example, if the
|
|
1054
|
-
# last entry in the stack is a compact namespace like `Foo::Bar`, then the last name is `Bar`
|
|
1055
|
-
#: -> String?
|
|
1056
|
-
def last_name_in_stack
|
|
1057
|
-
name = @stack.last
|
|
1058
|
-
return unless name
|
|
1059
|
-
|
|
1060
|
-
name.split("::").last
|
|
1061
|
-
end
|
|
1062
|
-
|
|
1063
|
-
#: (Prism::CallNode, Symbol) -> void
|
|
1064
|
-
def handle_visibility_change(node, visibility)
|
|
1065
|
-
owner = @owner_stack.last
|
|
1066
|
-
return unless owner
|
|
1067
|
-
|
|
1068
|
-
owner_name = owner.name
|
|
1069
|
-
method_names = string_or_symbol_argument_values(node)
|
|
1070
|
-
|
|
1071
|
-
if method_names.empty?
|
|
1072
|
-
@visibility_stack.push(VisibilityScope.new(visibility: visibility))
|
|
1073
|
-
return
|
|
1074
|
-
end
|
|
1075
|
-
|
|
1076
|
-
method_names.each do |method_name|
|
|
1077
|
-
entries = @index.resolve_method(method_name, owner_name)
|
|
1078
|
-
next unless entries
|
|
1079
|
-
|
|
1080
|
-
entries.each do |entry|
|
|
1081
|
-
entry.visibility = visibility
|
|
1082
|
-
end
|
|
1083
|
-
end
|
|
1084
|
-
end
|
|
1085
|
-
|
|
1086
|
-
#: (Prism::CallNode) -> Array[String]
|
|
1087
|
-
def string_or_symbol_argument_values(node)
|
|
1088
|
-
arguments = node.arguments&.arguments
|
|
1089
|
-
return [] unless arguments
|
|
1090
|
-
|
|
1091
|
-
arguments.filter_map do |argument|
|
|
1092
|
-
case argument
|
|
1093
|
-
when Prism::StringNode
|
|
1094
|
-
argument.content
|
|
1095
|
-
when Prism::SymbolNode
|
|
1096
|
-
argument.value
|
|
1097
|
-
end
|
|
1098
|
-
end
|
|
1099
|
-
end
|
|
1100
|
-
end
|
|
1101
|
-
end
|