ruby-lsp 0.27.0.beta2 → 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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp +0 -46
  4. data/exe/ruby-lsp-check +0 -15
  5. data/lib/ruby_lsp/global_state.rb +0 -5
  6. data/lib/ruby_lsp/internal.rb +2 -1
  7. data/lib/ruby_lsp/listeners/code_lens.rb +1 -1
  8. data/lib/ruby_lsp/listeners/completion.rb +246 -382
  9. data/lib/ruby_lsp/listeners/definition.rb +6 -9
  10. data/lib/ruby_lsp/listeners/hover.rb +11 -9
  11. data/lib/ruby_lsp/listeners/signature_help.rb +11 -12
  12. data/lib/ruby_lsp/listeners/test_discovery.rb +17 -1
  13. data/lib/ruby_lsp/listeners/test_style.rb +1 -1
  14. data/lib/ruby_lsp/requests/completion_resolve.rb +49 -29
  15. data/lib/ruby_lsp/requests/references.rb +21 -7
  16. data/lib/ruby_lsp/requests/rename.rb +1 -1
  17. data/lib/ruby_lsp/requests/support/common.rb +69 -68
  18. data/lib/ruby_lsp/ruby_document.rb +0 -73
  19. data/lib/ruby_lsp/rubydex/declaration.rb +128 -2
  20. data/lib/ruby_lsp/rubydex/definition.rb +16 -0
  21. data/lib/ruby_lsp/rubydex/signature.rb +107 -0
  22. data/lib/ruby_lsp/scripts/compose_bundle.rb +1 -1
  23. data/lib/ruby_lsp/server.rb +7 -162
  24. data/lib/ruby_lsp/test_helper.rb +0 -1
  25. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +1 -1
  26. data/lib/ruby_lsp/type_inferrer.rb +2 -2
  27. metadata +11 -14
  28. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +0 -276
  29. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +0 -1101
  30. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +0 -44
  31. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +0 -605
  32. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +0 -1077
  33. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +0 -37
  34. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +0 -149
  35. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +0 -294
  36. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +0 -32
  37. data/lib/ruby_indexer/ruby_indexer.rb +0 -19
  38. /data/lib/{ruby_indexer/lib/ruby_indexer → ruby_lsp}/uri.rb +0 -0
@@ -1,44 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module RubyIndexer
5
- # @abstract
6
- class Enhancement
7
- @enhancements = [] #: Array[Class[Enhancement]]
8
-
9
- class << self
10
- #: (Class[Enhancement] child) -> void
11
- def inherited(child)
12
- @enhancements << child
13
- super
14
- end
15
-
16
- #: (DeclarationListener listener) -> Array[Enhancement]
17
- def all(listener)
18
- @enhancements.map { |enhancement| enhancement.new(listener) }
19
- end
20
-
21
- # Only available for testing purposes
22
- #: -> void
23
- def clear
24
- @enhancements.clear
25
- end
26
- end
27
-
28
- #: (DeclarationListener listener) -> void
29
- def initialize(listener)
30
- @listener = listener
31
- end
32
-
33
- # The `on_extend` indexing enhancement is invoked whenever an extend is encountered in the code. It can be used to
34
- # register for an included callback, similar to what `ActiveSupport::Concern` does in order to auto-extend the
35
- # `ClassMethods` modules
36
- # @overridable
37
- #: (Prism::CallNode node) -> void
38
- def on_call_node_enter(node); end # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
39
-
40
- # @overridable
41
- #: (Prism::CallNode node) -> void
42
- def on_call_node_leave(node); end # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
43
- end
44
- end
@@ -1,605 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module RubyIndexer
5
- class Entry
6
- #: Configuration
7
- attr_reader :configuration
8
-
9
- #: String
10
- attr_reader :name
11
-
12
- #: URI::Generic
13
- attr_reader :uri
14
-
15
- #: RubyIndexer::Location
16
- attr_reader :location
17
-
18
- alias_method :name_location, :location
19
-
20
- #: Symbol
21
- attr_accessor :visibility
22
-
23
- #: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments) -> void
24
- def initialize(configuration, name, uri, location, comments)
25
- @configuration = configuration
26
- @name = name
27
- @uri = uri
28
- @comments = comments
29
- @visibility = :public #: Symbol
30
- @location = location
31
- end
32
-
33
- #: -> bool
34
- def public?
35
- @visibility == :public
36
- end
37
-
38
- #: -> bool
39
- def protected?
40
- @visibility == :protected
41
- end
42
-
43
- #: -> bool
44
- def private?
45
- @visibility == :private
46
- end
47
-
48
- #: -> String
49
- def file_name
50
- if @uri.scheme == "untitled"
51
- @uri.opaque #: as !nil
52
- else
53
- File.basename(
54
- file_path, #: as !nil
55
- )
56
- end
57
- end
58
-
59
- #: -> String?
60
- def file_path
61
- @uri.full_path
62
- end
63
-
64
- #: -> String
65
- def comments
66
- @comments ||= begin
67
- # Parse only the comments based on the file path, which is much faster than parsing the entire file
68
- path = file_path
69
- parsed_comments = path ? Prism.parse_file_comments(path) : []
70
-
71
- # Group comments based on whether they belong to a single block of comments
72
- grouped = parsed_comments.slice_when do |left, right|
73
- left.location.start_line + 1 != right.location.start_line
74
- end
75
-
76
- # Find the group that is either immediately or two lines above the current entry
77
- correct_group = grouped.find do |group|
78
- comment_end_line = group.last.location.start_line
79
- (comment_end_line..comment_end_line + 1).cover?(@location.start_line - 1)
80
- end
81
-
82
- # If we found something, we join the comments together. Otherwise, the entry has no documentation and we don't
83
- # want to accidentally re-parse it, so we set it to an empty string. If an entry is updated, the entire entry
84
- # object is dropped, so this will not prevent updates
85
- if correct_group
86
- correct_group.filter_map do |comment|
87
- content = comment.slice.chomp
88
-
89
- if content.valid_encoding? && !content.match?(@configuration.magic_comment_regex)
90
- content.delete_prefix!("#")
91
- content.delete_prefix!(" ")
92
- content
93
- end
94
- end.join("\n")
95
- else
96
- ""
97
- end
98
- rescue Errno::ENOENT
99
- # If the file was deleted, but the entry hasn't been removed yet (could happen due to concurrency), then we do
100
- # not want to fail. Just set the comments to an empty string
101
- ""
102
- end
103
- end
104
-
105
- # @abstract
106
- class ModuleOperation
107
- #: String
108
- attr_reader :module_name
109
-
110
- #: (String module_name) -> void
111
- def initialize(module_name)
112
- @module_name = module_name
113
- end
114
- end
115
-
116
- class Include < ModuleOperation; end
117
- class Prepend < ModuleOperation; end
118
-
119
- # @abstract
120
- class Namespace < Entry
121
- #: Array[String]
122
- attr_reader :nesting
123
-
124
- # Returns the location of the constant name, excluding the parent class or the body
125
- #: Location
126
- attr_reader :name_location
127
-
128
- #: (Configuration configuration, Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments) -> void
129
- def initialize(configuration, nesting, uri, location, name_location, comments) # rubocop:disable Metrics/ParameterLists
130
- @name = nesting.join("::") #: String
131
- # The original nesting where this namespace was discovered
132
- @nesting = nesting
133
-
134
- super(configuration, @name, uri, location, comments)
135
-
136
- @name_location = name_location
137
- end
138
-
139
- #: -> Array[String]
140
- def mixin_operation_module_names
141
- mixin_operations.map(&:module_name)
142
- end
143
-
144
- # Stores all explicit prepend, include and extend operations in the exact order they were discovered in the source
145
- # code. Maintaining the order is essential to linearize ancestors the right way when a module is both included
146
- # and prepended
147
- #: -> Array[ModuleOperation]
148
- def mixin_operations
149
- @mixin_operations ||= [] #: Array[ModuleOperation]?
150
- end
151
-
152
- #: -> Integer
153
- def ancestor_hash
154
- mixin_operation_module_names.hash
155
- end
156
- end
157
-
158
- class Module < Namespace
159
- end
160
-
161
- class Class < Namespace
162
- # The unresolved name of the parent class. This may return `nil`, which indicates the lack of an explicit parent
163
- # and therefore ::Object is the correct parent class
164
- #: String?
165
- attr_reader :parent_class
166
-
167
- #: (Configuration configuration, Array[String] nesting, URI::Generic uri, Location location, Location name_location, String? comments, String? parent_class) -> void
168
- def initialize(configuration, nesting, uri, location, name_location, comments, parent_class) # rubocop:disable Metrics/ParameterLists
169
- super(configuration, nesting, uri, location, name_location, comments)
170
- @parent_class = parent_class
171
- end
172
-
173
- # @override
174
- #: -> Integer
175
- def ancestor_hash
176
- [mixin_operation_module_names, @parent_class].hash
177
- end
178
- end
179
-
180
- class SingletonClass < Class
181
- #: (Location location, Location name_location, String? comments) -> void
182
- def update_singleton_information(location, name_location, comments)
183
- @location = location
184
- @name_location = name_location
185
- (@comments ||= +"") << comments if comments
186
- end
187
- end
188
-
189
- class Constant < Entry
190
- end
191
-
192
- # @abstract
193
- class Parameter
194
- # Name includes just the name of the parameter, excluding symbols like splats
195
- #: Symbol
196
- attr_reader :name
197
-
198
- # Decorated name is the parameter name including the splat or block prefix, e.g.: `*foo`, `**foo` or `&block`
199
- alias_method :decorated_name, :name
200
-
201
- #: (name: Symbol) -> void
202
- def initialize(name:)
203
- @name = name
204
- end
205
- end
206
-
207
- # A required method parameter, e.g. `def foo(a)`
208
- class RequiredParameter < Parameter
209
- end
210
-
211
- # An optional method parameter, e.g. `def foo(a = 123)`
212
- class OptionalParameter < Parameter
213
- # @override
214
- #: -> Symbol
215
- def decorated_name
216
- :"#{@name} = <default>"
217
- end
218
- end
219
-
220
- # An required keyword method parameter, e.g. `def foo(a:)`
221
- class KeywordParameter < Parameter
222
- # @override
223
- #: -> Symbol
224
- def decorated_name
225
- :"#{@name}:"
226
- end
227
- end
228
-
229
- # An optional keyword method parameter, e.g. `def foo(a: 123)`
230
- class OptionalKeywordParameter < Parameter
231
- # @override
232
- #: -> Symbol
233
- def decorated_name
234
- :"#{@name}: <default>"
235
- end
236
- end
237
-
238
- # A rest method parameter, e.g. `def foo(*a)`
239
- class RestParameter < Parameter
240
- DEFAULT_NAME = :"<anonymous splat>" #: Symbol
241
-
242
- # @override
243
- #: -> Symbol
244
- def decorated_name
245
- :"*#{@name}"
246
- end
247
- end
248
-
249
- # A keyword rest method parameter, e.g. `def foo(**a)`
250
- class KeywordRestParameter < Parameter
251
- DEFAULT_NAME = :"<anonymous keyword splat>" #: Symbol
252
-
253
- # @override
254
- #: -> Symbol
255
- def decorated_name
256
- :"**#{@name}"
257
- end
258
- end
259
-
260
- # A block method parameter, e.g. `def foo(&block)`
261
- class BlockParameter < Parameter
262
- DEFAULT_NAME = :"<anonymous block>" #: Symbol
263
-
264
- class << self
265
- #: -> BlockParameter
266
- def anonymous
267
- new(name: DEFAULT_NAME)
268
- end
269
- end
270
-
271
- # @override
272
- #: -> Symbol
273
- def decorated_name
274
- :"&#{@name}"
275
- end
276
- end
277
-
278
- # A forwarding method parameter, e.g. `def foo(...)`
279
- class ForwardingParameter < Parameter
280
- #: -> void
281
- def initialize
282
- # You can't name a forwarding parameter, it's always called `...`
283
- super(name: :"...")
284
- end
285
- end
286
-
287
- # @abstract
288
- class Member < Entry
289
- #: Entry::Namespace?
290
- attr_reader :owner
291
-
292
- #: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments, Symbol visibility, Entry::Namespace? owner) -> void
293
- def initialize(configuration, name, uri, location, comments, visibility, owner) # rubocop:disable Metrics/ParameterLists
294
- super(configuration, name, uri, location, comments)
295
- @visibility = visibility
296
- @owner = owner
297
- end
298
-
299
- # @abstract
300
- #: -> Array[Signature]
301
- def signatures
302
- raise AbstractMethodInvokedError
303
- end
304
-
305
- #: -> String
306
- def decorated_parameters
307
- first_signature = signatures.first
308
- return "()" unless first_signature
309
-
310
- "(#{first_signature.format})"
311
- end
312
-
313
- #: -> String
314
- def formatted_signatures
315
- overloads_count = signatures.size
316
- case overloads_count
317
- when 1
318
- ""
319
- when 2
320
- "\n(+1 overload)"
321
- else
322
- "\n(+#{overloads_count - 1} overloads)"
323
- end
324
- end
325
- end
326
-
327
- class Accessor < Member
328
- # @override
329
- #: -> Array[Signature]
330
- def signatures
331
- @signatures ||= begin
332
- params = []
333
- params << RequiredParameter.new(name: name.delete_suffix("=").to_sym) if name.end_with?("=")
334
- [Entry::Signature.new(params)]
335
- end #: Array[Signature]?
336
- end
337
- end
338
-
339
- class Method < Member
340
- # @override
341
- #: Array[Signature]
342
- attr_reader :signatures
343
-
344
- # Returns the location of the method name, excluding parameters or the body
345
- #: Location
346
- attr_reader :name_location
347
-
348
- #: (Configuration configuration, String name, URI::Generic uri, Location location, Location name_location, String? comments, Array[Signature] signatures, Symbol visibility, Entry::Namespace? owner) -> void
349
- def initialize(configuration, name, uri, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists
350
- super(configuration, name, uri, location, comments, visibility, owner)
351
- @signatures = signatures
352
- @name_location = name_location
353
- end
354
- end
355
-
356
- # An UnresolvedAlias points to a constant alias with a right hand side that has not yet been resolved. For
357
- # example, if we find
358
- #
359
- # ```ruby
360
- # CONST = Foo
361
- # ```
362
- # Before we have discovered `Foo`, there's no way to eagerly resolve this alias to the correct target constant.
363
- # All aliases are inserted as UnresolvedAlias in the index first and then we lazily resolve them to the correct
364
- # target in [rdoc-ref:Index#resolve]. If the right hand side contains a constant that doesn't exist, then it's not
365
- # possible to resolve the alias and it will remain an UnresolvedAlias until the right hand side constant exists
366
- class UnresolvedConstantAlias < Entry
367
- #: String
368
- attr_reader :target
369
-
370
- #: Array[String]
371
- attr_reader :nesting
372
-
373
- #: (Configuration configuration, String target, Array[String] nesting, String name, URI::Generic uri, Location location, String? comments) -> void
374
- def initialize(configuration, target, nesting, name, uri, location, comments) # rubocop:disable Metrics/ParameterLists
375
- super(configuration, name, uri, location, comments)
376
-
377
- @target = target
378
- @nesting = nesting
379
- end
380
- end
381
-
382
- # Alias represents a resolved alias, which points to an existing constant target
383
- class ConstantAlias < Entry
384
- #: String
385
- attr_reader :target
386
-
387
- #: (String target, UnresolvedConstantAlias unresolved_alias) -> void
388
- def initialize(target, unresolved_alias)
389
- super(
390
- unresolved_alias.configuration,
391
- unresolved_alias.name,
392
- unresolved_alias.uri,
393
- unresolved_alias.location,
394
- unresolved_alias.comments,
395
- )
396
-
397
- @visibility = unresolved_alias.visibility
398
- @target = target
399
- end
400
- end
401
-
402
- # Represents a global variable e.g.: $DEBUG
403
- class GlobalVariable < Entry; end
404
-
405
- # Represents a class variable e.g.: @@a = 1
406
- class ClassVariable < Entry
407
- #: Entry::Namespace?
408
- attr_reader :owner
409
-
410
- #: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
411
- def initialize(configuration, name, uri, location, comments, owner) # rubocop:disable Metrics/ParameterLists
412
- super(configuration, name, uri, location, comments)
413
- @owner = owner
414
- end
415
- end
416
-
417
- # Represents an instance variable e.g.: @a = 1
418
- class InstanceVariable < Entry
419
- #: Entry::Namespace?
420
- attr_reader :owner
421
-
422
- #: (Configuration configuration, String name, URI::Generic uri, Location location, String? comments, Entry::Namespace? owner) -> void
423
- def initialize(configuration, name, uri, location, comments, owner) # rubocop:disable Metrics/ParameterLists
424
- super(configuration, name, uri, location, comments)
425
- @owner = owner
426
- end
427
- end
428
-
429
- # An unresolved method alias is an alias entry for which we aren't sure what the right hand side points to yet. For
430
- # example, if we have `alias a b`, we create an unresolved alias for `a` because we aren't sure immediate what `b`
431
- # is referring to
432
- class UnresolvedMethodAlias < Entry
433
- #: String
434
- attr_reader :new_name, :old_name
435
-
436
- #: Entry::Namespace?
437
- attr_reader :owner
438
-
439
- #: (Configuration configuration, String new_name, String old_name, Entry::Namespace? owner, URI::Generic uri, Location location, String? comments) -> void
440
- def initialize(configuration, new_name, old_name, owner, uri, location, comments) # rubocop:disable Metrics/ParameterLists
441
- super(configuration, new_name, uri, location, comments)
442
-
443
- @new_name = new_name
444
- @old_name = old_name
445
- @owner = owner
446
- end
447
- end
448
-
449
- # A method alias is a resolved alias entry that points to the exact method target it refers to
450
- class MethodAlias < Entry
451
- #: (Member | MethodAlias)
452
- attr_reader :target
453
-
454
- #: Entry::Namespace?
455
- attr_reader :owner
456
-
457
- #: ((Member | MethodAlias) target, UnresolvedMethodAlias unresolved_alias) -> void
458
- def initialize(target, unresolved_alias)
459
- full_comments = +"Alias for #{target.name}\n"
460
- full_comments << "#{unresolved_alias.comments}\n"
461
- full_comments << target.comments
462
-
463
- super(
464
- unresolved_alias.configuration,
465
- unresolved_alias.new_name,
466
- unresolved_alias.uri,
467
- unresolved_alias.location,
468
- full_comments,
469
- )
470
-
471
- @target = target
472
- @owner = unresolved_alias.owner #: Entry::Namespace?
473
- end
474
-
475
- #: -> String
476
- def decorated_parameters
477
- @target.decorated_parameters
478
- end
479
-
480
- #: -> String
481
- def formatted_signatures
482
- @target.formatted_signatures
483
- end
484
-
485
- #: -> Array[Signature]
486
- def signatures
487
- @target.signatures
488
- end
489
- end
490
-
491
- # Ruby doesn't support method overloading, so a method will have only one signature.
492
- # However RBS can represent the concept of method overloading, with different return types based on the arguments
493
- # passed, so we need to store all the signatures.
494
- class Signature
495
- #: Array[Parameter]
496
- attr_reader :parameters
497
-
498
- #: (Array[Parameter] parameters) -> void
499
- def initialize(parameters)
500
- @parameters = parameters
501
- end
502
-
503
- # Returns a string with the decorated names of the parameters of this member. E.g.: `(a, b = 1, c: 2)`
504
- #: -> String
505
- def format
506
- @parameters.map(&:decorated_name).join(", ")
507
- end
508
-
509
- # Returns `true` if the given call node arguments array matches this method signature. This method will prefer
510
- # returning `true` for situations that cannot be analyzed statically, like the presence of splats, keyword splats
511
- # or forwarding arguments.
512
- #
513
- # Since this method is used to detect which overload should be displayed in signature help, it will also return
514
- # `true` if there are missing arguments since the user may not be done typing yet. For example:
515
- #
516
- # ```ruby
517
- # def foo(a, b); end
518
- # # All of the following are considered matches because the user might be in the middle of typing and we have to
519
- # # show them the signature
520
- # foo
521
- # foo(1)
522
- # foo(1, 2)
523
- # ```
524
- #: (Array[Prism::Node] arguments) -> bool
525
- def matches?(arguments)
526
- min_pos = 0
527
- max_pos = 0 #: (Integer | Float)
528
- names = []
529
- has_forward = false #: bool
530
- has_keyword_rest = false #: bool
531
-
532
- @parameters.each do |param|
533
- case param
534
- when RequiredParameter
535
- min_pos += 1
536
- max_pos += 1
537
- when OptionalParameter
538
- max_pos += 1
539
- when RestParameter
540
- max_pos = Float::INFINITY
541
- when ForwardingParameter
542
- max_pos = Float::INFINITY
543
- has_forward = true
544
- when KeywordParameter, OptionalKeywordParameter
545
- names << param.name
546
- when KeywordRestParameter
547
- has_keyword_rest = true
548
- end
549
- end
550
-
551
- keyword_hash_nodes, positional_args = arguments.partition { |arg| arg.is_a?(Prism::KeywordHashNode) }
552
- keyword_args = keyword_hash_nodes.first #: as Prism::KeywordHashNode?
553
- &.elements
554
- forwarding_arguments, positionals = positional_args.partition do |arg|
555
- arg.is_a?(Prism::ForwardingArgumentsNode)
556
- end
557
-
558
- return true if has_forward && min_pos == 0
559
-
560
- # If the only argument passed is a forwarding argument, then anything will match
561
- (positionals.empty? && forwarding_arguments.any?) ||
562
- (
563
- # Check if positional arguments match. This includes required, optional, rest arguments. We also need to
564
- # verify if there's a trailing forwarding argument, like `def foo(a, ...); end`
565
- positional_arguments_match?(positionals, forwarding_arguments, keyword_args, min_pos, max_pos) &&
566
- # If the positional arguments match, we move on to checking keyword, optional keyword and keyword rest
567
- # arguments. If there's a forward argument, then it will always match. If the method accepts a keyword rest
568
- # (**kwargs), then we can't analyze statically because the user could be passing a hash and we don't know
569
- # what the runtime values inside the hash are.
570
- #
571
- # If none of those match, then we verify if the user is passing the expect names for the keyword arguments
572
- (has_forward || has_keyword_rest || keyword_arguments_match?(keyword_args, names))
573
- )
574
- end
575
-
576
- #: (Array[Prism::Node] positional_args, Array[Prism::Node] forwarding_arguments, Array[Prism::Node]? keyword_args, Integer min_pos, (Integer | Float) max_pos) -> bool
577
- def positional_arguments_match?(positional_args, forwarding_arguments, keyword_args, min_pos, max_pos)
578
- # If the method accepts at least one positional argument and a splat has been passed
579
- (min_pos > 0 && positional_args.any? { |arg| arg.is_a?(Prism::SplatNode) }) ||
580
- # If there's at least one positional argument unaccounted for and a keyword splat has been passed
581
- (min_pos - positional_args.length > 0 && keyword_args&.any? { |arg| arg.is_a?(Prism::AssocSplatNode) }) ||
582
- # If there's at least one positional argument unaccounted for and a forwarding argument has been passed
583
- (min_pos - positional_args.length > 0 && forwarding_arguments.any?) ||
584
- # If the number of positional arguments is within the expected range
585
- (min_pos > 0 && positional_args.length <= max_pos) ||
586
- (min_pos == 0 && positional_args.empty?)
587
- end
588
-
589
- #: (Array[Prism::Node]? args, Array[Symbol] names) -> bool
590
- def keyword_arguments_match?(args, names)
591
- return true unless args
592
- return true if args.any? { |arg| arg.is_a?(Prism::AssocSplatNode) }
593
-
594
- arg_names = args.filter_map do |arg|
595
- next unless arg.is_a?(Prism::AssocNode)
596
-
597
- key = arg.key
598
- key.value&.to_sym if key.is_a?(Prism::SymbolNode)
599
- end
600
-
601
- (arg_names - names).empty?
602
- end
603
- end
604
- end
605
- end