ruby-lsp 0.26.5 → 0.26.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,990 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require_relative "test_case"
5
-
6
- module RubyIndexer
7
- class MethodTest < TestCase
8
- def test_method_with_no_parameters
9
- index(<<~RUBY)
10
- class Foo
11
- def bar
12
- end
13
- end
14
- RUBY
15
-
16
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
17
- end
18
-
19
- def test_conditional_method
20
- index(<<~RUBY)
21
- class Foo
22
- def bar
23
- end if condition
24
- end
25
- RUBY
26
-
27
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
28
- end
29
-
30
- def test_method_with_multibyte_characters
31
- index(<<~RUBY)
32
- class Foo
33
- def こんにちは; end
34
- end
35
- RUBY
36
-
37
- assert_entry("こんにちは", Entry::Method, "/fake/path/foo.rb:1-2:1-16")
38
- end
39
-
40
- def test_singleton_method_using_self_receiver
41
- index(<<~RUBY)
42
- class Foo
43
- def self.bar
44
- end
45
- end
46
- RUBY
47
-
48
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
49
-
50
- entry = @index["bar"]&.first #: as Entry::Method
51
- owner = entry.owner
52
- assert_equal("Foo::<Class:Foo>", owner&.name)
53
- assert_instance_of(Entry::SingletonClass, owner)
54
- end
55
-
56
- def test_singleton_method_using_other_receiver_is_not_indexed
57
- index(<<~RUBY)
58
- class Foo
59
- def String.bar
60
- end
61
- end
62
- RUBY
63
-
64
- assert_no_entry("bar")
65
- end
66
-
67
- def test_method_under_dynamic_class_or_module
68
- index(<<~RUBY)
69
- module Foo
70
- class self::Bar
71
- def bar
72
- end
73
- end
74
- end
75
-
76
- module Bar
77
- def bar
78
- end
79
- end
80
- RUBY
81
-
82
- assert_equal(2, @index["bar"]&.length)
83
- first_entry = @index["bar"]&.first #: as Entry::Method
84
- assert_equal("Foo::self::Bar", first_entry.owner&.name)
85
- second_entry = @index["bar"]&.last #: as Entry::Method
86
- assert_equal("Bar", second_entry.owner&.name)
87
- end
88
-
89
- def test_visibility_tracking
90
- index(<<~RUBY)
91
- class Foo
92
- private def foo
93
- end
94
-
95
- def bar; end
96
-
97
- protected
98
-
99
- def baz; end
100
- end
101
- RUBY
102
-
103
- assert_entry("foo", Entry::Method, "/fake/path/foo.rb:1-10:2-5", visibility: :private)
104
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:4-2:4-14", visibility: :public)
105
- assert_entry("baz", Entry::Method, "/fake/path/foo.rb:8-2:8-14", visibility: :protected)
106
- end
107
-
108
- def test_visibility_tracking_with_nested_class_or_modules
109
- index(<<~RUBY)
110
- class Foo
111
- private
112
-
113
- def foo; end
114
-
115
- class Bar
116
- def bar; end
117
- end
118
-
119
- def baz; end
120
- end
121
- RUBY
122
-
123
- assert_entry("foo", Entry::Method, "/fake/path/foo.rb:3-2:3-14", visibility: :private)
124
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:6-4:6-16", visibility: :public)
125
- assert_entry("baz", Entry::Method, "/fake/path/foo.rb:9-2:9-14", visibility: :private)
126
- end
127
-
128
- def test_visibility_tracking_with_module_function
129
- index(<<~RUBY)
130
- module Test
131
- def foo; end
132
- def bar; end
133
- module_function :foo, "bar"
134
- end
135
- RUBY
136
-
137
- ["foo", "bar"].each do |keyword|
138
- entries = @index[keyword] #: as Array[Entry::Method]
139
- # should receive two entries because module_function creates a singleton method
140
- # for the Test module and a private method for classes include the Test module
141
- assert_equal(entries.size, 2)
142
- first_entry, second_entry = *entries
143
- # The first entry points to the location of the module_function call
144
- assert_equal("Test", first_entry&.owner&.name)
145
- assert_instance_of(Entry::Module, first_entry&.owner)
146
- assert_predicate(first_entry, :private?)
147
- # The second entry points to the public singleton method
148
- assert_equal("Test::<Class:Test>", second_entry&.owner&.name)
149
- assert_instance_of(Entry::SingletonClass, second_entry&.owner)
150
- assert_equal(:public, second_entry&.visibility)
151
- end
152
- end
153
-
154
- def test_private_class_method_visibility_tracking_string_symbol_arguments
155
- index(<<~RUBY)
156
- class Test
157
- def self.foo
158
- end
159
-
160
- def self.bar
161
- end
162
-
163
- private_class_method("foo", :bar)
164
-
165
- def self.baz
166
- end
167
- end
168
- RUBY
169
-
170
- ["foo", "bar"].each do |keyword|
171
- entries = @index[keyword] #: as Array[Entry::Method]
172
- assert_equal(1, entries.size)
173
- entry = entries.first
174
- assert_predicate(entry, :private?)
175
- end
176
-
177
- entries = @index["baz"] #: as Array[Entry::Method]
178
- assert_equal(1, entries.size)
179
- entry = entries.first
180
- assert_predicate(entry, :public?)
181
- end
182
-
183
- def test_private_class_method_visibility_tracking_array_argument
184
- index(<<~RUBY)
185
- class Test
186
- def self.foo
187
- end
188
-
189
- def self.bar
190
- end
191
-
192
- private_class_method(["foo", :bar])
193
-
194
- def self.baz
195
- end
196
- end
197
- RUBY
198
-
199
- ["foo", "bar"].each do |keyword|
200
- entries = @index[keyword] #: as Array[Entry::Method]
201
- assert_equal(1, entries.size)
202
- entry = entries.first
203
- assert_predicate(entry, :private?)
204
- end
205
-
206
- entries = @index["baz"] #: as Array[Entry::Method]
207
- assert_equal(1, entries.size)
208
- entry = entries.first
209
- assert_predicate(entry, :public?)
210
- end
211
-
212
- def test_private_class_method_visibility_tracking_method_argument
213
- index(<<~RUBY)
214
- class Test
215
- private_class_method def self.foo
216
- end
217
-
218
- def self.bar
219
- end
220
- end
221
- RUBY
222
-
223
- entries = @index["foo"] #: as Array[Entry::Method]
224
- assert_equal(1, entries.size)
225
- entry = entries.first
226
- assert_predicate(entry, :private?)
227
-
228
- entries = @index["bar"] #: as Array[Entry::Method]
229
- assert_equal(1, entries.size)
230
- entry = entries.first
231
- assert_predicate(entry, :public?)
232
- end
233
-
234
- def test_comments_documentation
235
- index(<<~RUBY)
236
- # Documentation for Foo
237
-
238
- class Foo
239
- # ####################
240
- # Documentation for bar
241
- # ####################
242
- #
243
- def bar
244
- end
245
-
246
- # test
247
-
248
- # Documentation for baz
249
- def baz; end
250
- def ban; end
251
- end
252
- RUBY
253
-
254
- foo = @index["Foo"]&.first #: as !nil
255
- assert_equal("Documentation for Foo", foo.comments)
256
-
257
- bar = @index["bar"]&.first #: as !nil
258
- assert_equal("####################\nDocumentation for bar\n####################\n", bar.comments)
259
-
260
- baz = @index["baz"]&.first #: as !nil
261
- assert_equal("Documentation for baz", baz.comments)
262
-
263
- ban = @index["ban"]&.first #: as !nil
264
- assert_empty(ban.comments)
265
- end
266
-
267
- def test_method_with_parameters
268
- index(<<~RUBY)
269
- class Foo
270
- def bar(a)
271
- end
272
- end
273
- RUBY
274
-
275
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
276
- entry = @index["bar"]&.first #: as Entry::Method
277
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
278
- assert_equal(1, parameters.length)
279
- parameter = parameters.first
280
- assert_equal(:a, parameter&.name)
281
- assert_instance_of(Entry::RequiredParameter, parameter)
282
- end
283
-
284
- def test_method_with_destructed_parameters
285
- index(<<~RUBY)
286
- class Foo
287
- def bar((a, (b, )))
288
- end
289
- end
290
- RUBY
291
-
292
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
293
- entry = @index["bar"]&.first #: as Entry::Method
294
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
295
- assert_equal(1, parameters.length)
296
- parameter = parameters.first
297
- assert_equal(:"(a, (b, ))", parameter&.name)
298
- assert_instance_of(Entry::RequiredParameter, parameter)
299
- end
300
-
301
- def test_method_with_optional_parameters
302
- index(<<~RUBY)
303
- class Foo
304
- def bar(a = 123)
305
- end
306
- end
307
- RUBY
308
-
309
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
310
- entry = @index["bar"]&.first #: as Entry::Method
311
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
312
- assert_equal(1, parameters.length)
313
- parameter = parameters.first
314
- assert_equal(:a, parameter&.name)
315
- assert_instance_of(Entry::OptionalParameter, parameter)
316
- end
317
-
318
- def test_method_with_keyword_parameters
319
- index(<<~RUBY)
320
- class Foo
321
- def bar(a:, b: 123)
322
- end
323
- end
324
- RUBY
325
-
326
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
327
- entry = @index["bar"]&.first #: as Entry::Method
328
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
329
- assert_equal(2, parameters.length)
330
- a, b = parameters
331
-
332
- assert_equal(:a, a&.name)
333
- assert_instance_of(Entry::KeywordParameter, a)
334
-
335
- assert_equal(:b, b&.name)
336
- assert_instance_of(Entry::OptionalKeywordParameter, b)
337
- end
338
-
339
- def test_method_with_rest_and_keyword_rest_parameters
340
- index(<<~RUBY)
341
- class Foo
342
- def bar(*a, **b)
343
- end
344
- end
345
- RUBY
346
-
347
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
348
- entry = @index["bar"]&.first #: as Entry::Method
349
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
350
- assert_equal(2, parameters.length)
351
- a, b = parameters
352
-
353
- assert_equal(:a, a&.name)
354
- assert_instance_of(Entry::RestParameter, a)
355
-
356
- assert_equal(:b, b&.name)
357
- assert_instance_of(Entry::KeywordRestParameter, b)
358
- end
359
-
360
- def test_method_with_post_parameters
361
- index(<<~RUBY)
362
- class Foo
363
- def bar(*a, b)
364
- end
365
-
366
- def baz(**a, b)
367
- end
368
-
369
- def qux(*a, (b, c))
370
- end
371
- RUBY
372
-
373
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
374
- entry = @index["bar"]&.first #: as Entry::Method
375
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
376
- assert_equal(2, parameters.length)
377
- a, b = parameters
378
-
379
- assert_equal(:a, a&.name)
380
- assert_instance_of(Entry::RestParameter, a)
381
-
382
- assert_equal(:b, b&.name)
383
- assert_instance_of(Entry::RequiredParameter, b)
384
-
385
- entry = @index["baz"]&.first #: as Entry::Method
386
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
387
- assert_equal(2, parameters.length)
388
- a, b = parameters
389
-
390
- assert_equal(:a, a&.name)
391
- assert_instance_of(Entry::KeywordRestParameter, a)
392
-
393
- assert_equal(:b, b&.name)
394
- assert_instance_of(Entry::RequiredParameter, b)
395
-
396
- entry = @index["qux"]&.first #: as Entry::Method
397
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
398
- assert_equal(2, parameters.length)
399
- _a, second = parameters
400
-
401
- assert_equal(:"(b, c)", second&.name)
402
- assert_instance_of(Entry::RequiredParameter, second)
403
- end
404
-
405
- def test_method_with_destructured_rest_parameters
406
- index(<<~RUBY)
407
- class Foo
408
- def bar((a, *b))
409
- end
410
- end
411
- RUBY
412
-
413
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
414
- entry = @index["bar"]&.first #: as Entry::Method
415
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
416
- assert_equal(1, parameters.length)
417
- param = parameters.first #: as Entry::Parameter
418
-
419
- assert_equal(:"(a, *b)", param.name)
420
- assert_instance_of(Entry::RequiredParameter, param)
421
- end
422
-
423
- def test_method_with_block_parameters
424
- index(<<~RUBY)
425
- class Foo
426
- def bar(&block)
427
- end
428
-
429
- def baz(&)
430
- end
431
- end
432
- RUBY
433
-
434
- entry = @index["bar"]&.first #: as Entry::Method
435
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
436
- param = parameters.first #: as Entry::Parameter
437
- assert_equal(:block, param.name)
438
- assert_instance_of(Entry::BlockParameter, param)
439
-
440
- entry = @index["baz"]&.first #: as Entry::Method
441
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
442
- assert_equal(1, parameters.length)
443
-
444
- param = parameters.first #: as Entry::Parameter
445
- assert_equal(Entry::BlockParameter::DEFAULT_NAME, param.name)
446
- assert_instance_of(Entry::BlockParameter, param)
447
- end
448
-
449
- def test_method_with_anonymous_rest_parameters
450
- index(<<~RUBY)
451
- class Foo
452
- def bar(*, **)
453
- end
454
- end
455
- RUBY
456
-
457
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
458
- entry = @index["bar"]&.first #: as Entry::Method
459
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
460
- assert_equal(2, parameters.length)
461
- first, second = parameters
462
-
463
- assert_equal(Entry::RestParameter::DEFAULT_NAME, first&.name)
464
- assert_instance_of(Entry::RestParameter, first)
465
-
466
- assert_equal(Entry::KeywordRestParameter::DEFAULT_NAME, second&.name)
467
- assert_instance_of(Entry::KeywordRestParameter, second)
468
- end
469
-
470
- def test_method_with_forbidden_keyword_splat_parameter
471
- index(<<~RUBY)
472
- class Foo
473
- def bar(**nil)
474
- end
475
- end
476
- RUBY
477
-
478
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
479
- entry = @index["bar"]&.first #: as Entry::Method
480
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
481
- assert_empty(parameters)
482
- end
483
-
484
- def test_methods_with_argument_forwarding
485
- index(<<~RUBY)
486
- class Foo
487
- def bar(...)
488
- end
489
-
490
- def baz(a, ...)
491
- end
492
- end
493
- RUBY
494
-
495
- entry = @index["bar"]&.first #: as Entry::Method
496
- assert_instance_of(Entry::Method, entry, "Expected `bar` to be indexed")
497
-
498
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
499
- assert_equal(1, parameters.length)
500
- assert_instance_of(Entry::ForwardingParameter, parameters.first)
501
-
502
- entry = @index["baz"]&.first #: as Entry::Method
503
- assert_instance_of(Entry::Method, entry, "Expected `baz` to be indexed")
504
-
505
- parameters = entry.signatures.first&.parameters #: as Array[Entry::Parameter]
506
- assert_equal(2, parameters.length)
507
- assert_instance_of(Entry::RequiredParameter, parameters[0])
508
- assert_instance_of(Entry::ForwardingParameter, parameters[1])
509
- end
510
-
511
- def test_keeps_track_of_method_owner
512
- index(<<~RUBY)
513
- class Foo
514
- def bar
515
- end
516
- end
517
- RUBY
518
-
519
- entry = @index["bar"]&.first #: as Entry::Method
520
- owner_name = entry.owner&.name
521
-
522
- assert_equal("Foo", owner_name)
523
- end
524
-
525
- def test_keeps_track_of_attributes
526
- index(<<~RUBY)
527
- class Foo
528
- # Hello there
529
- attr_reader :bar, :other
530
- attr_writer :baz
531
- attr_accessor :qux
532
- end
533
- RUBY
534
-
535
- assert_entry("bar", Entry::Accessor, "/fake/path/foo.rb:2-15:2-18")
536
- assert_equal("Hello there", @index["bar"]&.first&.comments)
537
- assert_entry("other", Entry::Accessor, "/fake/path/foo.rb:2-21:2-26")
538
- assert_equal("Hello there", @index["other"]&.first&.comments)
539
- assert_entry("baz=", Entry::Accessor, "/fake/path/foo.rb:3-15:3-18")
540
- assert_entry("qux", Entry::Accessor, "/fake/path/foo.rb:4-17:4-20")
541
- assert_entry("qux=", Entry::Accessor, "/fake/path/foo.rb:4-17:4-20")
542
- end
543
-
544
- def test_ignores_attributes_invoked_on_constant
545
- index(<<~RUBY)
546
- class Foo
547
- end
548
-
549
- Foo.attr_reader :bar
550
- RUBY
551
-
552
- assert_no_entry("bar")
553
- end
554
-
555
- def test_properly_tracks_multiple_levels_of_nesting
556
- index(<<~RUBY)
557
- module Foo
558
- def first_method; end
559
-
560
- module Bar
561
- def second_method; end
562
- end
563
-
564
- def third_method; end
565
- end
566
- RUBY
567
-
568
- entry = @index["first_method"]&.first #: as Entry::Method
569
- assert_equal("Foo", entry.owner&.name)
570
-
571
- entry = @index["second_method"]&.first #: as Entry::Method
572
- assert_equal("Foo::Bar", entry.owner&.name)
573
-
574
- entry = @index["third_method"]&.first #: as Entry::Method
575
- assert_equal("Foo", entry.owner&.name)
576
- end
577
-
578
- def test_keeps_track_of_aliases
579
- index(<<~RUBY)
580
- class Foo
581
- alias whatever to_s
582
- alias_method :foo, :to_a
583
- alias_method "bar", "to_a"
584
-
585
- # These two are not indexed because they are dynamic or incomplete
586
- alias_method baz, :to_a
587
- alias_method :baz
588
- end
589
- RUBY
590
-
591
- assert_entry("whatever", Entry::UnresolvedMethodAlias, "/fake/path/foo.rb:1-8:1-16")
592
- assert_entry("foo", Entry::UnresolvedMethodAlias, "/fake/path/foo.rb:2-15:2-19")
593
- assert_entry("bar", Entry::UnresolvedMethodAlias, "/fake/path/foo.rb:3-15:3-20")
594
- # Foo plus 3 valid aliases
595
- assert_equal(4, @index.length - @default_indexed_entries.length)
596
- end
597
-
598
- def test_singleton_methods
599
- index(<<~RUBY)
600
- class Foo
601
- def self.bar; end
602
-
603
- class << self
604
- def baz; end
605
- end
606
- end
607
- RUBY
608
-
609
- assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:1-19")
610
- assert_entry("baz", Entry::Method, "/fake/path/foo.rb:4-4:4-16")
611
-
612
- bar = @index["bar"]&.first #: as Entry::Method
613
- baz = @index["baz"]&.first #: as Entry::Method
614
-
615
- assert_instance_of(Entry::SingletonClass, bar.owner)
616
- assert_instance_of(Entry::SingletonClass, baz.owner)
617
-
618
- # Regardless of whether the method was added through `self.something` or `class << self`, the owner object must be
619
- # the exact same
620
- assert_same(bar.owner, baz.owner)
621
- end
622
-
623
- def test_name_location_points_to_method_identifier_location
624
- index(<<~RUBY)
625
- class Foo
626
- def bar
627
- a = 123
628
- a + 456
629
- end
630
- end
631
- RUBY
632
-
633
- entry = @index["bar"]&.first #: as Entry::Method
634
- refute_equal(entry.location, entry.name_location)
635
-
636
- name_location = entry.name_location
637
- assert_equal(2, name_location.start_line)
638
- assert_equal(2, name_location.end_line)
639
- assert_equal(6, name_location.start_column)
640
- assert_equal(9, name_location.end_column)
641
- end
642
-
643
- def test_signature_matches_for_a_method_with_positional_params
644
- index(<<~RUBY)
645
- class Foo
646
- def bar(a, b = 123)
647
- end
648
- end
649
- RUBY
650
-
651
- entry = @index["bar"]&.first #: as Entry::Method
652
-
653
- # Matching calls
654
- assert_signature_matches(entry, "bar()")
655
- assert_signature_matches(entry, "bar(1)")
656
- assert_signature_matches(entry, "bar(1, 2)")
657
- assert_signature_matches(entry, "bar(...)")
658
- assert_signature_matches(entry, "bar(1, ...)")
659
- assert_signature_matches(entry, "bar(*a)")
660
- assert_signature_matches(entry, "bar(1, *a)")
661
- assert_signature_matches(entry, "bar(1, *a, 2)")
662
- assert_signature_matches(entry, "bar(*a, 2)")
663
- assert_signature_matches(entry, "bar(1, **a)")
664
- assert_signature_matches(entry, "bar(1) {}")
665
- # This call is impossible to analyze statically because it depends on whether there are elements inside `a` or
666
- # not. If there's nothing, the call will fail. But if there's anything inside, the hash will become the first
667
- # positional argument
668
- assert_signature_matches(entry, "bar(**a)")
669
-
670
- # Non matching calls
671
-
672
- refute_signature_matches(entry, "bar(1, 2, 3)")
673
- refute_signature_matches(entry, "bar(1, b: 2)")
674
- refute_signature_matches(entry, "bar(1, 2, c: 3)")
675
- end
676
-
677
- def test_signature_matches_for_a_method_with_argument_forwarding
678
- index(<<~RUBY)
679
- class Foo
680
- def bar(...)
681
- end
682
- end
683
- RUBY
684
-
685
- entry = @index["bar"]&.first #: as Entry::Method
686
-
687
- # All calls match a forwarding parameter
688
- assert_signature_matches(entry, "bar(1)")
689
- assert_signature_matches(entry, "bar(1, 2)")
690
- assert_signature_matches(entry, "bar(...)")
691
- assert_signature_matches(entry, "bar(1, ...)")
692
- assert_signature_matches(entry, "bar(*a)")
693
- assert_signature_matches(entry, "bar(1, *a)")
694
- assert_signature_matches(entry, "bar(1, *a, 2)")
695
- assert_signature_matches(entry, "bar(*a, 2)")
696
- assert_signature_matches(entry, "bar(1, **a)")
697
- assert_signature_matches(entry, "bar(1) {}")
698
- assert_signature_matches(entry, "bar()")
699
- assert_signature_matches(entry, "bar(1, 2, 3)")
700
- assert_signature_matches(entry, "bar(1, 2, a: 1, b: 5) {}")
701
- end
702
-
703
- def test_signature_matches_for_post_forwarding_parameter
704
- index(<<~RUBY)
705
- class Foo
706
- def bar(a, ...)
707
- end
708
- end
709
- RUBY
710
-
711
- entry = @index["bar"]&.first #: as Entry::Method
712
-
713
- # All calls with at least one positional argument match
714
- assert_signature_matches(entry, "bar(1)")
715
- assert_signature_matches(entry, "bar(1, 2)")
716
- assert_signature_matches(entry, "bar(...)")
717
- assert_signature_matches(entry, "bar(1, ...)")
718
- assert_signature_matches(entry, "bar(*a)")
719
- assert_signature_matches(entry, "bar(1, *a)")
720
- assert_signature_matches(entry, "bar(1, *a, 2)")
721
- assert_signature_matches(entry, "bar(*a, 2)")
722
- assert_signature_matches(entry, "bar(1, **a)")
723
- assert_signature_matches(entry, "bar(1) {}")
724
- assert_signature_matches(entry, "bar(1, 2, 3)")
725
- assert_signature_matches(entry, "bar(1, 2, a: 1, b: 5) {}")
726
- assert_signature_matches(entry, "bar()")
727
- end
728
-
729
- def test_signature_matches_for_destructured_parameters
730
- index(<<~RUBY)
731
- class Foo
732
- def bar(a, (b, c))
733
- end
734
- end
735
- RUBY
736
-
737
- entry = @index["bar"]&.first #: as Entry::Method
738
-
739
- # All calls with at least one positional argument match
740
- assert_signature_matches(entry, "bar()")
741
- assert_signature_matches(entry, "bar(1)")
742
- assert_signature_matches(entry, "bar(1, 2)")
743
- assert_signature_matches(entry, "bar(...)")
744
- assert_signature_matches(entry, "bar(1, ...)")
745
- assert_signature_matches(entry, "bar(*a)")
746
- assert_signature_matches(entry, "bar(1, *a)")
747
- assert_signature_matches(entry, "bar(*a, 2)")
748
- # This matches because `bar(1, *[], 2)` would result in `bar(1, 2)`, which is a valid call
749
- assert_signature_matches(entry, "bar(1, *a, 2)")
750
- assert_signature_matches(entry, "bar(1, **a)")
751
- assert_signature_matches(entry, "bar(1) {}")
752
-
753
- refute_signature_matches(entry, "bar(1, 2, 3)")
754
- refute_signature_matches(entry, "bar(1, 2, a: 1, b: 5) {}")
755
- end
756
-
757
- def test_signature_matches_for_post_parameters
758
- index(<<~RUBY)
759
- class Foo
760
- def bar(*splat, a)
761
- end
762
- end
763
- RUBY
764
-
765
- entry = @index["bar"]&.first #: as Entry::Method
766
-
767
- # All calls with at least one positional argument match
768
- assert_signature_matches(entry, "bar(1)")
769
- assert_signature_matches(entry, "bar(1, 2)")
770
- assert_signature_matches(entry, "bar(...)")
771
- assert_signature_matches(entry, "bar(1, ...)")
772
- assert_signature_matches(entry, "bar(*a)")
773
- assert_signature_matches(entry, "bar(1, *a)")
774
- assert_signature_matches(entry, "bar(*a, 2)")
775
- assert_signature_matches(entry, "bar(1, *a, 2)")
776
- assert_signature_matches(entry, "bar(1, **a)")
777
- assert_signature_matches(entry, "bar(1, 2, 3)")
778
- assert_signature_matches(entry, "bar(1) {}")
779
- assert_signature_matches(entry, "bar()")
780
-
781
- refute_signature_matches(entry, "bar(1, 2, a: 1, b: 5) {}")
782
- end
783
-
784
- def test_signature_matches_for_keyword_parameters
785
- index(<<~RUBY)
786
- class Foo
787
- def bar(a:, b: 123)
788
- end
789
- end
790
- RUBY
791
-
792
- entry = @index["bar"]&.first #: as Entry::Method
793
-
794
- assert_signature_matches(entry, "bar(...)")
795
- assert_signature_matches(entry, "bar()")
796
- assert_signature_matches(entry, "bar(a: 1)")
797
- assert_signature_matches(entry, "bar(a: 1, b: 32)")
798
-
799
- refute_signature_matches(entry, "bar(a: 1, c: 2)")
800
- refute_signature_matches(entry, "bar(1, ...)")
801
- refute_signature_matches(entry, "bar(1) {}")
802
- refute_signature_matches(entry, "bar(1, *a)")
803
- refute_signature_matches(entry, "bar(*a, 2)")
804
- refute_signature_matches(entry, "bar(1, *a, 2)")
805
- refute_signature_matches(entry, "bar(1, **a)")
806
- refute_signature_matches(entry, "bar(*a)")
807
- refute_signature_matches(entry, "bar(1)")
808
- refute_signature_matches(entry, "bar(1, 2)")
809
- refute_signature_matches(entry, "bar(1, 2, a: 1, b: 5) {}")
810
- end
811
-
812
- def test_signature_matches_for_keyword_splats
813
- index(<<~RUBY)
814
- class Foo
815
- def bar(a, b:, **kwargs)
816
- end
817
- end
818
- RUBY
819
-
820
- entry = @index["bar"]&.first #: as Entry::Method
821
-
822
- assert_signature_matches(entry, "bar(...)")
823
- assert_signature_matches(entry, "bar()")
824
- assert_signature_matches(entry, "bar(1)")
825
- assert_signature_matches(entry, "bar(1, b: 2)")
826
- assert_signature_matches(entry, "bar(1, b: 2, c: 3, d: 4)")
827
-
828
- refute_signature_matches(entry, "bar(1, 2, b: 2)")
829
- end
830
-
831
- def test_partial_signature_matches
832
- # It's important to match signatures partially, because we want to figure out which signature we should show while
833
- # the user is in the middle of typing
834
- index(<<~RUBY)
835
- class Foo
836
- def bar(a:, b:)
837
- end
838
-
839
- def baz(a, b)
840
- end
841
- end
842
- RUBY
843
-
844
- entry = @index["bar"]&.first #: as Entry::Method
845
- assert_signature_matches(entry, "bar(a: 1)")
846
-
847
- entry = @index["baz"]&.first #: as Entry::Method
848
- assert_signature_matches(entry, "baz(1)")
849
- end
850
-
851
- def test_module_function_with_no_arguments
852
- index(<<~RUBY)
853
- module Foo
854
- def bar; end
855
-
856
- module_function
857
-
858
- def baz; end
859
- attr_reader :attribute
860
-
861
- public
862
-
863
- def qux; end
864
- end
865
- RUBY
866
-
867
- entry = @index["bar"]&.first #: as Entry::Method
868
- assert_predicate(entry, :public?)
869
- assert_equal("Foo", entry.owner&.name)
870
-
871
- instance_baz, singleton_baz = @index["baz"] #: as Array[Entry::Method]
872
- assert_predicate(instance_baz, :private?)
873
- assert_equal("Foo", instance_baz&.owner&.name)
874
-
875
- assert_predicate(singleton_baz, :public?)
876
- assert_equal("Foo::<Class:Foo>", singleton_baz&.owner&.name)
877
-
878
- # After invoking `public`, the state of `module_function` is reset
879
- instance_qux, singleton_qux = @index["qux"] #: as Array[Entry::Method]
880
- assert_nil(singleton_qux)
881
- assert_predicate(instance_qux, :public?)
882
- assert_equal("Foo", instance_baz&.owner&.name)
883
-
884
- # Attributes are not turned into class methods, they do become private
885
- instance_attribute, singleton_attribute = @index["attribute"] #: as Array[Entry::Method]
886
- assert_nil(singleton_attribute)
887
- assert_equal("Foo", instance_attribute&.owner&.name)
888
- assert_predicate(instance_attribute, :private?)
889
- end
890
-
891
- def test_module_function_does_nothing_in_classes
892
- # Invoking `module_function` in a class raises an error. We simply ignore it
893
- index(<<~RUBY)
894
- class Foo
895
- def bar; end
896
-
897
- module_function
898
-
899
- def baz; end
900
- end
901
- RUBY
902
-
903
- entry = @index["bar"]&.first #: as Entry::Method
904
- assert_predicate(entry, :public?)
905
- assert_equal("Foo", entry.owner&.name)
906
-
907
- entry = @index["baz"]&.first #: as Entry::Method
908
- assert_predicate(entry, :public?)
909
- assert_equal("Foo", entry.owner&.name)
910
- end
911
-
912
- def test_making_several_class_methods_private
913
- index(<<~RUBY)
914
- class Foo
915
- def self.bar; end
916
- def self.baz; end
917
- def self.qux; end
918
-
919
- private_class_method :bar, :baz, :qux
920
-
921
- def initialize
922
- end
923
- end
924
- RUBY
925
- end
926
-
927
- def test_changing_visibility_post_definition
928
- index(<<~RUBY)
929
- class Foo
930
- def bar; end
931
- private :bar
932
-
933
- def baz; end
934
- protected :baz
935
-
936
- private
937
- def qux; end
938
-
939
- public :qux
940
- end
941
- RUBY
942
-
943
- entry = @index["bar"]&.first #: as Entry::Method
944
- assert_predicate(entry, :private?)
945
-
946
- entry = @index["baz"]&.first #: as Entry::Method
947
- assert_predicate(entry, :protected?)
948
-
949
- entry = @index["qux"]&.first #: as Entry::Method
950
- assert_predicate(entry, :public?)
951
- end
952
-
953
- def test_handling_attr
954
- index(<<~RUBY)
955
- class Foo
956
- attr :bar
957
- attr :baz, true
958
- attr :qux, false
959
- end
960
- RUBY
961
-
962
- assert_entry("bar", Entry::Accessor, "/fake/path/foo.rb:1-8:1-11")
963
- assert_no_entry("bar=")
964
- assert_entry("baz", Entry::Accessor, "/fake/path/foo.rb:2-8:2-11")
965
- assert_entry("baz=", Entry::Accessor, "/fake/path/foo.rb:2-8:2-11")
966
- assert_entry("qux", Entry::Accessor, "/fake/path/foo.rb:3-8:3-11")
967
- assert_no_entry("qux=")
968
- end
969
-
970
- private
971
-
972
- #: (Entry::Method entry, String call_string) -> void
973
- def assert_signature_matches(entry, call_string)
974
- sig = entry.signatures.first #: as !nil
975
- arguments = parse_prism_args(call_string)
976
- assert(sig.matches?(arguments), "Expected #{call_string} to match #{entry.name}#{entry.decorated_parameters}")
977
- end
978
-
979
- #: (Entry::Method entry, String call_string) -> void
980
- def refute_signature_matches(entry, call_string)
981
- sig = entry.signatures.first #: as !nil
982
- arguments = parse_prism_args(call_string)
983
- refute(sig.matches?(arguments), "Expected #{call_string} to not match #{entry.name}#{entry.decorated_parameters}")
984
- end
985
-
986
- def parse_prism_args(s)
987
- Array(Prism.parse(s).value.statements.body.first.arguments&.arguments)
988
- end
989
- end
990
- end