@@ -71,43 +71,72 @@ def bar
7171 assert_includes ( ref_lines , 5 ) # reference
7272 end
7373
74- def test_does_not_match_simple_names_when_method_receiver_is_known
75- source = <<~RUBY
76- class Foo
77- def self.bar
78- end
74+ AMBIGUOUS_BAR_SOURCE = <<~RUBY
75+ class Foo
76+ def self.bar
7977 end
78+ end
8079
81- class Qux
82- def bar
83- end
80+ class Qux
81+ def bar
82+ end
83+ end
84+
85+ class Other
86+ def self.bar
8487 end
88+ end
8589
86- it = Qux.new
87- it.bar
90+ it = Qux.new
91+ it.bar
8892
89- Foo.bar
90- RUBY
93+ Foo.bar
94+ Other.bar
95+ RUBY
9196
92- # Cursor on `bar` in `Foo.bar` — the receiver is the `Foo` singleton, so only the `Foo.bar`
93- # declaration is a valid target. We must not surface `Qux#bar` as a candidate declaration.
94- refs = find_references ( source , { line : 13 , character : 4 } , include_declarations : true )
97+ def test_filters_method_references_when_call_site_receiver_is_a_known_constant
98+ refs = find_references ( AMBIGUOUS_BAR_SOURCE , { line : 18 , character : 4 } , include_declarations : true )
9599 ref_lines = refs . map { |r | r . range . start . line }
100+
96101 assert_includes ( ref_lines , 1 ) # def self.bar declaration
97- assert_includes ( ref_lines , 13 ) # Foo.bar call site
98102 refute_includes ( ref_lines , 6 ) # def bar (Qux) must not appear
103+ refute_includes ( ref_lines , 11 ) # def self.bar (Other) must not appear
104+ assert_includes ( ref_lines , 16 ) # it.bar included because receiver is unresolved
105+ assert_includes ( ref_lines , 18 ) # Foo.bar call site
106+ refute_includes ( ref_lines , 19 ) # Other.bar call site is filtered out by its resolved receiver
107+ end
99108
100- # it.bar must not appear, but we don't currently expose method reference receivers in the API
101- assert_includes ( ref_lines , 11 )
102-
103- # Cursor on `bar` in `it.bar` — the type of the local `it` can't be inferred, so we fall back
104- # to including every `bar` declaration and call site as candidates.
105- refs = find_references ( source , { line : 11 , character : 3 } , include_declarations : true )
109+ def test_falls_back_to_all_candidates_when_call_site_receiver_is_unresolvable
110+ refs = find_references ( AMBIGUOUS_BAR_SOURCE , { line : 16 , character : 3 } , include_declarations : true )
106111 ref_lines = refs . map { |r | r . range . start . line }
112+
107113 assert_includes ( ref_lines , 1 ) # Foo.bar declaration
108114 assert_includes ( ref_lines , 6 ) # Qux#bar declaration
109- assert_includes ( ref_lines , 11 ) # it.bar call site
110- assert_includes ( ref_lines , 13 ) # Foo.bar call site
115+ assert_includes ( ref_lines , 11 ) # Other.bar declaration
116+ assert_includes ( ref_lines , 16 ) # it.bar call site
117+ assert_includes ( ref_lines , 18 ) # Foo.bar call site
118+ assert_includes ( ref_lines , 19 ) # Other.bar call site
119+ end
120+
121+ def test_method_references_match_through_superclass_chain
122+ source = <<~RUBY
123+ class Parent
124+ def self.bar
125+ end
126+ end
127+
128+ class Child < Parent
129+ end
130+
131+ Parent.bar
132+ Child.bar
133+ RUBY
134+
135+ refs = find_references ( source , { line : 1 , character : 11 } , include_declarations : true )
136+ ref_lines = refs . map { |r | r . range . start . line }
137+ assert_includes ( ref_lines , 1 ) # Parent.bar declaration
138+ assert_includes ( ref_lines , 8 ) # Parent.bar call site
139+ assert_includes ( ref_lines , 9 ) # Child.bar call site (matched through Child::<Child>'s ancestors)
111140 end
112141
113142 def test_finds_references_from_def_node
0 commit comments