ruby-lsp 0.17.3 → 0.17.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/VERSION +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +251 -100
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +173 -114
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +337 -77
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +43 -14
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +79 -3
- data/lib/ruby_indexer/test/index_test.rb +563 -29
- data/lib/ruby_indexer/test/instance_variables_test.rb +84 -7
- data/lib/ruby_indexer/test/method_test.rb +75 -25
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +38 -2
- data/lib/ruby_indexer/test/test_case.rb +1 -5
- data/lib/ruby_lsp/addon.rb +13 -1
- data/lib/ruby_lsp/document.rb +50 -23
- data/lib/ruby_lsp/erb_document.rb +125 -0
- data/lib/ruby_lsp/global_state.rb +11 -4
- data/lib/ruby_lsp/internal.rb +3 -0
- data/lib/ruby_lsp/listeners/completion.rb +69 -34
- data/lib/ruby_lsp/listeners/definition.rb +34 -23
- data/lib/ruby_lsp/listeners/hover.rb +14 -7
- data/lib/ruby_lsp/listeners/signature_help.rb +5 -2
- data/lib/ruby_lsp/node_context.rb +6 -1
- data/lib/ruby_lsp/requests/code_action_resolve.rb +2 -2
- data/lib/ruby_lsp/requests/completion.rb +6 -5
- data/lib/ruby_lsp/requests/completion_resolve.rb +7 -4
- data/lib/ruby_lsp/requests/definition.rb +4 -3
- data/lib/ruby_lsp/requests/formatting.rb +2 -0
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +88 -0
- data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +3 -2
- data/lib/ruby_lsp/requests/support/common.rb +19 -1
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -4
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +87 -0
- data/lib/ruby_lsp/requests/workspace_symbol.rb +1 -21
- data/lib/ruby_lsp/requests.rb +2 -0
- data/lib/ruby_lsp/ruby_document.rb +10 -0
- data/lib/ruby_lsp/server.rb +95 -26
- data/lib/ruby_lsp/store.rb +23 -8
- data/lib/ruby_lsp/test_helper.rb +3 -1
- data/lib/ruby_lsp/type_inferrer.rb +86 -0
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30ab87e9f42251fafcf8c085d14272b6e0cc0fb6e6968db3fc4c304e92000c63
|
4
|
+
data.tar.gz: 305592ad82c3e41b72dff4c0a48ff60e6158ffba6d06b802844418c3873a6ef9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a38745ee99e4e62843f3bc2a698ec8c447d9bbb39091e158b2a64e36e46a1612962d1062635a007e13aabd3709733b9726a302ef680bd2881673e6abd48e038
|
7
|
+
data.tar.gz: 57b5327b0f17af4530b21ba3c51eb2bff13912e76df77f78284cd9644cebef252e1cbdd38b960de19cc64a68d9daf3788c6e78ef3b95b4bb5d6dc7f97e56c58f
|
data/README.md
CHANGED
@@ -109,6 +109,10 @@ features. This is the mechanism that powers addons like
|
|
109
109
|
- [Ruby LSP RSpec](https://github.com/st0012/ruby-lsp-rspec)
|
110
110
|
- [Ruby LSP rubyfmt](https://github.com/jscharf/ruby-lsp-rubyfmt)
|
111
111
|
|
112
|
+
Additionally, some tools may include a Ruby LSP addon directly, like
|
113
|
+
|
114
|
+
- [Standard Ruby (from v1.39.1)](https://github.com/standardrb/standard/wiki/IDE:-vscode#using-ruby-lsp)
|
115
|
+
|
112
116
|
Other community driven addons can be found in [rubygems](https://rubygems.org/search?query=name%3A+ruby-lsp) by
|
113
117
|
searching for the `ruby-lsp` prefix.
|
114
118
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.17.
|
1
|
+
0.17.5
|
@@ -5,6 +5,9 @@ module RubyIndexer
|
|
5
5
|
class DeclarationListener
|
6
6
|
extend T::Sig
|
7
7
|
|
8
|
+
OBJECT_NESTING = T.let(["Object"].freeze, T::Array[String])
|
9
|
+
BASIC_OBJECT_NESTING = T.let(["BasicObject"].freeze, T::Array[String])
|
10
|
+
|
8
11
|
sig do
|
9
12
|
params(index: Index, dispatcher: Prism::Dispatcher, parse_result: Prism::ParseResult, file_path: String).void
|
10
13
|
end
|
@@ -33,6 +36,8 @@ module RubyIndexer
|
|
33
36
|
:on_class_node_leave,
|
34
37
|
:on_module_node_enter,
|
35
38
|
:on_module_node_leave,
|
39
|
+
:on_singleton_class_node_enter,
|
40
|
+
:on_singleton_class_node_leave,
|
36
41
|
:on_def_node_enter,
|
37
42
|
:on_def_node_leave,
|
38
43
|
:on_call_node_enter,
|
@@ -59,30 +64,43 @@ module RubyIndexer
|
|
59
64
|
sig { params(node: Prism::ClassNode).void }
|
60
65
|
def on_class_node_enter(node)
|
61
66
|
@visibility_stack.push(Entry::Visibility::PUBLIC)
|
62
|
-
|
67
|
+
constant_path = node.constant_path
|
68
|
+
name = constant_path.slice
|
63
69
|
|
64
70
|
comments = collect_comments(node)
|
65
71
|
|
66
72
|
superclass = node.superclass
|
73
|
+
|
74
|
+
nesting = name.start_with?("::") ? [name.delete_prefix("::")] : @stack + [name.delete_prefix("::")]
|
75
|
+
|
67
76
|
parent_class = case superclass
|
68
77
|
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
69
78
|
superclass.slice
|
70
79
|
else
|
71
|
-
|
80
|
+
case nesting
|
81
|
+
when OBJECT_NESTING
|
82
|
+
# When Object is reopened, its parent class should still be the top-level BasicObject
|
83
|
+
"::BasicObject"
|
84
|
+
when BASIC_OBJECT_NESTING
|
85
|
+
# When BasicObject is reopened, its parent class should still be nil
|
86
|
+
nil
|
87
|
+
else
|
88
|
+
# Otherwise, the parent class should be the top-level Object
|
89
|
+
"::Object"
|
90
|
+
end
|
72
91
|
end
|
73
92
|
|
74
|
-
nesting = name.start_with?("::") ? [name.delete_prefix("::")] : @stack + [name.delete_prefix("::")]
|
75
|
-
|
76
93
|
entry = Entry::Class.new(
|
77
94
|
nesting,
|
78
95
|
@file_path,
|
79
96
|
node.location,
|
97
|
+
constant_path.location,
|
80
98
|
comments,
|
81
99
|
parent_class,
|
82
100
|
)
|
83
101
|
|
84
102
|
@owner_stack << entry
|
85
|
-
@index
|
103
|
+
@index.add(entry)
|
86
104
|
@stack << name
|
87
105
|
end
|
88
106
|
|
@@ -96,15 +114,16 @@ module RubyIndexer
|
|
96
114
|
sig { params(node: Prism::ModuleNode).void }
|
97
115
|
def on_module_node_enter(node)
|
98
116
|
@visibility_stack.push(Entry::Visibility::PUBLIC)
|
99
|
-
|
117
|
+
constant_path = node.constant_path
|
118
|
+
name = constant_path.slice
|
100
119
|
|
101
120
|
comments = collect_comments(node)
|
102
121
|
|
103
122
|
nesting = name.start_with?("::") ? [name.delete_prefix("::")] : @stack + [name.delete_prefix("::")]
|
104
|
-
entry = Entry::Module.new(nesting, @file_path, node.location, comments)
|
123
|
+
entry = Entry::Module.new(nesting, @file_path, node.location, constant_path.location, comments)
|
105
124
|
|
106
125
|
@owner_stack << entry
|
107
|
-
@index
|
126
|
+
@index.add(entry)
|
108
127
|
@stack << name
|
109
128
|
end
|
110
129
|
|
@@ -115,6 +134,44 @@ module RubyIndexer
|
|
115
134
|
@visibility_stack.pop
|
116
135
|
end
|
117
136
|
|
137
|
+
sig { params(node: Prism::SingletonClassNode).void }
|
138
|
+
def on_singleton_class_node_enter(node)
|
139
|
+
@visibility_stack.push(Entry::Visibility::PUBLIC)
|
140
|
+
|
141
|
+
current_owner = @owner_stack.last
|
142
|
+
|
143
|
+
if current_owner
|
144
|
+
expression = node.expression
|
145
|
+
@stack << (expression.is_a?(Prism::SelfNode) ? "<Class:#{@stack.last}>" : "<Class:#{expression.slice}>")
|
146
|
+
|
147
|
+
existing_entries = T.cast(@index[@stack.join("::")], T.nilable(T::Array[Entry::SingletonClass]))
|
148
|
+
|
149
|
+
if existing_entries
|
150
|
+
entry = T.must(existing_entries.first)
|
151
|
+
entry.update_singleton_information(node.location, expression.location, collect_comments(node))
|
152
|
+
else
|
153
|
+
entry = Entry::SingletonClass.new(
|
154
|
+
@stack,
|
155
|
+
@file_path,
|
156
|
+
node.location,
|
157
|
+
expression.location,
|
158
|
+
collect_comments(node),
|
159
|
+
nil,
|
160
|
+
)
|
161
|
+
@index.add(entry, skip_prefix_tree: true)
|
162
|
+
end
|
163
|
+
|
164
|
+
@owner_stack << entry
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
sig { params(node: Prism::SingletonClassNode).void }
|
169
|
+
def on_singleton_class_node_leave(node)
|
170
|
+
@stack.pop
|
171
|
+
@owner_stack.pop
|
172
|
+
@visibility_stack.pop
|
173
|
+
end
|
174
|
+
|
118
175
|
sig { params(node: Prism::MultiWriteNode).void }
|
119
176
|
def on_multi_write_node_enter(node)
|
120
177
|
value = node.value
|
@@ -246,119 +303,119 @@ module RubyIndexer
|
|
246
303
|
|
247
304
|
case node.receiver
|
248
305
|
when nil
|
249
|
-
@index
|
306
|
+
@index.add(Entry::Method.new(
|
250
307
|
method_name,
|
251
308
|
@file_path,
|
252
309
|
node.location,
|
310
|
+
node.name_loc,
|
253
311
|
comments,
|
254
|
-
node.parameters,
|
312
|
+
[Entry::Signature.new(list_params(node.parameters))],
|
255
313
|
current_visibility,
|
256
314
|
@owner_stack.last,
|
257
|
-
)
|
315
|
+
))
|
258
316
|
when Prism::SelfNode
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
317
|
+
owner = @owner_stack.last
|
318
|
+
|
319
|
+
if owner
|
320
|
+
singleton = @index.existing_or_new_singleton_class(owner.name)
|
321
|
+
|
322
|
+
@index.add(Entry::Method.new(
|
323
|
+
method_name,
|
324
|
+
@file_path,
|
325
|
+
node.location,
|
326
|
+
node.name_loc,
|
327
|
+
comments,
|
328
|
+
[Entry::Signature.new(list_params(node.parameters))],
|
329
|
+
current_visibility,
|
330
|
+
singleton,
|
331
|
+
))
|
332
|
+
|
333
|
+
@owner_stack << singleton
|
334
|
+
@stack << "<Class:#{@stack.last}>"
|
335
|
+
end
|
268
336
|
end
|
269
337
|
end
|
270
338
|
|
271
339
|
sig { params(node: Prism::DefNode).void }
|
272
340
|
def on_def_node_leave(node)
|
273
341
|
@inside_def = false
|
342
|
+
|
343
|
+
if node.receiver.is_a?(Prism::SelfNode)
|
344
|
+
@owner_stack.pop
|
345
|
+
@stack.pop
|
346
|
+
end
|
274
347
|
end
|
275
348
|
|
276
349
|
sig { params(node: Prism::InstanceVariableWriteNode).void }
|
277
350
|
def on_instance_variable_write_node_enter(node)
|
278
|
-
|
279
|
-
return if name == "@"
|
280
|
-
|
281
|
-
@index << Entry::InstanceVariable.new(
|
282
|
-
name,
|
283
|
-
@file_path,
|
284
|
-
node.name_loc,
|
285
|
-
collect_comments(node),
|
286
|
-
@owner_stack.last,
|
287
|
-
)
|
351
|
+
handle_instance_variable(node, node.name_loc)
|
288
352
|
end
|
289
353
|
|
290
354
|
sig { params(node: Prism::InstanceVariableAndWriteNode).void }
|
291
355
|
def on_instance_variable_and_write_node_enter(node)
|
292
|
-
|
293
|
-
return if name == "@"
|
294
|
-
|
295
|
-
@index << Entry::InstanceVariable.new(
|
296
|
-
name,
|
297
|
-
@file_path,
|
298
|
-
node.name_loc,
|
299
|
-
collect_comments(node),
|
300
|
-
@owner_stack.last,
|
301
|
-
)
|
356
|
+
handle_instance_variable(node, node.name_loc)
|
302
357
|
end
|
303
358
|
|
304
359
|
sig { params(node: Prism::InstanceVariableOperatorWriteNode).void }
|
305
360
|
def on_instance_variable_operator_write_node_enter(node)
|
306
|
-
|
307
|
-
return if name == "@"
|
308
|
-
|
309
|
-
@index << Entry::InstanceVariable.new(
|
310
|
-
name,
|
311
|
-
@file_path,
|
312
|
-
node.name_loc,
|
313
|
-
collect_comments(node),
|
314
|
-
@owner_stack.last,
|
315
|
-
)
|
361
|
+
handle_instance_variable(node, node.name_loc)
|
316
362
|
end
|
317
363
|
|
318
364
|
sig { params(node: Prism::InstanceVariableOrWriteNode).void }
|
319
365
|
def on_instance_variable_or_write_node_enter(node)
|
320
|
-
|
321
|
-
return if name == "@"
|
322
|
-
|
323
|
-
@index << Entry::InstanceVariable.new(
|
324
|
-
name,
|
325
|
-
@file_path,
|
326
|
-
node.name_loc,
|
327
|
-
collect_comments(node),
|
328
|
-
@owner_stack.last,
|
329
|
-
)
|
366
|
+
handle_instance_variable(node, node.name_loc)
|
330
367
|
end
|
331
368
|
|
332
369
|
sig { params(node: Prism::InstanceVariableTargetNode).void }
|
333
370
|
def on_instance_variable_target_node_enter(node)
|
334
|
-
|
335
|
-
return if name == "@"
|
336
|
-
|
337
|
-
@index << Entry::InstanceVariable.new(
|
338
|
-
name,
|
339
|
-
@file_path,
|
340
|
-
node.location,
|
341
|
-
collect_comments(node),
|
342
|
-
@owner_stack.last,
|
343
|
-
)
|
371
|
+
handle_instance_variable(node, node.location)
|
344
372
|
end
|
345
373
|
|
346
374
|
sig { params(node: Prism::AliasMethodNode).void }
|
347
375
|
def on_alias_method_node_enter(node)
|
348
376
|
method_name = node.new_name.slice
|
349
377
|
comments = collect_comments(node)
|
350
|
-
@index
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
378
|
+
@index.add(
|
379
|
+
Entry::UnresolvedMethodAlias.new(
|
380
|
+
method_name,
|
381
|
+
node.old_name.slice,
|
382
|
+
@owner_stack.last,
|
383
|
+
@file_path,
|
384
|
+
node.new_name.location,
|
385
|
+
comments,
|
386
|
+
),
|
357
387
|
)
|
358
388
|
end
|
359
389
|
|
360
390
|
private
|
361
391
|
|
392
|
+
sig do
|
393
|
+
params(
|
394
|
+
node: T.any(
|
395
|
+
Prism::InstanceVariableAndWriteNode,
|
396
|
+
Prism::InstanceVariableOperatorWriteNode,
|
397
|
+
Prism::InstanceVariableOrWriteNode,
|
398
|
+
Prism::InstanceVariableTargetNode,
|
399
|
+
Prism::InstanceVariableWriteNode,
|
400
|
+
),
|
401
|
+
loc: Prism::Location,
|
402
|
+
).void
|
403
|
+
end
|
404
|
+
def handle_instance_variable(node, loc)
|
405
|
+
name = node.name.to_s
|
406
|
+
return if name == "@"
|
407
|
+
|
408
|
+
# When instance variables are declared inside the class body, they turn into class instance variables rather than
|
409
|
+
# regular instance variables
|
410
|
+
owner = @owner_stack.last
|
411
|
+
|
412
|
+
if owner && !@inside_def
|
413
|
+
owner = @index.existing_or_new_singleton_class(owner.name)
|
414
|
+
end
|
415
|
+
|
416
|
+
@index.add(Entry::InstanceVariable.new(name, @file_path, loc, collect_comments(node), owner))
|
417
|
+
end
|
418
|
+
|
362
419
|
sig { params(node: Prism::CallNode).void }
|
363
420
|
def handle_private_constant(node)
|
364
421
|
arguments = node.arguments&.arguments
|
@@ -411,13 +468,15 @@ module RubyIndexer
|
|
411
468
|
return unless old_name_value
|
412
469
|
|
413
470
|
comments = collect_comments(node)
|
414
|
-
@index
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
471
|
+
@index.add(
|
472
|
+
Entry::UnresolvedMethodAlias.new(
|
473
|
+
new_name_value,
|
474
|
+
old_name_value,
|
475
|
+
@owner_stack.last,
|
476
|
+
@file_path,
|
477
|
+
new_name.location,
|
478
|
+
comments,
|
479
|
+
),
|
421
480
|
)
|
422
481
|
end
|
423
482
|
|
@@ -443,22 +502,24 @@ module RubyIndexer
|
|
443
502
|
value = node.value unless node.is_a?(Prism::ConstantTargetNode) || node.is_a?(Prism::ConstantPathTargetNode)
|
444
503
|
comments = collect_comments(node)
|
445
504
|
|
446
|
-
@index
|
447
|
-
|
448
|
-
|
449
|
-
|
505
|
+
@index.add(
|
506
|
+
case value
|
507
|
+
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
508
|
+
Entry::UnresolvedAlias.new(value.slice, @stack.dup, name, @file_path, node.location, comments)
|
509
|
+
when Prism::ConstantWriteNode, Prism::ConstantAndWriteNode, Prism::ConstantOrWriteNode,
|
450
510
|
Prism::ConstantOperatorWriteNode
|
451
511
|
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
512
|
+
# If the right hand side is another constant assignment, we need to visit it because that constant has to be
|
513
|
+
# indexed too
|
514
|
+
Entry::UnresolvedAlias.new(value.name.to_s, @stack.dup, name, @file_path, node.location, comments)
|
515
|
+
when Prism::ConstantPathWriteNode, Prism::ConstantPathOrWriteNode, Prism::ConstantPathOperatorWriteNode,
|
456
516
|
Prism::ConstantPathAndWriteNode
|
457
517
|
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
518
|
+
Entry::UnresolvedAlias.new(value.target.slice, @stack.dup, name, @file_path, node.location, comments)
|
519
|
+
else
|
520
|
+
Entry::Constant.new(name, @file_path, node.location, comments)
|
521
|
+
end,
|
522
|
+
)
|
462
523
|
end
|
463
524
|
|
464
525
|
sig { params(node: Prism::Node).returns(T::Array[String]) }
|
@@ -515,15 +576,20 @@ module RubyIndexer
|
|
515
576
|
|
516
577
|
next unless name && loc
|
517
578
|
|
518
|
-
|
519
|
-
|
579
|
+
if reader
|
580
|
+
@index.add(Entry::Accessor.new(name, @file_path, loc, comments, current_visibility, @owner_stack.last))
|
581
|
+
end
|
582
|
+
|
583
|
+
next unless writer
|
584
|
+
|
585
|
+
@index.add(Entry::Accessor.new(
|
520
586
|
"#{name}=",
|
521
587
|
@file_path,
|
522
588
|
loc,
|
523
589
|
comments,
|
524
590
|
current_visibility,
|
525
591
|
@owner_stack.last,
|
526
|
-
)
|
592
|
+
))
|
527
593
|
end
|
528
594
|
end
|
529
595
|
|
@@ -546,7 +612,8 @@ module RubyIndexer
|
|
546
612
|
when :prepend
|
547
613
|
owner.mixin_operations << Entry::Prepend.new(node.full_name)
|
548
614
|
when :extend
|
549
|
-
|
615
|
+
singleton = @index.existing_or_new_singleton_class(owner.name)
|
616
|
+
singleton.mixin_operations << Entry::Include.new(node.full_name)
|
550
617
|
end
|
551
618
|
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
|
552
619
|
Prism::ConstantPathNode::MissingNodesInConstantPathError
|
@@ -558,5 +625,89 @@ module RubyIndexer
|
|
558
625
|
def current_visibility
|
559
626
|
T.must(@visibility_stack.last)
|
560
627
|
end
|
628
|
+
|
629
|
+
sig { params(parameters_node: T.nilable(Prism::ParametersNode)).returns(T::Array[Entry::Parameter]) }
|
630
|
+
def list_params(parameters_node)
|
631
|
+
return [] unless parameters_node
|
632
|
+
|
633
|
+
parameters = []
|
634
|
+
|
635
|
+
parameters_node.requireds.each do |required|
|
636
|
+
name = parameter_name(required)
|
637
|
+
next unless name
|
638
|
+
|
639
|
+
parameters << Entry::RequiredParameter.new(name: name)
|
640
|
+
end
|
641
|
+
|
642
|
+
parameters_node.optionals.each do |optional|
|
643
|
+
name = parameter_name(optional)
|
644
|
+
next unless name
|
645
|
+
|
646
|
+
parameters << Entry::OptionalParameter.new(name: name)
|
647
|
+
end
|
648
|
+
|
649
|
+
rest = parameters_node.rest
|
650
|
+
|
651
|
+
if rest.is_a?(Prism::RestParameterNode)
|
652
|
+
rest_name = rest.name || Entry::RestParameter::DEFAULT_NAME
|
653
|
+
parameters << Entry::RestParameter.new(name: rest_name)
|
654
|
+
end
|
655
|
+
|
656
|
+
parameters_node.keywords.each do |keyword|
|
657
|
+
name = parameter_name(keyword)
|
658
|
+
next unless name
|
659
|
+
|
660
|
+
case keyword
|
661
|
+
when Prism::RequiredKeywordParameterNode
|
662
|
+
parameters << Entry::KeywordParameter.new(name: name)
|
663
|
+
when Prism::OptionalKeywordParameterNode
|
664
|
+
parameters << Entry::OptionalKeywordParameter.new(name: name)
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
keyword_rest = parameters_node.keyword_rest
|
669
|
+
|
670
|
+
if keyword_rest.is_a?(Prism::KeywordRestParameterNode)
|
671
|
+
keyword_rest_name = parameter_name(keyword_rest) || Entry::KeywordRestParameter::DEFAULT_NAME
|
672
|
+
parameters << Entry::KeywordRestParameter.new(name: keyword_rest_name)
|
673
|
+
end
|
674
|
+
|
675
|
+
parameters_node.posts.each do |post|
|
676
|
+
name = parameter_name(post)
|
677
|
+
next unless name
|
678
|
+
|
679
|
+
parameters << Entry::RequiredParameter.new(name: name)
|
680
|
+
end
|
681
|
+
|
682
|
+
block = parameters_node.block
|
683
|
+
parameters << Entry::BlockParameter.new(name: block.name || Entry::BlockParameter::DEFAULT_NAME) if block
|
684
|
+
|
685
|
+
parameters
|
686
|
+
end
|
687
|
+
|
688
|
+
sig { params(node: T.nilable(Prism::Node)).returns(T.nilable(Symbol)) }
|
689
|
+
def parameter_name(node)
|
690
|
+
case node
|
691
|
+
when Prism::RequiredParameterNode, Prism::OptionalParameterNode,
|
692
|
+
Prism::RequiredKeywordParameterNode, Prism::OptionalKeywordParameterNode,
|
693
|
+
Prism::RestParameterNode, Prism::KeywordRestParameterNode
|
694
|
+
node.name
|
695
|
+
when Prism::MultiTargetNode
|
696
|
+
names = node.lefts.map { |parameter_node| parameter_name(parameter_node) }
|
697
|
+
|
698
|
+
rest = node.rest
|
699
|
+
if rest.is_a?(Prism::SplatNode)
|
700
|
+
name = rest.expression&.slice
|
701
|
+
names << (rest.operator == "*" ? "*#{name}".to_sym : name&.to_sym)
|
702
|
+
end
|
703
|
+
|
704
|
+
names << nil if rest.is_a?(Prism::ImplicitRestNode)
|
705
|
+
|
706
|
+
names.concat(node.rights.map { |parameter_node| parameter_name(parameter_node) })
|
707
|
+
|
708
|
+
names_with_commas = names.join(", ")
|
709
|
+
:"(#{names_with_commas})"
|
710
|
+
end
|
711
|
+
end
|
561
712
|
end
|
562
713
|
end
|