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,2273 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require_relative "test_case"
5
-
6
- module RubyIndexer
7
- class IndexTest < TestCase
8
- def test_deleting_one_entry_for_a_class
9
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
10
- class Foo
11
- end
12
- RUBY
13
- @index.index_single(URI::Generic.from_path(path: "/fake/path/other_foo.rb"), <<~RUBY)
14
- class Foo
15
- end
16
- RUBY
17
-
18
- entries = @index["Foo"] #: as !nil
19
- assert_equal(2, entries.length)
20
-
21
- @index.delete(URI::Generic.from_path(path: "/fake/path/other_foo.rb"))
22
- entries = @index["Foo"] #: as !nil
23
- assert_equal(1, entries.length)
24
- end
25
-
26
- def test_deleting_all_entries_for_a_class
27
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
28
- class Foo
29
- end
30
- RUBY
31
-
32
- entries = @index["Foo"] #: as !nil
33
- assert_equal(1, entries.length)
34
-
35
- @index.delete(URI::Generic.from_path(path: "/fake/path/foo.rb"))
36
- entries = @index["Foo"]
37
- assert_nil(entries)
38
- end
39
-
40
- def test_index_resolve
41
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
42
- class Bar; end
43
-
44
- module Foo
45
- class Bar
46
- end
47
-
48
- class Baz
49
- class Something
50
- end
51
- end
52
- end
53
- RUBY
54
-
55
- entries = @index.resolve("Something", ["Foo", "Baz"]) #: as !nil
56
- refute_empty(entries)
57
- assert_equal("Foo::Baz::Something", entries.first&.name)
58
-
59
- entries = @index.resolve("Bar", ["Foo"]) #: as !nil
60
- refute_empty(entries)
61
- assert_equal("Foo::Bar", entries.first&.name)
62
-
63
- entries = @index.resolve("Bar", ["Foo", "Baz"]) #: as !nil
64
- refute_empty(entries)
65
- assert_equal("Foo::Bar", entries.first&.name)
66
-
67
- entries = @index.resolve("Foo::Bar", ["Foo", "Baz"]) #: as !nil
68
- refute_empty(entries)
69
- assert_equal("Foo::Bar", entries.first&.name)
70
-
71
- assert_nil(@index.resolve("DoesNotExist", ["Foo"]))
72
- end
73
-
74
- def test_accessing_with_colon_colon_prefix
75
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
76
- class Bar; end
77
-
78
- module Foo
79
- class Bar
80
- end
81
-
82
- class Baz
83
- class Something
84
- end
85
- end
86
- end
87
- RUBY
88
-
89
- entries = @index["::Foo::Baz::Something"] #: as !nil
90
- refute_empty(entries)
91
- assert_equal("Foo::Baz::Something", entries.first&.name)
92
- end
93
-
94
- def test_fuzzy_search
95
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
96
- class Zws; end
97
-
98
- module Qtl
99
- class Zws
100
- end
101
-
102
- class Zwo
103
- class Something
104
- end
105
- end
106
- end
107
- RUBY
108
-
109
- result = @index.fuzzy_search("Zws")
110
- assert_equal(["Zws", "Qtl::Zwo::Something"], result.map(&:name))
111
-
112
- result = @index.fuzzy_search("qtlzwssomeking")
113
- assert_equal(["Qtl::Zwo::Something", "Qtl::Zws", "Qtl::Zwo", "Qtl", "Zws", "blocking"], result.map(&:name))
114
-
115
- result = @index.fuzzy_search("QltZwo")
116
- assert_equal(["Qtl::Zwo", "Qtl::Zws", "Qtl::Zwo::Something", "Qtl"], result.map(&:name))
117
- end
118
-
119
- def test_index_single_ignores_directories
120
- path = "#{Dir.pwd}/lib/this_is_a_dir.rb"
121
- FileUtils.mkdir(path)
122
-
123
- begin
124
- @index.index_file(URI::Generic.from_path(path: path))
125
- ensure
126
- FileUtils.rm_r(path)
127
- end
128
- end
129
-
130
- def test_searching_for_require_paths
131
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb", load_path_entry: "/fake"), <<~RUBY)
132
- class Foo
133
- end
134
- RUBY
135
- @index.index_single(URI::Generic.from_path(path: "/fake/path/other_foo.rb", load_path_entry: "/fake"), <<~RUBY)
136
- class Foo
137
- end
138
- RUBY
139
-
140
- assert_equal(["path/other_foo", "path/foo"], @index.search_require_paths("path").map(&:require_path))
141
- end
142
-
143
- def test_searching_for_entries_based_on_prefix
144
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb", load_path_entry: "/fake"), <<~RUBY)
145
- class Foo::Bizw
146
- end
147
- RUBY
148
- @index.index_single(URI::Generic.from_path(path: "/fake/path/other_foo.rb", load_path_entry: "/fake"), <<~RUBY)
149
- class Foo::Bizw
150
- end
151
-
152
- class Foo::Bizt
153
- end
154
- RUBY
155
-
156
- results = @index.prefix_search("Foo", []).map { |entries| entries.map(&:name) }
157
- assert_equal([["Foo::Bizt"], ["Foo::Bizw", "Foo::Bizw"]], results)
158
-
159
- results = @index.prefix_search("Biz", ["Foo"]).map { |entries| entries.map(&:name) }
160
- assert_equal([["Foo::Bizt"], ["Foo::Bizw", "Foo::Bizw"]], results)
161
- end
162
-
163
- def test_resolve_normalizes_top_level_names
164
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb", load_path_entry: "/fake"), <<~RUBY)
165
- class Bar; end
166
-
167
- module Foo
168
- class Bar; end
169
- end
170
- RUBY
171
-
172
- entries = @index.resolve("::Foo::Bar", []) #: as !nil
173
- refute_nil(entries)
174
-
175
- assert_equal("Foo::Bar", entries.first&.name)
176
-
177
- entries = @index.resolve("::Bar", ["Foo"]) #: as !nil
178
- refute_nil(entries)
179
-
180
- assert_equal("Bar", entries.first&.name)
181
- end
182
-
183
- def test_resolving_aliases_to_non_existing_constants_with_conflicting_names
184
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb", load_path_entry: "/fake"), <<~RUBY)
185
- class Bar
186
- end
187
-
188
- module Foo
189
- class Bar < self
190
- BAZ = ::Bar::BAZ
191
- end
192
- end
193
- RUBY
194
-
195
- entry = @index.resolve("BAZ", ["Foo", "Bar"])&.first
196
- refute_nil(entry)
197
-
198
- assert_instance_of(Entry::UnresolvedConstantAlias, entry)
199
- end
200
-
201
- def test_visitor_does_not_visit_unnecessary_nodes
202
- concats = (0...10_000).map do |i|
203
- <<~STRING
204
- "string#{i}" \\
205
- STRING
206
- end.join
207
-
208
- index(<<~RUBY)
209
- module Foo
210
- local_var = #{concats}
211
- "final"
212
- @class_instance_var = #{concats}
213
- "final"
214
- @@class_var = #{concats}
215
- "final"
216
- $global_var = #{concats}
217
- "final"
218
- CONST = #{concats}
219
- "final"
220
- end
221
- RUBY
222
- end
223
-
224
- def test_resolve_method_with_known_receiver
225
- index(<<~RUBY)
226
- module Foo
227
- module Bar
228
- def baz; end
229
- end
230
- end
231
- RUBY
232
-
233
- entries = @index.resolve_method("baz", "Foo::Bar") #: as !nil
234
- assert_equal("baz", entries.first&.name)
235
- owner = entries.first&.owner #: as !nil
236
- assert_equal("Foo::Bar", owner.name)
237
- end
238
-
239
- def test_resolve_method_with_class_name_conflict
240
- index(<<~RUBY)
241
- class Array
242
- end
243
-
244
- class Foo
245
- def Array(*args); end
246
- end
247
- RUBY
248
-
249
- entries = @index.resolve_method("Array", "Foo") #: as !nil
250
- assert_equal("Array", entries.first&.name)
251
- owner = entries.first&.owner #: as !nil
252
- assert_equal("Foo", owner.name)
253
- end
254
-
255
- def test_resolve_method_attribute
256
- index(<<~RUBY)
257
- class Foo
258
- attr_reader :bar
259
- end
260
- RUBY
261
-
262
- entries = @index.resolve_method("bar", "Foo") #: as !nil
263
- assert_equal("bar", entries.first&.name)
264
- owner = entries.first&.owner #: as !nil
265
- assert_equal("Foo", owner.name)
266
- end
267
-
268
- def test_resolve_method_with_two_definitions
269
- index(<<~RUBY)
270
- class Foo
271
- # Hello from first `bar`
272
- def bar; end
273
- end
274
-
275
- class Foo
276
- # Hello from second `bar`
277
- def bar; end
278
- end
279
- RUBY
280
-
281
- first_entry, second_entry = @index.resolve_method("bar", "Foo") #: as !nil
282
-
283
- assert_equal("bar", first_entry&.name)
284
- owner = first_entry&.owner #: as !nil
285
- assert_equal("Foo", owner.name)
286
- assert_includes(first_entry&.comments, "Hello from first `bar`")
287
-
288
- assert_equal("bar", second_entry&.name)
289
- owner = second_entry&.owner #: as !nil
290
- assert_equal("Foo", owner.name)
291
- assert_includes(second_entry&.comments, "Hello from second `bar`")
292
- end
293
-
294
- def test_resolve_method_inherited_only
295
- index(<<~RUBY)
296
- class Bar
297
- def baz; end
298
- end
299
-
300
- class Foo < Bar
301
- def baz; end
302
- end
303
- RUBY
304
-
305
- entry = @index.resolve_method("baz", "Foo", inherited_only: true)&.first #: as !nil
306
- assert_equal("Bar", entry.owner&.name)
307
- end
308
-
309
- def test_resolve_method_inherited_only_for_prepended_module
310
- index(<<~RUBY)
311
- module Bar
312
- def baz
313
- super
314
- end
315
- end
316
-
317
- class Foo
318
- prepend Bar
319
-
320
- def baz; end
321
- end
322
- RUBY
323
-
324
- # This test is just to document the fact that we don't yet support resolving inherited methods for modules that
325
- # are prepended. The only way to support this is to find all namespaces that have the module a subtype, so that we
326
- # can show the results for everywhere the module has been prepended.
327
- assert_nil(@index.resolve_method("baz", "Bar", inherited_only: true))
328
- end
329
-
330
- def test_prefix_search_for_methods
331
- index(<<~RUBY)
332
- module Foo
333
- module Bar
334
- def qzx; end
335
- end
336
- end
337
- RUBY
338
-
339
- entries = @index.prefix_search("qz")
340
- refute_empty(entries)
341
-
342
- entry = entries.first&.first #: as !nil
343
- assert_equal("qzx", entry.name)
344
- end
345
-
346
- def test_indexing_prism_fixtures_succeeds
347
- unless Dir.exist?("test/fixtures/prism/test/prism/fixtures")
348
- raise "Prism fixtures not found. Run `git submodule update --init` to fetch them."
349
- end
350
-
351
- fixtures = Dir.glob("#{Dir.pwd}/test/fixtures/prism/test/prism/fixtures/**/*.txt")
352
-
353
- fixtures.each do |fixture|
354
- uri = URI::Generic.from_path(path: fixture)
355
- @index.index_file(uri)
356
- end
357
-
358
- refute_empty(@index)
359
- end
360
-
361
- def test_index_single_does_not_fail_for_non_existing_file
362
- @index.index_file(URI::Generic.from_path(path: "/fake/path/foo.rb"))
363
- entries_after_indexing = @index.names
364
- assert_equal(@default_indexed_entries.keys, entries_after_indexing)
365
- end
366
-
367
- def test_linearized_ancestors_basic_ordering
368
- index(<<~RUBY)
369
- module A; end
370
- module B; end
371
-
372
- class Foo
373
- prepend A
374
- prepend B
375
- end
376
-
377
- class Bar
378
- include A
379
- include B
380
- end
381
- RUBY
382
-
383
- assert_equal(
384
- [
385
- "B",
386
- "A",
387
- "Foo",
388
- "Object",
389
- "Kernel",
390
- "BasicObject",
391
- ],
392
- @index.linearized_ancestors_of("Foo"),
393
- )
394
-
395
- assert_equal(
396
- [
397
- "Bar",
398
- "B",
399
- "A",
400
- "Object",
401
- "Kernel",
402
- "BasicObject",
403
- ],
404
- @index.linearized_ancestors_of("Bar"),
405
- )
406
- end
407
-
408
- def test_linearized_ancestors
409
- index(<<~RUBY)
410
- module A; end
411
- module B; end
412
- module C; end
413
-
414
- module D
415
- include A
416
- end
417
-
418
- module E
419
- prepend B
420
- end
421
-
422
- module F
423
- include C
424
- include A
425
- end
426
-
427
- class Bar
428
- prepend F
429
- end
430
-
431
- class Foo < Bar
432
- include E
433
- prepend D
434
- end
435
- RUBY
436
-
437
- # Object, Kernel and BasicObject are intentionally commented out for now until we develop a strategy for indexing
438
- # declarations made in C code
439
- assert_equal(
440
- [
441
- "D",
442
- "A",
443
- "Foo",
444
- "B",
445
- "E",
446
- "F",
447
- "A",
448
- "C",
449
- "Bar",
450
- "Object",
451
- "Kernel",
452
- "BasicObject",
453
- ],
454
- @index.linearized_ancestors_of("Foo"),
455
- )
456
- end
457
-
458
- def test_linearized_ancestors_duplicates
459
- index(<<~RUBY)
460
- module A; end
461
- module B
462
- include A
463
- end
464
-
465
- class Foo
466
- include B
467
- include A
468
- end
469
-
470
- class Bar
471
- prepend B
472
- prepend A
473
- end
474
- RUBY
475
-
476
- assert_equal(
477
- [
478
- "Foo",
479
- "B",
480
- "A",
481
- "Object",
482
- "Kernel",
483
- "BasicObject",
484
- ],
485
- @index.linearized_ancestors_of("Foo"),
486
- )
487
-
488
- assert_equal(
489
- [
490
- "B",
491
- "A",
492
- "Bar",
493
- "Object",
494
- "Kernel",
495
- "BasicObject",
496
- ],
497
- @index.linearized_ancestors_of("Bar"),
498
- )
499
- end
500
-
501
- def test_linearizing_ancestors_is_cached
502
- index(<<~RUBY)
503
- module C; end
504
- module A; end
505
- module B
506
- include A
507
- end
508
-
509
- class Foo
510
- include B
511
- include A
512
- end
513
- RUBY
514
-
515
- @index.linearized_ancestors_of("Foo")
516
- ancestors = @index.instance_variable_get(:@ancestors)
517
- assert(ancestors.key?("Foo"))
518
- assert(ancestors.key?("A"))
519
- assert(ancestors.key?("B"))
520
- refute(ancestors.key?("C"))
521
- end
522
-
523
- def test_duplicate_prepend_include
524
- index(<<~RUBY)
525
- module A; end
526
-
527
- class Foo
528
- prepend A
529
- include A
530
- end
531
-
532
- class Bar
533
- include A
534
- prepend A
535
- end
536
- RUBY
537
-
538
- assert_equal(
539
- [
540
- "A",
541
- "Foo",
542
- "Object",
543
- "Kernel",
544
- "BasicObject",
545
- ],
546
- @index.linearized_ancestors_of("Foo"),
547
- )
548
-
549
- assert_equal(
550
- [
551
- "A",
552
- "Bar",
553
- "A",
554
- "Object",
555
- "Kernel",
556
- "BasicObject",
557
- ],
558
- @index.linearized_ancestors_of("Bar"),
559
- )
560
- end
561
-
562
- def test_linearizing_ancestors_handles_circular_parent_class
563
- index(<<~RUBY)
564
- class Foo < Foo
565
- end
566
- RUBY
567
-
568
- assert_equal(["Foo"], @index.linearized_ancestors_of("Foo"))
569
- end
570
-
571
- def test_ancestors_linearization_complex_prepend_duplication
572
- index(<<~RUBY)
573
- module A; end
574
- module B
575
- prepend A
576
- end
577
- module C
578
- prepend B
579
- end
580
-
581
- class Foo
582
- prepend A
583
- prepend C
584
- end
585
- RUBY
586
-
587
- assert_equal(
588
- [
589
- "A",
590
- "B",
591
- "C",
592
- "Foo",
593
- "Object",
594
- "Kernel",
595
- "BasicObject",
596
- ],
597
- @index.linearized_ancestors_of("Foo"),
598
- )
599
- end
600
-
601
- def test_ancestors_linearization_complex_include_duplication
602
- index(<<~RUBY)
603
- module A; end
604
- module B
605
- include A
606
- end
607
- module C
608
- include B
609
- end
610
-
611
- class Foo
612
- include A
613
- include C
614
- end
615
- RUBY
616
-
617
- assert_equal(
618
- [
619
- "Foo",
620
- "C",
621
- "B",
622
- "A",
623
- "Object",
624
- "Kernel",
625
- "BasicObject",
626
- ],
627
- @index.linearized_ancestors_of("Foo"),
628
- )
629
- end
630
-
631
- def test_linearizing_ancestors_that_need_to_be_resolved
632
- index(<<~RUBY)
633
- module Foo
634
- module Baz
635
- end
636
- module Qux
637
- end
638
-
639
- class Something; end
640
-
641
- class Bar < Something
642
- include Baz
643
- prepend Qux
644
- end
645
- end
646
- RUBY
647
-
648
- assert_equal(
649
- [
650
- "Foo::Qux",
651
- "Foo::Bar",
652
- "Foo::Baz",
653
- "Foo::Something",
654
- "Object",
655
- "Kernel",
656
- "BasicObject",
657
- ],
658
- @index.linearized_ancestors_of("Foo::Bar"),
659
- )
660
- end
661
-
662
- def test_linearizing_ancestors_for_non_existing_namespaces
663
- index(<<~RUBY)
664
- def Bar(a); end
665
- RUBY
666
-
667
- assert_raises(Index::NonExistingNamespaceError) do
668
- @index.linearized_ancestors_of("Foo")
669
- end
670
-
671
- assert_raises(Index::NonExistingNamespaceError) do
672
- @index.linearized_ancestors_of("Bar")
673
- end
674
- end
675
-
676
- def test_linearizing_circular_ancestors
677
- index(<<~RUBY)
678
- module M1
679
- include M2
680
- end
681
-
682
- module M2
683
- include M1
684
- end
685
-
686
- module A1
687
- include A2
688
- end
689
-
690
- module A2
691
- include A3
692
- end
693
-
694
- module A3
695
- include A1
696
- end
697
-
698
- class Foo < Foo
699
- include Foo
700
- end
701
-
702
- module Bar
703
- include Bar
704
- end
705
- RUBY
706
-
707
- assert_equal(["M2", "M1"], @index.linearized_ancestors_of("M2"))
708
- assert_equal(["A3", "A1", "A2"], @index.linearized_ancestors_of("A3"))
709
- assert_equal(["Foo"], @index.linearized_ancestors_of("Foo"))
710
- assert_equal(["Bar"], @index.linearized_ancestors_of("Bar"))
711
- end
712
-
713
- def test_linearizing_circular_aliased_dependency
714
- index(<<~RUBY)
715
- module A
716
- end
717
-
718
- ALIAS = A
719
-
720
- module A
721
- include ALIAS
722
- end
723
- RUBY
724
-
725
- assert_equal(["A", "ALIAS"], @index.linearized_ancestors_of("A"))
726
- end
727
-
728
- def test_linearizing_ancestors_for_classes_with_overridden_parents
729
- index(<<~RUBY)
730
- # Find the re-open of a class first, without specifying a parent
731
- class Child
732
- end
733
-
734
- # Now, find the actual definition of the class, which includes a parent
735
- class Parent; end
736
- class Child < Parent
737
- end
738
- RUBY
739
-
740
- assert_equal(
741
- [
742
- "Child",
743
- "Parent",
744
- "Object",
745
- "Kernel",
746
- "BasicObject",
747
- ],
748
- @index.linearized_ancestors_of("Child"),
749
- )
750
- end
751
-
752
- def test_resolving_an_inherited_method
753
- index(<<~RUBY)
754
- module Foo
755
- def baz; end
756
- end
757
-
758
- class Bar
759
- def qux; end
760
- end
761
-
762
- class Wow < Bar
763
- include Foo
764
- end
765
- RUBY
766
-
767
- entry = @index.resolve_method("baz", "Wow")&.first #: as !nil
768
- assert_equal("baz", entry.name)
769
- assert_equal("Foo", entry.owner&.name)
770
-
771
- entry = @index.resolve_method("qux", "Wow")&.first #: as !nil
772
- assert_equal("qux", entry.name)
773
- assert_equal("Bar", entry.owner&.name)
774
- end
775
-
776
- def test_resolving_an_inherited_method_lands_on_first_match
777
- index(<<~RUBY)
778
- module Foo
779
- def qux; end
780
- end
781
-
782
- class Bar
783
- def qux; end
784
- end
785
-
786
- class Wow < Bar
787
- prepend Foo
788
-
789
- def qux; end
790
- end
791
- RUBY
792
-
793
- entries = @index.resolve_method("qux", "Wow") #: as !nil
794
- assert_equal(1, entries.length)
795
-
796
- entry = entries.first #: as !nil
797
- assert_equal("qux", entry.name)
798
- assert_equal("Foo", entry.owner&.name)
799
- end
800
-
801
- def test_handle_change_clears_ancestor_cache_if_tree_changed
802
- Dir.mktmpdir do |dir|
803
- Dir.chdir(dir) do
804
- # Write the original file
805
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
806
- module Foo
807
- end
808
-
809
- class Bar
810
- include Foo
811
- end
812
- RUBY
813
-
814
- uri = URI::Generic.from_path(path: File.join(dir, "foo.rb"))
815
- @index.index_file(uri)
816
-
817
- assert_equal(["Bar", "Foo", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
818
-
819
- # Remove include to invalidate the ancestor tree
820
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
821
- module Foo
822
- end
823
-
824
- class Bar
825
- end
826
- RUBY
827
-
828
- path = uri.full_path #: as !nil
829
- @index.handle_change(uri, File.read(path))
830
- assert_empty(@index.instance_variable_get(:@ancestors))
831
- assert_equal(["Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
832
- end
833
- end
834
- end
835
-
836
- def test_handle_change_does_not_clear_ancestor_cache_if_tree_not_changed
837
- Dir.mktmpdir do |dir|
838
- Dir.chdir(dir) do
839
- # Write the original file
840
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
841
- module Foo
842
- end
843
-
844
- class Bar
845
- include Foo
846
- end
847
- RUBY
848
-
849
- uri = URI::Generic.from_path(path: File.join(dir, "foo.rb"))
850
- @index.index_file(uri)
851
-
852
- assert_equal(["Bar", "Foo", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
853
-
854
- # Remove include to invalidate the ancestor tree
855
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
856
- module Foo
857
- end
858
-
859
- class Bar
860
- include Foo
861
-
862
- def baz; end
863
- end
864
- RUBY
865
-
866
- path = uri.full_path #: as !nil
867
- @index.handle_change(uri, File.read(path))
868
- refute_empty(@index.instance_variable_get(:@ancestors))
869
- assert_equal(["Bar", "Foo", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
870
- end
871
- end
872
- end
873
-
874
- def test_handle_change_clears_ancestor_cache_if_parent_class_changed
875
- Dir.mktmpdir do |dir|
876
- Dir.chdir(dir) do
877
- # Write the original file
878
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
879
- class Foo
880
- end
881
-
882
- class Bar < Foo
883
- end
884
- RUBY
885
-
886
- uri = URI::Generic.from_path(path: File.join(dir, "foo.rb"))
887
- @index.index_file(uri)
888
-
889
- assert_equal(["Bar", "Foo", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
890
-
891
- # Remove include to invalidate the ancestor tree
892
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
893
- class Foo
894
- end
895
-
896
- class Bar
897
- end
898
- RUBY
899
-
900
- path = uri.full_path #: as !nil
901
- @index.handle_change(uri, File.read(path))
902
- assert_empty(@index.instance_variable_get(:@ancestors))
903
- assert_equal(["Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
904
- end
905
- end
906
- end
907
-
908
- def test_resolving_inherited_constants
909
- index(<<~RUBY)
910
- module Foo
911
- CONST = 1
912
- end
913
-
914
- module Baz
915
- CONST = 2
916
- end
917
-
918
- module Qux
919
- include Foo
920
- end
921
-
922
- module Namespace
923
- CONST = 3
924
-
925
- include Baz
926
-
927
- class Bar
928
- include Qux
929
- end
930
- end
931
-
932
- CONST = 4
933
- RUBY
934
-
935
- entry = @index.resolve("CONST", ["Namespace", "Bar"])&.first #: as !nil
936
- assert_equal(14, entry.location.start_line)
937
- end
938
-
939
- def test_resolving_inherited_aliased_namespace
940
- index(<<~RUBY)
941
- module Bar
942
- TARGET = 123
943
- end
944
-
945
- module Foo
946
- CONST = Bar
947
- end
948
-
949
- module Namespace
950
- class Bar
951
- include Foo
952
- end
953
- end
954
- RUBY
955
-
956
- entry = @index.resolve("Foo::CONST::TARGET", [])&.first #: as !nil
957
- assert_equal(2, entry.location.start_line)
958
-
959
- entry = @index.resolve("Namespace::Bar::CONST::TARGET", [])&.first #: as !nil
960
- assert_equal(2, entry.location.start_line)
961
- end
962
-
963
- def test_resolving_same_constant_from_different_scopes
964
- index(<<~RUBY)
965
- module Namespace
966
- CONST = 123
967
-
968
- class Parent
969
- CONST = 321
970
- end
971
-
972
- class Child < Parent
973
- end
974
- end
975
- RUBY
976
-
977
- entry = @index.resolve("CONST", ["Namespace", "Child"])&.first #: as !nil
978
- assert_equal(2, entry.location.start_line)
979
-
980
- entry = @index.resolve("Namespace::Child::CONST", [])&.first #: as !nil
981
- assert_equal(5, entry.location.start_line)
982
- end
983
-
984
- def test_resolving_prepended_constants
985
- index(<<~RUBY)
986
- module Included
987
- CONST = 123
988
- end
989
-
990
- module Prepended
991
- CONST = 321
992
- end
993
-
994
- class Foo
995
- include Included
996
- prepend Prepended
997
- end
998
-
999
- class Bar
1000
- CONST = 456
1001
- include Included
1002
- prepend Prepended
1003
- end
1004
- RUBY
1005
-
1006
- entry = @index.resolve("CONST", ["Foo"])&.first #: as !nil
1007
- assert_equal(6, entry.location.start_line)
1008
-
1009
- entry = @index.resolve("Foo::CONST", [])&.first #: as !nil
1010
- assert_equal(6, entry.location.start_line)
1011
-
1012
- entry = @index.resolve("Bar::CONST", [])&.first #: as !nil
1013
- assert_equal(15, entry.location.start_line)
1014
- end
1015
-
1016
- def test_resolving_constants_favors_ancestors_over_top_level
1017
- index(<<~RUBY)
1018
- module Value1
1019
- CONST = 1
1020
- end
1021
-
1022
- module Value2
1023
- CONST = 2
1024
- end
1025
-
1026
- CONST = 3
1027
- module First
1028
- include Value1
1029
-
1030
- module Second
1031
- include Value2
1032
- end
1033
- end
1034
- RUBY
1035
-
1036
- entry = @index.resolve("CONST", ["First", "Second"])&.first #: as !nil
1037
- assert_equal(6, entry.location.start_line)
1038
- end
1039
-
1040
- def test_resolving_circular_alias
1041
- index(<<~RUBY)
1042
- module Namespace
1043
- FOO = BAR
1044
- BAR = FOO
1045
- end
1046
- RUBY
1047
-
1048
- foo_entry = @index.resolve("FOO", ["Namespace"])&.first #: as !nil
1049
- assert_equal(2, foo_entry.location.start_line)
1050
- assert_instance_of(Entry::ConstantAlias, foo_entry)
1051
-
1052
- bar_entry = @index.resolve("BAR", ["Namespace"])&.first #: as !nil
1053
- assert_equal(3, bar_entry.location.start_line)
1054
- assert_instance_of(Entry::ConstantAlias, bar_entry)
1055
- end
1056
-
1057
- def test_resolving_circular_alias_three_levels
1058
- index(<<~RUBY)
1059
- module Namespace
1060
- FOO = BAR
1061
- BAR = BAZ
1062
- BAZ = FOO
1063
- end
1064
- RUBY
1065
-
1066
- foo_entry = @index.resolve("FOO", ["Namespace"])&.first #: as !nil
1067
- assert_equal(2, foo_entry.location.start_line)
1068
- assert_instance_of(Entry::ConstantAlias, foo_entry)
1069
-
1070
- bar_entry = @index.resolve("BAR", ["Namespace"])&.first #: as !nil
1071
- assert_equal(3, bar_entry.location.start_line)
1072
- assert_instance_of(Entry::ConstantAlias, bar_entry)
1073
-
1074
- baz_entry = @index.resolve("BAZ", ["Namespace"])&.first #: as !nil
1075
- assert_equal(4, baz_entry.location.start_line)
1076
- assert_instance_of(Entry::ConstantAlias, baz_entry)
1077
- end
1078
-
1079
- def test_resolving_constants_in_aliased_namespace
1080
- index(<<~RUBY)
1081
- module Original
1082
- module Something
1083
- CONST = 123
1084
- end
1085
- end
1086
-
1087
- module Other
1088
- ALIAS = Original::Something
1089
- end
1090
-
1091
- module Third
1092
- Other::ALIAS::CONST
1093
- end
1094
- RUBY
1095
-
1096
- entry = @index.resolve("Other::ALIAS::CONST", ["Third"])&.first #: as !nil
1097
- assert_kind_of(Entry::Constant, entry)
1098
- assert_equal("Original::Something::CONST", entry.name)
1099
- end
1100
-
1101
- def test_resolving_top_level_aliases
1102
- index(<<~RUBY)
1103
- class Foo
1104
- CONST = 123
1105
- end
1106
-
1107
- FOO = Foo
1108
- FOO::CONST
1109
- RUBY
1110
-
1111
- entry = @index.resolve("FOO::CONST", [])&.first #: as !nil
1112
- assert_kind_of(Entry::Constant, entry)
1113
- assert_equal("Foo::CONST", entry.name)
1114
- end
1115
-
1116
- def test_resolving_top_level_compact_reference
1117
- index(<<~RUBY)
1118
- class Foo::Bar
1119
- end
1120
- RUBY
1121
-
1122
- foo_entry = @index.resolve("Foo::Bar", [])&.first #: as !nil
1123
- assert_equal(1, foo_entry.location.start_line)
1124
- assert_instance_of(Entry::Class, foo_entry)
1125
- end
1126
-
1127
- def test_resolving_references_with_redundant_namespaces
1128
- index(<<~RUBY)
1129
- module Bar
1130
- CONST = 1
1131
- end
1132
-
1133
- module A
1134
- CONST = 2
1135
-
1136
- module B
1137
- CONST = 3
1138
-
1139
- class Foo
1140
- include Bar
1141
- end
1142
-
1143
- A::B::Foo::CONST
1144
- end
1145
- end
1146
- RUBY
1147
-
1148
- foo_entry = @index.resolve("A::B::Foo::CONST", ["A", "B"])&.first #: as !nil
1149
- assert_equal(2, foo_entry.location.start_line)
1150
- end
1151
-
1152
- def test_resolving_self_referential_constant_alias
1153
- index(<<~RUBY)
1154
- module A
1155
- module B
1156
- class C
1157
- end
1158
- end
1159
- end
1160
-
1161
- module A
1162
- module D
1163
- B = B::C
1164
- end
1165
- end
1166
- RUBY
1167
-
1168
- entry = @index.resolve("A::D::B", [])&.first #: as Entry::ConstantAlias
1169
-
1170
- assert_kind_of(RubyIndexer::Entry::ConstantAlias, entry)
1171
- assert_equal(10, entry.location.start_line)
1172
- assert_equal("A::B::C", entry.target)
1173
- end
1174
-
1175
- def test_resolving_non_existing_self_referential_constant_alias
1176
- index(<<~RUBY)
1177
- module Foo
1178
- SomeClass = ::SomeClass
1179
- UNRESOLVED = SomeClass::CONSTANT
1180
- end
1181
- RUBY
1182
-
1183
- entry = @index.resolve("Foo::UNRESOLVED", [])&.first #: as Entry::UnresolvedConstantAlias
1184
- assert_kind_of(Entry::UnresolvedConstantAlias, entry)
1185
- assert_equal(3, entry.location.start_line)
1186
- assert_equal("SomeClass::CONSTANT", entry.target)
1187
-
1188
- entry = @index.resolve("SomeClass::CONSTANT", ["Foo"])
1189
- refute(entry)
1190
- end
1191
-
1192
- def test_resolving_qualified_references
1193
- index(<<~RUBY)
1194
- module Namespace
1195
- class Entry
1196
- CONST = 1
1197
- end
1198
- end
1199
-
1200
- module Namespace
1201
- class Index
1202
- end
1203
- end
1204
- RUBY
1205
-
1206
- foo_entry = @index.resolve("Entry::CONST", ["Namespace", "Index"])&.first #: as !nil
1207
- assert_equal(3, foo_entry.location.start_line)
1208
- end
1209
-
1210
- def test_resolving_unqualified_references
1211
- index(<<~RUBY)
1212
- module Foo
1213
- CONST = 1
1214
- end
1215
-
1216
- module Namespace
1217
- CONST = 2
1218
-
1219
- class Index
1220
- include Foo
1221
- end
1222
- end
1223
- RUBY
1224
-
1225
- foo_entry = @index.resolve("CONST", ["Namespace", "Index"])&.first #: as !nil
1226
- assert_equal(6, foo_entry.location.start_line)
1227
- end
1228
-
1229
- def test_resolving_references_with_only_top_level_declaration
1230
- index(<<~RUBY)
1231
- CONST = 1
1232
-
1233
- module Foo; end
1234
-
1235
- module Namespace
1236
- class Index
1237
- include Foo
1238
- end
1239
- end
1240
- RUBY
1241
-
1242
- foo_entry = @index.resolve("CONST", ["Namespace", "Index"])&.first #: as !nil
1243
- assert_equal(1, foo_entry.location.start_line)
1244
- end
1245
-
1246
- def test_instance_variables_completions_from_different_owners_with_conflicting_names
1247
- index(<<~RUBY)
1248
- class Foo
1249
- def initialize
1250
- @bar = 1
1251
- end
1252
- end
1253
-
1254
- class Bar
1255
- def initialize
1256
- @bar = 2
1257
- end
1258
- end
1259
- RUBY
1260
-
1261
- entry = @index.instance_variable_completion_candidates("@", "Bar").first #: as !nil
1262
- assert_equal("@bar", entry.name)
1263
- assert_equal("Bar", entry.owner&.name)
1264
- end
1265
-
1266
- def test_resolving_a_qualified_reference
1267
- index(<<~RUBY)
1268
- class Base
1269
- module Third
1270
- CONST = 1
1271
- end
1272
- end
1273
-
1274
- class Foo
1275
- module Third
1276
- CONST = 2
1277
- end
1278
-
1279
- class Second < Base
1280
- end
1281
- end
1282
- RUBY
1283
-
1284
- foo_entry = @index.resolve("Third::CONST", ["Foo"])&.first #: as !nil
1285
- assert_equal(9, foo_entry.location.start_line)
1286
- end
1287
-
1288
- def test_resolving_unindexed_constant_with_no_nesting
1289
- assert_nil(@index.resolve("RSpec", []))
1290
- end
1291
-
1292
- def test_object_superclass_indexing_and_resolution_with_reopened_object_class
1293
- index(<<~RUBY)
1294
- class Object; end
1295
- RUBY
1296
-
1297
- entries = @index["Object"] #: as !nil
1298
- assert_equal(2, entries.length)
1299
- reopened_entry = entries.last #: as Entry::Class
1300
- assert_equal("::BasicObject", reopened_entry.parent_class)
1301
- assert_equal(["Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Object"))
1302
- end
1303
-
1304
- def test_object_superclass_indexing_and_resolution_with_reopened_basic_object_class
1305
- index(<<~RUBY)
1306
- class BasicObject; end
1307
- RUBY
1308
-
1309
- entries = @index["BasicObject"] #: as !nil
1310
- assert_equal(2, entries.length)
1311
- reopened_entry = entries.last #: as Entry::Class
1312
- assert_nil(reopened_entry.parent_class)
1313
- assert_equal(["BasicObject"], @index.linearized_ancestors_of("BasicObject"))
1314
- end
1315
-
1316
- def test_object_superclass_resolution
1317
- index(<<~RUBY)
1318
- module Foo
1319
- class Object; end
1320
-
1321
- class Bar; end
1322
- class Baz < Object; end
1323
- end
1324
- RUBY
1325
-
1326
- assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1327
- assert_equal(
1328
- ["Foo::Baz", "Foo::Object", "Object", "Kernel", "BasicObject"],
1329
- @index.linearized_ancestors_of("Foo::Baz"),
1330
- )
1331
- end
1332
-
1333
- def test_basic_object_superclass_resolution
1334
- index(<<~RUBY)
1335
- module Foo
1336
- class BasicObject; end
1337
-
1338
- class Bar; end
1339
- class Baz < BasicObject; end
1340
- end
1341
- RUBY
1342
-
1343
- assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1344
- assert_equal(
1345
- ["Foo::Baz", "Foo::BasicObject", "Object", "Kernel", "BasicObject"],
1346
- @index.linearized_ancestors_of("Foo::Baz"),
1347
- )
1348
- end
1349
-
1350
- def test_top_level_object_superclass_resolution
1351
- index(<<~RUBY)
1352
- module Foo
1353
- class Object; end
1354
-
1355
- class Bar < ::Object; end
1356
- end
1357
- RUBY
1358
-
1359
- assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1360
- end
1361
-
1362
- def test_top_level_basic_object_superclass_resolution
1363
- index(<<~RUBY)
1364
- module Foo
1365
- class BasicObject; end
1366
-
1367
- class Bar < ::BasicObject; end
1368
- end
1369
- RUBY
1370
-
1371
- assert_equal(["Foo::Bar", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1372
- end
1373
-
1374
- def test_resolving_method_inside_singleton_context
1375
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1376
- module Foo
1377
- class Bar
1378
- class << self
1379
- class Baz
1380
- class << self
1381
- def found_me!; end
1382
- end
1383
- end
1384
- end
1385
- end
1386
- end
1387
- RUBY
1388
-
1389
- entry = @index.resolve_method("found_me!", "Foo::Bar::<Class:Bar>::Baz::<Class:Baz>")&.first #: as !nil
1390
- refute_nil(entry)
1391
- assert_equal("found_me!", entry.name)
1392
- end
1393
-
1394
- def test_resolving_constants_in_singleton_contexts
1395
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1396
- module Foo
1397
- class Bar
1398
- CONST = 3
1399
-
1400
- class << self
1401
- CONST = 2
1402
-
1403
- class Baz
1404
- CONST = 1
1405
-
1406
- class << self
1407
- end
1408
- end
1409
- end
1410
- end
1411
- end
1412
- RUBY
1413
-
1414
- entry = @index.resolve("CONST", ["Foo", "Bar", "<Class:Bar>", "Baz", "<Class:Baz>"])&.first #: as !nil
1415
- refute_nil(entry)
1416
- assert_equal(9, entry.location.start_line)
1417
- end
1418
-
1419
- def test_resolving_instance_variables_in_singleton_contexts
1420
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1421
- module Foo
1422
- class Bar
1423
- @a = 123
1424
-
1425
- class << self
1426
- def hello
1427
- @b = 123
1428
- end
1429
-
1430
- @c = 123
1431
- end
1432
- end
1433
- end
1434
- RUBY
1435
-
1436
- entry = @index.resolve_instance_variable("@a", "Foo::Bar::<Class:Bar>")&.first #: as !nil
1437
- refute_nil(entry)
1438
- assert_equal("@a", entry.name)
1439
-
1440
- entry = @index.resolve_instance_variable("@b", "Foo::Bar::<Class:Bar>")&.first #: as !nil
1441
- refute_nil(entry)
1442
- assert_equal("@b", entry.name)
1443
-
1444
- entry = @index.resolve_instance_variable("@c", "Foo::Bar::<Class:Bar>::<Class:<Class:Bar>>")&.first #: as !nil
1445
- refute_nil(entry)
1446
- assert_equal("@c", entry.name)
1447
- end
1448
-
1449
- def test_instance_variable_completion_in_singleton_contexts
1450
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1451
- module Foo
1452
- class Bar
1453
- @a = 123
1454
-
1455
- class << self
1456
- def hello
1457
- @b = 123
1458
- end
1459
-
1460
- @c = 123
1461
- end
1462
- end
1463
- end
1464
- RUBY
1465
-
1466
- entries = @index.instance_variable_completion_candidates("@", "Foo::Bar::<Class:Bar>").map(&:name)
1467
- assert_includes(entries, "@a")
1468
- assert_includes(entries, "@b")
1469
- end
1470
-
1471
- def test_singletons_are_excluded_from_prefix_search
1472
- index(<<~RUBY)
1473
- class Zwq
1474
- class << self
1475
- end
1476
- end
1477
- RUBY
1478
-
1479
- assert_empty(@index.prefix_search("Zwq::<C"))
1480
- end
1481
-
1482
- def test_singletons_are_excluded_from_fuzzy_search
1483
- index(<<~RUBY)
1484
- class Zwq
1485
- class << self
1486
- end
1487
- end
1488
- RUBY
1489
-
1490
- results = @index.fuzzy_search("Zwq")
1491
- assert_equal(1, results.length)
1492
- assert_equal("Zwq", results.first&.name)
1493
- end
1494
-
1495
- def test_resolving_method_aliases
1496
- index(<<~RUBY)
1497
- class Foo
1498
- def bar(a, b, c)
1499
- end
1500
-
1501
- alias double_alias bar
1502
- end
1503
-
1504
- class Bar < Foo
1505
- def hello(b); end
1506
-
1507
- alias baz bar
1508
- alias_method :qux, :hello
1509
- alias double double_alias
1510
- end
1511
- RUBY
1512
-
1513
- # baz
1514
- methods = @index.resolve_method("baz", "Bar") #: as !nil
1515
- refute_nil(methods)
1516
-
1517
- entry = methods.first #: as Entry::MethodAlias
1518
- assert_kind_of(Entry::MethodAlias, entry)
1519
- assert_equal("bar", entry.target.name)
1520
- assert_equal("Foo", entry.target.owner&.name)
1521
-
1522
- # qux
1523
- methods = @index.resolve_method("qux", "Bar") #: as !nil
1524
- refute_nil(methods)
1525
-
1526
- entry = methods.first #: as Entry::MethodAlias
1527
- assert_kind_of(Entry::MethodAlias, entry)
1528
- assert_equal("hello", entry.target.name)
1529
- assert_equal("Bar", entry.target.owner&.name)
1530
-
1531
- # double
1532
- methods = @index.resolve_method("double", "Bar") #: as !nil
1533
- refute_nil(methods)
1534
-
1535
- entry = methods.first #: as Entry::MethodAlias
1536
- assert_kind_of(Entry::MethodAlias, entry)
1537
-
1538
- target = entry.target #: as Entry::MethodAlias
1539
- assert_equal("double_alias", target.name)
1540
- assert_kind_of(Entry::MethodAlias, target)
1541
- assert_equal("Foo", target.owner&.name)
1542
-
1543
- final_target = target.target
1544
- assert_equal("bar", final_target.name)
1545
- assert_kind_of(Entry::Method, final_target)
1546
- assert_equal("Foo", final_target.owner&.name)
1547
- end
1548
-
1549
- def test_resolving_circular_method_aliases
1550
- index(<<~RUBY)
1551
- class Foo
1552
- alias bar bar
1553
- end
1554
- RUBY
1555
-
1556
- # It's not possible to resolve an alias that points to itself
1557
- methods = @index.resolve_method("bar", "Foo")
1558
- assert_nil(methods)
1559
-
1560
- entry = @index["bar"]&.first
1561
- assert_kind_of(Entry::UnresolvedMethodAlias, entry)
1562
- end
1563
-
1564
- def test_unresolvable_method_aliases
1565
- index(<<~RUBY)
1566
- class Foo
1567
- alias bar baz
1568
- end
1569
- RUBY
1570
-
1571
- # `baz` does not exist, so resolving `bar` is not possible
1572
- methods = @index.resolve_method("bar", "Foo")
1573
- assert_nil(methods)
1574
-
1575
- entry = @index["bar"]&.first
1576
- assert_kind_of(Entry::UnresolvedMethodAlias, entry)
1577
- end
1578
-
1579
- def test_only_aliases_for_the_right_owner_are_resolved
1580
- index(<<~RUBY)
1581
- class Foo
1582
- attr_reader :name
1583
- alias_method :decorated_name, :name
1584
- end
1585
-
1586
- class Bar
1587
- alias_method :decorated_name, :to_s
1588
- end
1589
- RUBY
1590
-
1591
- methods = @index.resolve_method("decorated_name", "Foo") #: as !nil
1592
- refute_nil(methods)
1593
-
1594
- entry = methods.first #: as Entry::MethodAlias
1595
- assert_kind_of(Entry::MethodAlias, entry)
1596
-
1597
- target = entry.target
1598
- assert_equal("name", target.name)
1599
- assert_kind_of(Entry::Accessor, target)
1600
- assert_equal("Foo", target.owner&.name)
1601
-
1602
- other_decorated_name = @index["decorated_name"]&.find { |e| e.is_a?(Entry::UnresolvedMethodAlias) }
1603
- assert_kind_of(Entry::UnresolvedMethodAlias, other_decorated_name)
1604
- end
1605
-
1606
- def test_completion_does_not_include_unresolved_aliases
1607
- index(<<~RUBY)
1608
- class Foo
1609
- alias_method :bar, :missing
1610
- end
1611
- RUBY
1612
-
1613
- assert_empty(@index.method_completion_candidates("bar", "Foo"))
1614
- end
1615
-
1616
- def test_first_unqualified_const
1617
- index(<<~RUBY)
1618
- module Foo
1619
- class Bar; end
1620
- end
1621
-
1622
- module Baz
1623
- class Bar; end
1624
- end
1625
- RUBY
1626
-
1627
- entry = @index.first_unqualified_const("Bar")&.first #: as !nil
1628
- assert_equal("Foo::Bar", entry.name)
1629
- end
1630
-
1631
- def test_first_unqualified_const_prefers_exact_matches
1632
- index(<<~RUBY)
1633
- module Foo
1634
- class ParseResultType
1635
- end
1636
- end
1637
-
1638
- module Namespace
1639
- class Type
1640
- end
1641
- end
1642
- RUBY
1643
-
1644
- entry = @index.first_unqualified_const("Type")&.first #: as !nil
1645
- assert_equal("Namespace::Type", entry.name)
1646
- end
1647
-
1648
- def test_completion_does_not_duplicate_overridden_methods
1649
- index(<<~RUBY)
1650
- class Foo
1651
- def bar; end
1652
- end
1653
-
1654
- class Baz < Foo
1655
- def bar; end
1656
- end
1657
- RUBY
1658
-
1659
- entries = @index.method_completion_candidates("bar", "Baz")
1660
- assert_equal(["bar"], entries.map(&:name))
1661
- assert_equal("Baz", entries.first&.owner&.name)
1662
- end
1663
-
1664
- def test_completion_does_not_duplicate_methods_overridden_by_aliases
1665
- index(<<~RUBY)
1666
- class Foo
1667
- def bar; end
1668
- end
1669
-
1670
- class Baz < Foo
1671
- alias bar to_s
1672
- end
1673
- RUBY
1674
-
1675
- entries = @index.method_completion_candidates("bar", "Baz")
1676
- assert_equal(["bar"], entries.map(&:name))
1677
- assert_equal("Baz", entries.first&.owner&.name)
1678
- end
1679
-
1680
- def test_decorated_parameters
1681
- index(<<~RUBY)
1682
- class Foo
1683
- def bar(a, b = 1, c: 2)
1684
- end
1685
- end
1686
- RUBY
1687
-
1688
- methods = @index.resolve_method("bar", "Foo") #: as !nil
1689
- refute_nil(methods)
1690
-
1691
- entry = methods.first #: as Entry::Method
1692
- assert_equal("(a, b = <default>, c: <default>)", entry.decorated_parameters)
1693
- end
1694
-
1695
- def test_decorated_parameters_when_method_has_no_parameters
1696
- index(<<~RUBY)
1697
- class Foo
1698
- def bar
1699
- end
1700
- end
1701
- RUBY
1702
-
1703
- methods = @index.resolve_method("bar", "Foo") #: as !nil
1704
- refute_nil(methods)
1705
-
1706
- entry = methods.first #: as Entry::Method
1707
- assert_equal("()", entry.decorated_parameters)
1708
- end
1709
-
1710
- def test_linearizing_singleton_ancestors_of_singleton_when_class_has_parent
1711
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1712
- class Foo; end
1713
-
1714
- class Bar < Foo
1715
- end
1716
-
1717
- class Baz < Bar
1718
- class << self
1719
- class << self
1720
- end
1721
- end
1722
- end
1723
- RUBY
1724
-
1725
- assert_equal(
1726
- [
1727
- "Baz::<Class:Baz>::<Class:<Class:Baz>>",
1728
- "Bar::<Class:Bar>::<Class:<Class:Bar>>",
1729
- "Foo::<Class:Foo>::<Class:<Class:Foo>>",
1730
- "Object::<Class:Object>::<Class:<Class:Object>>",
1731
- "BasicObject::<Class:BasicObject>::<Class:<Class:BasicObject>>",
1732
- "Class::<Class:Class>",
1733
- "Module::<Class:Module>",
1734
- "Object::<Class:Object>",
1735
- "BasicObject::<Class:BasicObject>",
1736
- "Class",
1737
- "Module",
1738
- "Object",
1739
- "Kernel",
1740
- "BasicObject",
1741
- ],
1742
- @index.linearized_ancestors_of("Baz::<Class:Baz>::<Class:<Class:Baz>>"),
1743
- )
1744
- end
1745
-
1746
- def test_linearizing_singleton_object
1747
- assert_equal(
1748
- [
1749
- "Object::<Class:Object>",
1750
- "BasicObject::<Class:BasicObject>",
1751
- "Class",
1752
- "Module",
1753
- "Object",
1754
- "Kernel",
1755
- "BasicObject",
1756
- ],
1757
- @index.linearized_ancestors_of("Object::<Class:Object>"),
1758
- )
1759
- end
1760
-
1761
- def test_extend_self
1762
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1763
- module Foo
1764
- def bar
1765
- end
1766
-
1767
- extend self
1768
-
1769
- def baz
1770
- end
1771
- end
1772
- RUBY
1773
-
1774
- ["bar", "baz"].product(["Foo", "Foo::<Class:Foo>"]).each do |method, receiver|
1775
- entry = @index.resolve_method(method, receiver)&.first #: as !nil
1776
- refute_nil(entry)
1777
- assert_equal(method, entry.name)
1778
- end
1779
-
1780
- assert_equal(
1781
- [
1782
- "Foo::<Class:Foo>",
1783
- "Foo",
1784
- "Module",
1785
- "Object",
1786
- "Kernel",
1787
- "BasicObject",
1788
- ],
1789
- @index.linearized_ancestors_of("Foo::<Class:Foo>"),
1790
- )
1791
- end
1792
-
1793
- def test_linearizing_singleton_ancestors
1794
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1795
- module First
1796
- end
1797
-
1798
- module Second
1799
- include First
1800
- end
1801
-
1802
- module Foo
1803
- class Bar
1804
- class << self
1805
- class Baz
1806
- extend Second
1807
-
1808
- class << self
1809
- include First
1810
- end
1811
- end
1812
- end
1813
- end
1814
- end
1815
- RUBY
1816
-
1817
- assert_equal(
1818
- [
1819
- "Foo::Bar::<Class:Bar>::Baz::<Class:Baz>",
1820
- "Second",
1821
- "First",
1822
- "Object::<Class:Object>",
1823
- "BasicObject::<Class:BasicObject>",
1824
- "Class",
1825
- "Module",
1826
- "Object",
1827
- "Kernel",
1828
- "BasicObject",
1829
- ],
1830
- @index.linearized_ancestors_of("Foo::Bar::<Class:Bar>::Baz::<Class:Baz>"),
1831
- )
1832
- end
1833
-
1834
- def test_linearizing_singleton_ancestors_when_class_has_parent
1835
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1836
- class Foo; end
1837
-
1838
- class Bar < Foo
1839
- end
1840
-
1841
- class Baz < Bar
1842
- class << self
1843
- end
1844
- end
1845
- RUBY
1846
-
1847
- assert_equal(
1848
- [
1849
- "Baz::<Class:Baz>",
1850
- "Bar::<Class:Bar>",
1851
- "Foo::<Class:Foo>",
1852
- "Object::<Class:Object>",
1853
- "BasicObject::<Class:BasicObject>",
1854
- "Class",
1855
- "Module",
1856
- "Object",
1857
- "Kernel",
1858
- "BasicObject",
1859
- ],
1860
- @index.linearized_ancestors_of("Baz::<Class:Baz>"),
1861
- )
1862
- end
1863
-
1864
- def test_linearizing_a_module_singleton_class
1865
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1866
- module A; end
1867
- RUBY
1868
-
1869
- assert_equal(
1870
- [
1871
- "A::<Class:A>",
1872
- "Module",
1873
- "Object",
1874
- "Kernel",
1875
- "BasicObject",
1876
- ],
1877
- @index.linearized_ancestors_of("A::<Class:A>"),
1878
- )
1879
- end
1880
-
1881
- def test_linearizing_a_singleton_class_with_no_attached
1882
- assert_raises(Index::NonExistingNamespaceError) do
1883
- @index.linearized_ancestors_of("A::<Class:A>")
1884
- end
1885
- end
1886
-
1887
- def test_linearizing_singleton_parent_class_with_namespace
1888
- index(<<~RUBY)
1889
- class ActiveRecord::Base; end
1890
-
1891
- class User < ActiveRecord::Base
1892
- end
1893
- RUBY
1894
-
1895
- assert_equal(
1896
- [
1897
- "User::<Class:User>",
1898
- "ActiveRecord::Base::<Class:Base>",
1899
- "Object::<Class:Object>",
1900
- "BasicObject::<Class:BasicObject>",
1901
- "Class",
1902
- "Module",
1903
- "Object",
1904
- "Kernel",
1905
- "BasicObject",
1906
- ],
1907
- @index.linearized_ancestors_of("User::<Class:User>"),
1908
- )
1909
- end
1910
-
1911
- def test_singleton_nesting_is_correctly_split_during_linearization
1912
- index(<<~RUBY)
1913
- module Bar; end
1914
-
1915
- module Foo
1916
- class Namespace::Parent
1917
- extend Bar
1918
- end
1919
- end
1920
-
1921
- module Foo
1922
- class Child < Namespace::Parent
1923
- end
1924
- end
1925
- RUBY
1926
-
1927
- assert_equal(
1928
- [
1929
- "Foo::Child::<Class:Child>",
1930
- "Foo::Namespace::Parent::<Class:Parent>",
1931
- "Bar",
1932
- "Object::<Class:Object>",
1933
- "BasicObject::<Class:BasicObject>",
1934
- "Class",
1935
- "Module",
1936
- "Object",
1937
- "Kernel",
1938
- "BasicObject",
1939
- ],
1940
- @index.linearized_ancestors_of("Foo::Child::<Class:Child>"),
1941
- )
1942
- end
1943
-
1944
- def test_resolving_circular_method_aliases_on_class_reopen
1945
- index(<<~RUBY)
1946
- class Foo
1947
- alias bar ==
1948
- def ==(other) = true
1949
- end
1950
-
1951
- class Foo
1952
- alias == bar
1953
- end
1954
- RUBY
1955
-
1956
- method = @index.resolve_method("==", "Foo")&.first #: as Entry::Method
1957
- assert_kind_of(Entry::Method, method)
1958
- assert_equal("==", method.name)
1959
-
1960
- candidates = @index.method_completion_candidates("=", "Foo")
1961
- assert_equal(["==", "==="], candidates.map(&:name))
1962
- end
1963
-
1964
- def test_entries_for
1965
- index(<<~RUBY)
1966
- class Foo; end
1967
-
1968
- module Bar
1969
- def my_def; end
1970
- def self.my_singleton_def; end
1971
- end
1972
- RUBY
1973
-
1974
- entries = @index.entries_for("file:///fake/path/foo.rb", Entry) #: as !nil
1975
- assert_equal(["Foo", "Bar", "my_def", "Bar::<Class:Bar>", "my_singleton_def"], entries.map(&:name))
1976
-
1977
- entries = @index.entries_for("file:///fake/path/foo.rb", RubyIndexer::Entry::Namespace) #: as !nil
1978
- assert_equal(["Foo", "Bar", "Bar::<Class:Bar>"], entries.map(&:name))
1979
-
1980
- entries = @index.entries_for("file:///fake/path/foo.rb") #: as !nil
1981
- assert_equal(["Foo", "Bar", "my_def", "Bar::<Class:Bar>", "my_singleton_def"], entries.map(&:name))
1982
- end
1983
-
1984
- def test_entries_for_returns_nil_if_no_matches
1985
- assert_nil(@index.entries_for("non_existing_file.rb", Entry::Namespace))
1986
- end
1987
-
1988
- def test_constant_completion_candidates_all_possible_constants
1989
- index(<<~RUBY)
1990
- XQRK = 3
1991
-
1992
- module Bar
1993
- XQRK = 2
1994
- end
1995
-
1996
- module Foo
1997
- XQRK = 1
1998
- end
1999
-
2000
- module Namespace
2001
- XQRK = 0
2002
-
2003
- class Baz
2004
- include Foo
2005
- include Bar
2006
- end
2007
- end
2008
- RUBY
2009
-
2010
- result = @index.constant_completion_candidates("X", ["Namespace", "Baz"])
2011
-
2012
- result.each do |entries|
2013
- name = entries.first&.name
2014
- assert(entries.all? { |e| e.name == name })
2015
- end
2016
-
2017
- assert_equal(["Namespace::XQRK", "Bar::XQRK", "XQRK"], result.map { |entries| entries.first&.name })
2018
-
2019
- result = @index.constant_completion_candidates("::X", ["Namespace", "Baz"])
2020
- assert_equal(["XQRK"], result.map { |entries| entries.first&.name })
2021
- end
2022
-
2023
- def test_constant_completion_does_not_confuse_uppercase_methods
2024
- index(<<~RUBY)
2025
- class Foo
2026
- def Qux
2027
- end
2028
- end
2029
- RUBY
2030
-
2031
- candidates = @index.constant_completion_candidates("Q", [])
2032
- refute_includes(candidates.flat_map { |entries| entries.map(&:name) }, "Qux")
2033
-
2034
- candidates = @index.constant_completion_candidates("Qux", [])
2035
- assert_equal(0, candidates.length)
2036
- end
2037
-
2038
- def test_constant_completion_candidates_for_empty_name
2039
- index(<<~RUBY)
2040
- module Foo
2041
- Bar = 1
2042
- end
2043
-
2044
- class Baz
2045
- include Foo
2046
- end
2047
- RUBY
2048
-
2049
- result = @index.constant_completion_candidates("Baz::", [])
2050
- assert_includes(result.map { |entries| entries.first&.name }, "Foo::Bar")
2051
- end
2052
-
2053
- def test_follow_alias_namespace
2054
- index(<<~RUBY)
2055
- module First
2056
- module Second
2057
- class Foo
2058
- end
2059
- end
2060
- end
2061
-
2062
- module Namespace
2063
- Second = First::Second
2064
- end
2065
- RUBY
2066
-
2067
- real_namespace = @index.follow_aliased_namespace("Namespace::Second")
2068
- assert_equal("First::Second", real_namespace)
2069
- end
2070
-
2071
- def test_resolving_alias_to_non_existing_namespace
2072
- index(<<~RUBY)
2073
- module Namespace
2074
- class Foo
2075
- module InnerNamespace
2076
- Constants = Namespace::Foo::Constants
2077
- end
2078
- end
2079
- end
2080
- RUBY
2081
-
2082
- entry = @index.resolve("Constants", ["Namespace", "Foo", "InnerNamespace"])&.first
2083
- assert_instance_of(Entry::UnresolvedConstantAlias, entry)
2084
-
2085
- entry = @index.resolve("Namespace::Foo::Constants", ["Namespace", "Foo", "InnerNamespace"])&.first
2086
- assert_nil(entry)
2087
- end
2088
-
2089
- def test_resolving_alias_to_existing_constant_from_inner_namespace
2090
- index(<<~RUBY)
2091
- module Parent
2092
- CONST = 123
2093
- end
2094
-
2095
- module First
2096
- module Namespace
2097
- class Foo
2098
- include Parent
2099
-
2100
- module InnerNamespace
2101
- Constants = Namespace::Foo::CONST
2102
- end
2103
- end
2104
- end
2105
- end
2106
- RUBY
2107
-
2108
- entry = @index.resolve("Namespace::Foo::CONST", ["First", "Namespace", "Foo", "InnerNamespace"])&.first #: as !nil
2109
- assert_equal("Parent::CONST", entry.name)
2110
- assert_instance_of(Entry::Constant, entry)
2111
- end
2112
-
2113
- def test_build_non_redundant_name
2114
- assert_equal(
2115
- "Namespace::Foo::Constants",
2116
- @index.send(
2117
- :build_non_redundant_full_name,
2118
- "Namespace::Foo::Constants",
2119
- ["Namespace", "Foo", "InnerNamespace"],
2120
- ),
2121
- )
2122
-
2123
- assert_equal(
2124
- "Namespace::Foo::Constants",
2125
- @index.send(
2126
- :build_non_redundant_full_name,
2127
- "Namespace::Foo::Constants",
2128
- ["Namespace", "Foo"],
2129
- ),
2130
- )
2131
-
2132
- assert_equal(
2133
- "Namespace::Foo::Constants",
2134
- @index.send(
2135
- :build_non_redundant_full_name,
2136
- "Foo::Constants",
2137
- ["Namespace", "Foo"],
2138
- ),
2139
- )
2140
-
2141
- assert_equal(
2142
- "Bar::Namespace::Foo::Constants",
2143
- @index.send(
2144
- :build_non_redundant_full_name,
2145
- "Namespace::Foo::Constants",
2146
- ["Bar"],
2147
- ),
2148
- )
2149
-
2150
- assert_equal(
2151
- "First::Namespace::Foo::Constants",
2152
- @index.send(
2153
- :build_non_redundant_full_name,
2154
- "Namespace::Foo::Constants",
2155
- ["First", "Namespace", "Foo", "InnerNamespace"],
2156
- ),
2157
- )
2158
- end
2159
-
2160
- def test_prevents_multiple_calls_to_index_all
2161
- @index.index_all
2162
-
2163
- assert_raises(Index::IndexNotEmptyError) do
2164
- @index.index_all
2165
- end
2166
- end
2167
-
2168
- def test_index_can_handle_entries_from_untitled_scheme
2169
- uri = URI("untitled:Untitled-1")
2170
-
2171
- index(<<~RUBY, uri: uri)
2172
- class Foo
2173
- end
2174
- RUBY
2175
-
2176
- entry = @index["Foo"]&.first #: as !nil
2177
- refute_nil(entry, "Expected indexer to be able to handle unsaved URIs")
2178
- assert_equal("untitled:Untitled-1", entry.uri.to_s)
2179
- assert_equal("Untitled-1", entry.file_name)
2180
- assert_nil(entry.file_path)
2181
-
2182
- @index.handle_change(uri, <<~RUBY)
2183
- # I added this comment!
2184
- class Foo
2185
- end
2186
- RUBY
2187
-
2188
- entry = @index["Foo"]&.first #: as !nil
2189
- refute_nil(entry, "Expected indexer to be able to handle unsaved URIs")
2190
- assert_equal("I added this comment!", entry.comments)
2191
- end
2192
-
2193
- def test_instance_variable_completion_returns_class_variables_too
2194
- index(<<~RUBY)
2195
- class Parent
2196
- @@abc = 123
2197
- end
2198
-
2199
- class Child < Parent
2200
- @@adf = 123
2201
-
2202
- def self.do
2203
- end
2204
- end
2205
- RUBY
2206
-
2207
- adf, abc = @index.instance_variable_completion_candidates("@", "Child::<Class:Child>")
2208
-
2209
- refute_nil(abc)
2210
- refute_nil(adf)
2211
-
2212
- assert_equal("@@abc", abc&.name)
2213
- assert_equal("@@adf", adf&.name)
2214
- end
2215
-
2216
- def test_class_variable_completion_from_singleton_context
2217
- index(<<~RUBY)
2218
- class Foo
2219
- @@hello = 123
2220
-
2221
- def self.do
2222
- end
2223
- end
2224
- RUBY
2225
-
2226
- candidates = @index.class_variable_completion_candidates("@@", "Foo::<Class:Foo>")
2227
- refute_empty(candidates)
2228
-
2229
- assert_equal("@@hello", candidates.first&.name)
2230
- end
2231
-
2232
- def test_resolve_class_variable_in_singleton_context
2233
- index(<<~RUBY)
2234
- class Foo
2235
- @@hello = 123
2236
- end
2237
- RUBY
2238
-
2239
- candidates = @index.resolve_class_variable("@@hello", "Foo::<Class:Foo>") #: as !nil
2240
- refute_empty(candidates)
2241
-
2242
- assert_equal("@@hello", candidates.first&.name)
2243
- end
2244
-
2245
- def test_actual_nesting
2246
- assert_equal(["Foo"], Index.actual_nesting([], "Foo"))
2247
- assert_equal(["TopLevel", "Foo"], Index.actual_nesting(["First", "::TopLevel"], "Foo"))
2248
- assert_equal(["TopLevel", "Another", "Foo"], Index.actual_nesting(["::TopLevel", "Another"], "Foo"))
2249
- assert_equal(["TopLevel"], Index.actual_nesting(["First", "::TopLevel"], nil))
2250
- end
2251
-
2252
- def test_constant_name
2253
- node = Prism.parse("class var::Foo; end").value.statements.body.first.constant_path
2254
- assert_nil(Index.constant_name(node))
2255
-
2256
- node = Prism.parse("class ; end").value.statements.body.first.constant_path
2257
- assert_nil(Index.constant_name(node))
2258
-
2259
- node = Prism.parse("class method_call; end").value.statements.body.first.constant_path
2260
- assert_nil(Index.constant_name(node))
2261
-
2262
- node = Prism.parse("class Foo; end").value.statements.body.first.constant_path
2263
- assert_equal("Foo", Index.constant_name(node))
2264
-
2265
- node = Prism.parse(<<~RUBY).value.statements.body.first.constant_path
2266
- class class Foo
2267
- end
2268
- end
2269
- RUBY
2270
- assert_nil(Index.constant_name(node))
2271
- end
2272
- end
2273
- end