ruby-lsp 0.17.3 → 0.17.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|