ruby-lsp 0.16.6 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp +21 -4
- data/exe/ruby-lsp-check +1 -3
- data/exe/ruby-lsp-doctor +1 -4
- data/lib/core_ext/uri.rb +3 -0
- data/lib/ruby_indexer/lib/ruby_indexer/{collector.rb → declaration_listener.rb} +258 -140
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +101 -12
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +187 -12
- data/lib/ruby_indexer/ruby_indexer.rb +1 -1
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +106 -10
- data/lib/ruby_indexer/test/configuration_test.rb +4 -5
- data/lib/ruby_indexer/test/constant_test.rb +11 -8
- data/lib/ruby_indexer/test/index_test.rb +528 -0
- data/lib/ruby_indexer/test/instance_variables_test.rb +131 -0
- data/lib/ruby_indexer/test/method_test.rb +93 -0
- data/lib/ruby_indexer/test/test_case.rb +3 -1
- data/lib/ruby_lsp/addon.rb +8 -8
- data/lib/ruby_lsp/document.rb +3 -3
- data/lib/ruby_lsp/internal.rb +1 -0
- data/lib/ruby_lsp/listeners/code_lens.rb +11 -0
- data/lib/ruby_lsp/listeners/completion.rb +144 -51
- data/lib/ruby_lsp/listeners/definition.rb +77 -12
- data/lib/ruby_lsp/listeners/document_highlight.rb +1 -1
- data/lib/ruby_lsp/listeners/document_link.rb +1 -1
- data/lib/ruby_lsp/listeners/hover.rb +60 -6
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +59 -3
- data/lib/ruby_lsp/listeners/signature_help.rb +4 -4
- data/lib/ruby_lsp/node_context.rb +28 -0
- data/lib/ruby_lsp/requests/code_action_resolve.rb +73 -2
- data/lib/ruby_lsp/requests/code_actions.rb +16 -15
- data/lib/ruby_lsp/requests/completion.rb +22 -13
- data/lib/ruby_lsp/requests/completion_resolve.rb +26 -10
- data/lib/ruby_lsp/requests/definition.rb +21 -5
- data/lib/ruby_lsp/requests/document_highlight.rb +2 -2
- data/lib/ruby_lsp/requests/hover.rb +5 -6
- data/lib/ruby_lsp/requests/on_type_formatting.rb +8 -4
- data/lib/ruby_lsp/requests/signature_help.rb +3 -3
- data/lib/ruby_lsp/requests/support/common.rb +20 -1
- data/lib/ruby_lsp/requests/workspace_symbol.rb +3 -1
- data/lib/ruby_lsp/server.rb +10 -4
- metadata +10 -8
@@ -12,10 +12,13 @@ module RubyIndexer
|
|
12
12
|
class ::Bar
|
13
13
|
FOO = 2
|
14
14
|
end
|
15
|
+
|
16
|
+
BAR = 3 if condition
|
15
17
|
RUBY
|
16
18
|
|
17
19
|
assert_entry("FOO", Entry::Constant, "/fake/path/foo.rb:0-0:0-7")
|
18
20
|
assert_entry("Bar::FOO", Entry::Constant, "/fake/path/foo.rb:3-2:3-9")
|
21
|
+
assert_entry("BAR", Entry::Constant, "/fake/path/foo.rb:6-0:6-7")
|
19
22
|
end
|
20
23
|
|
21
24
|
def test_constant_or_writes
|
@@ -119,13 +122,13 @@ module RubyIndexer
|
|
119
122
|
RUBY
|
120
123
|
|
121
124
|
b_const = @index["A::B"].first
|
122
|
-
assert_equal(
|
125
|
+
assert_equal(Entry::Visibility::PRIVATE, b_const.visibility)
|
123
126
|
|
124
127
|
c_const = @index["A::C"].first
|
125
|
-
assert_equal(
|
128
|
+
assert_equal(Entry::Visibility::PRIVATE, c_const.visibility)
|
126
129
|
|
127
130
|
d_const = @index["A::D"].first
|
128
|
-
assert_equal(
|
131
|
+
assert_equal(Entry::Visibility::PUBLIC, d_const.visibility)
|
129
132
|
end
|
130
133
|
|
131
134
|
def test_marking_constants_as_private_reopening_namespaces
|
@@ -152,13 +155,13 @@ module RubyIndexer
|
|
152
155
|
RUBY
|
153
156
|
|
154
157
|
a_const = @index["A::B::CONST_A"].first
|
155
|
-
assert_equal(
|
158
|
+
assert_equal(Entry::Visibility::PRIVATE, a_const.visibility)
|
156
159
|
|
157
160
|
b_const = @index["A::B::CONST_B"].first
|
158
|
-
assert_equal(
|
161
|
+
assert_equal(Entry::Visibility::PRIVATE, b_const.visibility)
|
159
162
|
|
160
163
|
c_const = @index["A::B::CONST_C"].first
|
161
|
-
assert_equal(
|
164
|
+
assert_equal(Entry::Visibility::PRIVATE, c_const.visibility)
|
162
165
|
end
|
163
166
|
|
164
167
|
def test_marking_constants_as_private_with_receiver
|
@@ -176,10 +179,10 @@ module RubyIndexer
|
|
176
179
|
RUBY
|
177
180
|
|
178
181
|
a_const = @index["A::B::CONST_A"].first
|
179
|
-
assert_equal(
|
182
|
+
assert_equal(Entry::Visibility::PRIVATE, a_const.visibility)
|
180
183
|
|
181
184
|
b_const = @index["A::B::CONST_B"].first
|
182
|
-
assert_equal(
|
185
|
+
assert_equal(Entry::Visibility::PRIVATE, b_const.visibility)
|
183
186
|
end
|
184
187
|
|
185
188
|
def test_indexing_constant_aliases
|
@@ -299,6 +299,10 @@ module RubyIndexer
|
|
299
299
|
end
|
300
300
|
|
301
301
|
def test_indexing_prism_fixtures_succeeds
|
302
|
+
unless Dir.exist?("test/fixtures/prism/test/prism/fixtures")
|
303
|
+
raise "Prism fixtures not found. Run `git submodule update --init` to fetch them."
|
304
|
+
end
|
305
|
+
|
302
306
|
fixtures = Dir.glob("test/fixtures/prism/test/prism/fixtures/**/*.txt")
|
303
307
|
|
304
308
|
fixtures.each do |fixture|
|
@@ -313,5 +317,529 @@ module RubyIndexer
|
|
313
317
|
@index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"))
|
314
318
|
assert_empty(@index.instance_variable_get(:@entries))
|
315
319
|
end
|
320
|
+
|
321
|
+
def test_linearized_ancestors_basic_ordering
|
322
|
+
index(<<~RUBY)
|
323
|
+
module A; end
|
324
|
+
module B; end
|
325
|
+
|
326
|
+
class Foo
|
327
|
+
prepend A
|
328
|
+
prepend B
|
329
|
+
end
|
330
|
+
|
331
|
+
class Bar
|
332
|
+
include A
|
333
|
+
include B
|
334
|
+
end
|
335
|
+
RUBY
|
336
|
+
|
337
|
+
assert_equal(
|
338
|
+
[
|
339
|
+
"B",
|
340
|
+
"A",
|
341
|
+
"Foo",
|
342
|
+
# "Object",
|
343
|
+
# "Kernel",
|
344
|
+
# "BasicObject",
|
345
|
+
],
|
346
|
+
@index.linearized_ancestors_of("Foo"),
|
347
|
+
)
|
348
|
+
|
349
|
+
assert_equal(
|
350
|
+
[
|
351
|
+
"Bar",
|
352
|
+
"B",
|
353
|
+
"A",
|
354
|
+
# "Object",
|
355
|
+
# "Kernel",
|
356
|
+
# "BasicObject",
|
357
|
+
],
|
358
|
+
@index.linearized_ancestors_of("Bar"),
|
359
|
+
)
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_linearized_ancestors
|
363
|
+
index(<<~RUBY)
|
364
|
+
module A; end
|
365
|
+
module B; end
|
366
|
+
module C; end
|
367
|
+
|
368
|
+
module D
|
369
|
+
include A
|
370
|
+
end
|
371
|
+
|
372
|
+
module E
|
373
|
+
prepend B
|
374
|
+
end
|
375
|
+
|
376
|
+
module F
|
377
|
+
include C
|
378
|
+
include A
|
379
|
+
end
|
380
|
+
|
381
|
+
class Bar
|
382
|
+
prepend F
|
383
|
+
end
|
384
|
+
|
385
|
+
class Foo < Bar
|
386
|
+
include E
|
387
|
+
prepend D
|
388
|
+
end
|
389
|
+
RUBY
|
390
|
+
|
391
|
+
# Object, Kernel and BasicObject are intentionally commented out for now until we develop a strategy for indexing
|
392
|
+
# declarations made in C code
|
393
|
+
assert_equal(
|
394
|
+
[
|
395
|
+
"D",
|
396
|
+
"A",
|
397
|
+
"Foo",
|
398
|
+
"B",
|
399
|
+
"E",
|
400
|
+
"F",
|
401
|
+
"A",
|
402
|
+
"C",
|
403
|
+
"Bar",
|
404
|
+
# "Object",
|
405
|
+
# "Kernel",
|
406
|
+
# "BasicObject",
|
407
|
+
],
|
408
|
+
@index.linearized_ancestors_of("Foo"),
|
409
|
+
)
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_linearized_ancestors_duplicates
|
413
|
+
index(<<~RUBY)
|
414
|
+
module A; end
|
415
|
+
module B
|
416
|
+
include A
|
417
|
+
end
|
418
|
+
|
419
|
+
class Foo
|
420
|
+
include B
|
421
|
+
include A
|
422
|
+
end
|
423
|
+
|
424
|
+
class Bar
|
425
|
+
prepend B
|
426
|
+
prepend A
|
427
|
+
end
|
428
|
+
RUBY
|
429
|
+
|
430
|
+
assert_equal(
|
431
|
+
[
|
432
|
+
"Foo",
|
433
|
+
"B",
|
434
|
+
"A",
|
435
|
+
# "Object",
|
436
|
+
# "Kernel",
|
437
|
+
# "BasicObject",
|
438
|
+
],
|
439
|
+
@index.linearized_ancestors_of("Foo"),
|
440
|
+
)
|
441
|
+
|
442
|
+
assert_equal(
|
443
|
+
[
|
444
|
+
"B",
|
445
|
+
"A",
|
446
|
+
"Bar",
|
447
|
+
# "Object",
|
448
|
+
# "Kernel",
|
449
|
+
# "BasicObject",
|
450
|
+
],
|
451
|
+
@index.linearized_ancestors_of("Bar"),
|
452
|
+
)
|
453
|
+
end
|
454
|
+
|
455
|
+
def test_linearizing_ancestors_is_cached
|
456
|
+
index(<<~RUBY)
|
457
|
+
module C; end
|
458
|
+
module A; end
|
459
|
+
module B
|
460
|
+
include A
|
461
|
+
end
|
462
|
+
|
463
|
+
class Foo
|
464
|
+
include B
|
465
|
+
include A
|
466
|
+
end
|
467
|
+
RUBY
|
468
|
+
|
469
|
+
@index.linearized_ancestors_of("Foo")
|
470
|
+
ancestors = @index.instance_variable_get(:@ancestors)
|
471
|
+
assert(ancestors.key?("Foo"))
|
472
|
+
assert(ancestors.key?("A"))
|
473
|
+
assert(ancestors.key?("B"))
|
474
|
+
refute(ancestors.key?("C"))
|
475
|
+
end
|
476
|
+
|
477
|
+
def test_duplicate_prepend_include
|
478
|
+
index(<<~RUBY)
|
479
|
+
module A; end
|
480
|
+
|
481
|
+
class Foo
|
482
|
+
prepend A
|
483
|
+
include A
|
484
|
+
end
|
485
|
+
|
486
|
+
class Bar
|
487
|
+
include A
|
488
|
+
prepend A
|
489
|
+
end
|
490
|
+
RUBY
|
491
|
+
|
492
|
+
assert_equal(
|
493
|
+
[
|
494
|
+
"A",
|
495
|
+
"Foo",
|
496
|
+
# "Object",
|
497
|
+
# "Kernel",
|
498
|
+
# "BasicObject",
|
499
|
+
],
|
500
|
+
@index.linearized_ancestors_of("Foo"),
|
501
|
+
)
|
502
|
+
|
503
|
+
assert_equal(
|
504
|
+
[
|
505
|
+
"A",
|
506
|
+
"Bar",
|
507
|
+
"A",
|
508
|
+
# "Object",
|
509
|
+
# "Kernel",
|
510
|
+
# "BasicObject",
|
511
|
+
],
|
512
|
+
@index.linearized_ancestors_of("Bar"),
|
513
|
+
)
|
514
|
+
end
|
515
|
+
|
516
|
+
def test_linearizing_ancestors_handles_circular_parent_class
|
517
|
+
index(<<~RUBY)
|
518
|
+
class Foo < Foo
|
519
|
+
end
|
520
|
+
RUBY
|
521
|
+
|
522
|
+
assert_equal(
|
523
|
+
[
|
524
|
+
"Foo",
|
525
|
+
# "Object",
|
526
|
+
# "Kernel",
|
527
|
+
# "BasicObject",
|
528
|
+
],
|
529
|
+
@index.linearized_ancestors_of("Foo"),
|
530
|
+
)
|
531
|
+
end
|
532
|
+
|
533
|
+
def test_ancestors_linearization_complex_prepend_duplication
|
534
|
+
index(<<~RUBY)
|
535
|
+
module A; end
|
536
|
+
module B
|
537
|
+
prepend A
|
538
|
+
end
|
539
|
+
module C
|
540
|
+
prepend B
|
541
|
+
end
|
542
|
+
|
543
|
+
class Foo
|
544
|
+
prepend A
|
545
|
+
prepend C
|
546
|
+
end
|
547
|
+
RUBY
|
548
|
+
|
549
|
+
assert_equal(
|
550
|
+
[
|
551
|
+
"A",
|
552
|
+
"B",
|
553
|
+
"C",
|
554
|
+
"Foo",
|
555
|
+
# "Object",
|
556
|
+
# "Kernel",
|
557
|
+
# "BasicObject",
|
558
|
+
],
|
559
|
+
@index.linearized_ancestors_of("Foo"),
|
560
|
+
)
|
561
|
+
end
|
562
|
+
|
563
|
+
def test_ancestors_linearization_complex_include_duplication
|
564
|
+
index(<<~RUBY)
|
565
|
+
module A; end
|
566
|
+
module B
|
567
|
+
include A
|
568
|
+
end
|
569
|
+
module C
|
570
|
+
include B
|
571
|
+
end
|
572
|
+
|
573
|
+
class Foo
|
574
|
+
include A
|
575
|
+
include C
|
576
|
+
end
|
577
|
+
RUBY
|
578
|
+
|
579
|
+
assert_equal(
|
580
|
+
[
|
581
|
+
"Foo",
|
582
|
+
"C",
|
583
|
+
"B",
|
584
|
+
"A",
|
585
|
+
# "Object",
|
586
|
+
# "Kernel",
|
587
|
+
# "BasicObject",
|
588
|
+
],
|
589
|
+
@index.linearized_ancestors_of("Foo"),
|
590
|
+
)
|
591
|
+
end
|
592
|
+
|
593
|
+
def test_linearizing_ancestors_that_need_to_be_resolved
|
594
|
+
index(<<~RUBY)
|
595
|
+
module Foo
|
596
|
+
module Baz
|
597
|
+
end
|
598
|
+
module Qux
|
599
|
+
end
|
600
|
+
|
601
|
+
class Something; end
|
602
|
+
|
603
|
+
class Bar < Something
|
604
|
+
include Baz
|
605
|
+
prepend Qux
|
606
|
+
end
|
607
|
+
end
|
608
|
+
RUBY
|
609
|
+
|
610
|
+
assert_equal(
|
611
|
+
[
|
612
|
+
"Foo::Qux",
|
613
|
+
"Foo::Bar",
|
614
|
+
"Foo::Baz",
|
615
|
+
"Foo::Something",
|
616
|
+
# "Object",
|
617
|
+
# "Kernel",
|
618
|
+
# "BasicObject",
|
619
|
+
],
|
620
|
+
@index.linearized_ancestors_of("Foo::Bar"),
|
621
|
+
)
|
622
|
+
end
|
623
|
+
|
624
|
+
def test_linearizing_ancestors_for_non_existing_namespaces
|
625
|
+
index(<<~RUBY)
|
626
|
+
module Kernel
|
627
|
+
def Array(a); end
|
628
|
+
end
|
629
|
+
RUBY
|
630
|
+
|
631
|
+
assert_raises(Index::NonExistingNamespaceError) do
|
632
|
+
@index.linearized_ancestors_of("Foo")
|
633
|
+
end
|
634
|
+
|
635
|
+
assert_raises(Index::NonExistingNamespaceError) do
|
636
|
+
@index.linearized_ancestors_of("Array")
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
def test_linearizing_circular_ancestors
|
641
|
+
index(<<~RUBY)
|
642
|
+
module M1
|
643
|
+
include M2
|
644
|
+
end
|
645
|
+
|
646
|
+
module M2
|
647
|
+
include M1
|
648
|
+
end
|
649
|
+
|
650
|
+
module A1
|
651
|
+
include A2
|
652
|
+
end
|
653
|
+
|
654
|
+
module A2
|
655
|
+
include A3
|
656
|
+
end
|
657
|
+
|
658
|
+
module A3
|
659
|
+
include A1
|
660
|
+
end
|
661
|
+
|
662
|
+
class Foo < Foo
|
663
|
+
include Foo
|
664
|
+
end
|
665
|
+
|
666
|
+
module Bar
|
667
|
+
include Bar
|
668
|
+
end
|
669
|
+
RUBY
|
670
|
+
|
671
|
+
assert_equal(["M2", "M1"], @index.linearized_ancestors_of("M2"))
|
672
|
+
assert_equal(["A3", "A1", "A2"], @index.linearized_ancestors_of("A3"))
|
673
|
+
assert_equal(["Foo"], @index.linearized_ancestors_of("Foo"))
|
674
|
+
assert_equal(["Bar"], @index.linearized_ancestors_of("Bar"))
|
675
|
+
end
|
676
|
+
|
677
|
+
def test_linearizing_circular_aliased_dependency
|
678
|
+
index(<<~RUBY)
|
679
|
+
module A
|
680
|
+
end
|
681
|
+
|
682
|
+
ALIAS = A
|
683
|
+
|
684
|
+
module A
|
685
|
+
include ALIAS
|
686
|
+
end
|
687
|
+
RUBY
|
688
|
+
|
689
|
+
assert_equal(["A", "ALIAS"], @index.linearized_ancestors_of("A"))
|
690
|
+
end
|
691
|
+
|
692
|
+
def test_resolving_an_inherited_method
|
693
|
+
index(<<~RUBY)
|
694
|
+
module Foo
|
695
|
+
def baz; end
|
696
|
+
end
|
697
|
+
|
698
|
+
class Bar
|
699
|
+
def qux; end
|
700
|
+
end
|
701
|
+
|
702
|
+
class Wow < Bar
|
703
|
+
include Foo
|
704
|
+
end
|
705
|
+
RUBY
|
706
|
+
|
707
|
+
entry = T.must(@index.resolve_method("baz", "Wow")&.first)
|
708
|
+
assert_equal("baz", entry.name)
|
709
|
+
assert_equal("Foo", T.must(entry.owner).name)
|
710
|
+
|
711
|
+
entry = T.must(@index.resolve_method("qux", "Wow")&.first)
|
712
|
+
assert_equal("qux", entry.name)
|
713
|
+
assert_equal("Bar", T.must(entry.owner).name)
|
714
|
+
end
|
715
|
+
|
716
|
+
def test_resolving_an_inherited_method_lands_on_first_match
|
717
|
+
index(<<~RUBY)
|
718
|
+
module Foo
|
719
|
+
def qux; end
|
720
|
+
end
|
721
|
+
|
722
|
+
class Bar
|
723
|
+
def qux; end
|
724
|
+
end
|
725
|
+
|
726
|
+
class Wow < Bar
|
727
|
+
prepend Foo
|
728
|
+
|
729
|
+
def qux; end
|
730
|
+
end
|
731
|
+
RUBY
|
732
|
+
|
733
|
+
entries = T.must(@index.resolve_method("qux", "Wow"))
|
734
|
+
assert_equal(1, entries.length)
|
735
|
+
|
736
|
+
entry = T.must(entries.first)
|
737
|
+
assert_equal("qux", entry.name)
|
738
|
+
assert_equal("Foo", T.must(entry.owner).name)
|
739
|
+
end
|
740
|
+
|
741
|
+
def test_handle_change_clears_ancestor_cache_if_tree_changed
|
742
|
+
Dir.mktmpdir do |dir|
|
743
|
+
Dir.chdir(dir) do
|
744
|
+
# Write the original file
|
745
|
+
File.write(File.join(dir, "foo.rb"), <<~RUBY)
|
746
|
+
module Foo
|
747
|
+
end
|
748
|
+
|
749
|
+
class Bar
|
750
|
+
include Foo
|
751
|
+
end
|
752
|
+
RUBY
|
753
|
+
|
754
|
+
indexable_path = IndexablePath.new(nil, File.join(dir, "foo.rb"))
|
755
|
+
@index.index_single(indexable_path)
|
756
|
+
|
757
|
+
assert_equal(["Bar", "Foo"], @index.linearized_ancestors_of("Bar"))
|
758
|
+
|
759
|
+
# Remove include to invalidate the ancestor tree
|
760
|
+
File.write(File.join(dir, "foo.rb"), <<~RUBY)
|
761
|
+
module Foo
|
762
|
+
end
|
763
|
+
|
764
|
+
class Bar
|
765
|
+
end
|
766
|
+
RUBY
|
767
|
+
|
768
|
+
@index.handle_change(indexable_path)
|
769
|
+
assert_empty(@index.instance_variable_get(:@ancestors))
|
770
|
+
assert_equal(["Bar"], @index.linearized_ancestors_of("Bar"))
|
771
|
+
end
|
772
|
+
end
|
773
|
+
end
|
774
|
+
|
775
|
+
def test_handle_change_does_not_clear_ancestor_cache_if_tree_not_changed
|
776
|
+
Dir.mktmpdir do |dir|
|
777
|
+
Dir.chdir(dir) do
|
778
|
+
# Write the original file
|
779
|
+
File.write(File.join(dir, "foo.rb"), <<~RUBY)
|
780
|
+
module Foo
|
781
|
+
end
|
782
|
+
|
783
|
+
class Bar
|
784
|
+
include Foo
|
785
|
+
end
|
786
|
+
RUBY
|
787
|
+
|
788
|
+
indexable_path = IndexablePath.new(nil, File.join(dir, "foo.rb"))
|
789
|
+
@index.index_single(indexable_path)
|
790
|
+
|
791
|
+
assert_equal(["Bar", "Foo"], @index.linearized_ancestors_of("Bar"))
|
792
|
+
|
793
|
+
# Remove include to invalidate the ancestor tree
|
794
|
+
File.write(File.join(dir, "foo.rb"), <<~RUBY)
|
795
|
+
module Foo
|
796
|
+
end
|
797
|
+
|
798
|
+
class Bar
|
799
|
+
include Foo
|
800
|
+
|
801
|
+
def baz; end
|
802
|
+
end
|
803
|
+
RUBY
|
804
|
+
|
805
|
+
@index.handle_change(indexable_path)
|
806
|
+
refute_empty(@index.instance_variable_get(:@ancestors))
|
807
|
+
assert_equal(["Bar", "Foo"], @index.linearized_ancestors_of("Bar"))
|
808
|
+
end
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
def test_handle_change_clears_ancestor_cache_if_parent_class_changed
|
813
|
+
Dir.mktmpdir do |dir|
|
814
|
+
Dir.chdir(dir) do
|
815
|
+
# Write the original file
|
816
|
+
File.write(File.join(dir, "foo.rb"), <<~RUBY)
|
817
|
+
class Foo
|
818
|
+
end
|
819
|
+
|
820
|
+
class Bar < Foo
|
821
|
+
end
|
822
|
+
RUBY
|
823
|
+
|
824
|
+
indexable_path = IndexablePath.new(nil, File.join(dir, "foo.rb"))
|
825
|
+
@index.index_single(indexable_path)
|
826
|
+
|
827
|
+
assert_equal(["Bar", "Foo"], @index.linearized_ancestors_of("Bar"))
|
828
|
+
|
829
|
+
# Remove include to invalidate the ancestor tree
|
830
|
+
File.write(File.join(dir, "foo.rb"), <<~RUBY)
|
831
|
+
class Foo
|
832
|
+
end
|
833
|
+
|
834
|
+
class Bar
|
835
|
+
end
|
836
|
+
RUBY
|
837
|
+
|
838
|
+
@index.handle_change(indexable_path)
|
839
|
+
assert_empty(@index.instance_variable_get(:@ancestors))
|
840
|
+
assert_equal(["Bar"], @index.linearized_ancestors_of("Bar"))
|
841
|
+
end
|
842
|
+
end
|
843
|
+
end
|
316
844
|
end
|
317
845
|
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "test_case"
|
5
|
+
|
6
|
+
module RubyIndexer
|
7
|
+
class InstanceVariableTest < TestCase
|
8
|
+
def test_instance_variable_write
|
9
|
+
index(<<~RUBY)
|
10
|
+
module Foo
|
11
|
+
class Bar
|
12
|
+
def initialize
|
13
|
+
# Hello
|
14
|
+
@a = 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
RUBY
|
19
|
+
|
20
|
+
assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:4-6:4-8")
|
21
|
+
|
22
|
+
entry = T.must(@index["@a"]&.first)
|
23
|
+
assert_equal("Foo::Bar", T.must(entry.owner).name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_instance_variable_and_write
|
27
|
+
index(<<~RUBY)
|
28
|
+
module Foo
|
29
|
+
class Bar
|
30
|
+
def initialize
|
31
|
+
# Hello
|
32
|
+
@a &&= value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
RUBY
|
37
|
+
|
38
|
+
assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:4-6:4-8")
|
39
|
+
|
40
|
+
entry = T.must(@index["@a"]&.first)
|
41
|
+
assert_equal("Foo::Bar", T.must(entry.owner).name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_instance_variable_operator_write
|
45
|
+
index(<<~RUBY)
|
46
|
+
module Foo
|
47
|
+
class Bar
|
48
|
+
def initialize
|
49
|
+
# Hello
|
50
|
+
@a += value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
RUBY
|
55
|
+
|
56
|
+
assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:4-6:4-8")
|
57
|
+
|
58
|
+
entry = T.must(@index["@a"]&.first)
|
59
|
+
assert_equal("Foo::Bar", T.must(entry.owner).name)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_instance_variable_or_write
|
63
|
+
index(<<~RUBY)
|
64
|
+
module Foo
|
65
|
+
class Bar
|
66
|
+
def initialize
|
67
|
+
# Hello
|
68
|
+
@a ||= value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
RUBY
|
73
|
+
|
74
|
+
assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:4-6:4-8")
|
75
|
+
|
76
|
+
entry = T.must(@index["@a"]&.first)
|
77
|
+
assert_equal("Foo::Bar", T.must(entry.owner).name)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_instance_variable_target
|
81
|
+
index(<<~RUBY)
|
82
|
+
module Foo
|
83
|
+
class Bar
|
84
|
+
def initialize
|
85
|
+
# Hello
|
86
|
+
@a, @b = [1, 2]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
RUBY
|
91
|
+
|
92
|
+
assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:4-6:4-8")
|
93
|
+
assert_entry("@b", Entry::InstanceVariable, "/fake/path/foo.rb:4-10:4-12")
|
94
|
+
|
95
|
+
entry = T.must(@index["@a"]&.first)
|
96
|
+
assert_equal("Foo::Bar", T.must(entry.owner).name)
|
97
|
+
|
98
|
+
entry = T.must(@index["@b"]&.first)
|
99
|
+
assert_equal("Foo::Bar", T.must(entry.owner).name)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_empty_name_instance_variables
|
103
|
+
index(<<~RUBY)
|
104
|
+
module Foo
|
105
|
+
class Bar
|
106
|
+
def initialize
|
107
|
+
@ = 123
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
RUBY
|
112
|
+
|
113
|
+
refute_entry("@")
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_class_instance_variables
|
117
|
+
index(<<~RUBY)
|
118
|
+
module Foo
|
119
|
+
class Bar
|
120
|
+
@a = 123
|
121
|
+
end
|
122
|
+
end
|
123
|
+
RUBY
|
124
|
+
|
125
|
+
assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:2-4:2-6")
|
126
|
+
|
127
|
+
entry = T.must(@index["@a"]&.first)
|
128
|
+
assert_equal("Foo::Bar", T.must(entry.owner).name)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|