Skip to content

Commit ae57e98

Browse files
committed
test(radls): port findReferences cases to wire-level snapshot
5 cases moved to references.snap covering uses-only output, includeDeclaration=true behavior, cursor-from-use-site lookup, off-identifier empty result, and a single-decl-no-uses case. The snapshot makes the decl-as-use dedupe visible: in the IncludesDecl case, the decl span appears exactly once even though the binder records the LHS identifier in both Uses and Decls. Go file kept for nil-snapshot guard.
1 parent 2952d3e commit ae57e98

2 files changed

Lines changed: 216 additions & 103 deletions

File tree

radls/analysis/references_test.go

Lines changed: 3 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -6,93 +6,10 @@ import (
66
"github.com/amterp/rad/radls/lsp"
77
)
88

9-
func referencesFixture(t *testing.T, src string, pos lsp.Pos, includeDecl bool) []lsp.Location {
10-
t.Helper()
11-
s := NewState()
12-
s.SetEncoding(EncodingUTF16)
13-
const uri = "file:///refs_test.rad"
14-
s.AddDoc(uri, src)
15-
snap := s.Snapshot(uri)
16-
if snap == nil {
17-
t.Fatal("expected snapshot")
18-
}
19-
defer snap.Release()
20-
locs, err := s.References(snap, pos, includeDecl)
21-
if err != nil {
22-
t.Fatalf("References: %v", err)
23-
}
24-
return locs
25-
}
26-
27-
// TestReferencesUseSitesOnly verifies includeDeclaration=false
28-
// returns just the use sites of a symbol. Three references of `x`
29-
// past the decl -> three Locations, no decl.
30-
func TestReferencesUseSitesOnly(t *testing.T) {
31-
src := "x = 1\nprint(x)\nprint(x + x)\n"
32-
// Cursor on the `x` on line 0 (the decl).
33-
locs := referencesFixture(t, src, lsp.NewPos(0, 0), false)
34-
if len(locs) != 3 {
35-
t.Errorf("expected 3 uses (excluding decl), got %d (%v)", len(locs), locs)
36-
}
37-
}
9+
// Behavior cases for findReferences live in
10+
// radls/lstesting/snapshots/references.snap. This file
11+
// keeps only the nil-snapshot guard.
3812

39-
// TestReferencesIncludesDecl verifies includeDeclaration=true adds
40-
// the decl site to the result.
41-
func TestReferencesIncludesDecl(t *testing.T) {
42-
src := "x = 1\nprint(x)\n"
43-
locs := referencesFixture(t, src, lsp.NewPos(0, 0), true)
44-
if len(locs) != 2 {
45-
t.Errorf("expected 2 locations (decl + 1 use), got %d (%v)",
46-
len(locs), locs)
47-
}
48-
}
49-
50-
// TestReferencesSortedByPosition verifies results come back in
51-
// source order. Map iteration in Go is non-deterministic; without
52-
// the explicit sort, the editor would show results in whatever
53-
// order the underlying map happened to walk this time.
54-
func TestReferencesSortedByPosition(t *testing.T) {
55-
src := "x = 1\nprint(x)\nprint(x + x)\n"
56-
locs := referencesFixture(t, src, lsp.NewPos(0, 0), false)
57-
if len(locs) < 2 {
58-
t.Fatalf("need >= 2 to test sort, got %d", len(locs))
59-
}
60-
for i := 1; i < len(locs); i++ {
61-
prev, cur := locs[i-1].Range.Start, locs[i].Range.Start
62-
if prev.Line > cur.Line ||
63-
(prev.Line == cur.Line && prev.Character > cur.Character) {
64-
t.Errorf("not sorted: %v before %v", prev, cur)
65-
}
66-
}
67-
}
68-
69-
// TestReferencesFromUseSite verifies the cursor on a use (not the
70-
// decl) still finds all references. The lookup goes through the
71-
// Symbol, so any identifier bound to that Symbol must produce the
72-
// same result set.
73-
func TestReferencesFromUseSite(t *testing.T) {
74-
src := "x = 1\nprint(x)\nprint(x)\n"
75-
// Cursor on the `x` in `print(x)` on line 1.
76-
locs := referencesFixture(t, src, lsp.NewPos(1, 6), false)
77-
if len(locs) != 2 {
78-
t.Errorf("expected 2 uses from use-site cursor, got %d (%v)",
79-
len(locs), locs)
80-
}
81-
}
82-
83-
// TestReferencesOffIdentifierReturnsEmpty verifies cursor on
84-
// non-identifier territory yields an empty array (not nil).
85-
func TestReferencesOffIdentifierReturnsEmpty(t *testing.T) {
86-
locs := referencesFixture(t, "x = 1\n", lsp.NewPos(0, 4), false)
87-
if locs == nil {
88-
t.Fatal("expected empty slice, got nil")
89-
}
90-
if len(locs) != 0 {
91-
t.Errorf("expected 0 locations, got %d (%v)", len(locs), locs)
92-
}
93-
}
94-
95-
// TestReferencesNoSnapshotReturnsEmpty verifies the nil-snapshot path.
9613
func TestReferencesNoSnapshotReturnsEmpty(t *testing.T) {
9714
s := NewState()
9815
locs, err := s.References(nil, lsp.NewPos(0, 0), true)
@@ -103,20 +20,3 @@ func TestReferencesNoSnapshotReturnsEmpty(t *testing.T) {
10320
t.Errorf("expected empty slice for nil snapshot, got %v", locs)
10421
}
10522
}
106-
107-
// TestReferencesURIMatchesDocument verifies every Location carries
108-
// the document's URI. Single-file project today; this is forward
109-
// insurance for when multi-file lookups arrive.
110-
func TestReferencesURIMatchesDocument(t *testing.T) {
111-
src := "x = 1\nprint(x)\n"
112-
locs := referencesFixture(t, src, lsp.NewPos(0, 0), true)
113-
if len(locs) == 0 {
114-
t.Fatal("expected non-empty")
115-
}
116-
for i, loc := range locs {
117-
if loc.Uri != "file:///refs_test.rad" {
118-
t.Errorf("loc[%d] uri: got %q, want %q",
119-
i, loc.Uri, "file:///refs_test.rad")
120-
}
121-
}
122-
}
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
### TITLE ###
2+
UseSitesOnly
3+
### DOCUMENT ###
4+
x = 1
5+
print(x)
6+
print(x + x)
7+
### REFERENCES 0:0 ###
8+
### STDOUT ###
9+
{
10+
"jsonrpc": "2.0",
11+
"method": "textDocument/publishDiagnostics",
12+
"params": {
13+
"diagnostics": [],
14+
"uri": "file:///test.rad"
15+
}
16+
}
17+
18+
{
19+
"id": 1,
20+
"jsonrpc": "2.0",
21+
"result": [
22+
{
23+
"range": {
24+
"end": {
25+
"character": 7,
26+
"line": 1
27+
},
28+
"start": {
29+
"character": 6,
30+
"line": 1
31+
}
32+
},
33+
"uri": "file:///test.rad"
34+
},
35+
{
36+
"range": {
37+
"end": {
38+
"character": 7,
39+
"line": 2
40+
},
41+
"start": {
42+
"character": 6,
43+
"line": 2
44+
}
45+
},
46+
"uri": "file:///test.rad"
47+
},
48+
{
49+
"range": {
50+
"end": {
51+
"character": 11,
52+
"line": 2
53+
},
54+
"start": {
55+
"character": 10,
56+
"line": 2
57+
}
58+
},
59+
"uri": "file:///test.rad"
60+
}
61+
]
62+
}
63+
### TITLE ###
64+
IncludesDecl
65+
### DOCUMENT ###
66+
x = 1
67+
print(x)
68+
### REFERENCES 0:0 decl ###
69+
### STDOUT ###
70+
{
71+
"jsonrpc": "2.0",
72+
"method": "textDocument/publishDiagnostics",
73+
"params": {
74+
"diagnostics": [],
75+
"uri": "file:///test.rad"
76+
}
77+
}
78+
79+
{
80+
"id": 1,
81+
"jsonrpc": "2.0",
82+
"result": [
83+
{
84+
"range": {
85+
"end": {
86+
"character": 1,
87+
"line": 0
88+
},
89+
"start": {
90+
"character": 0,
91+
"line": 0
92+
}
93+
},
94+
"uri": "file:///test.rad"
95+
},
96+
{
97+
"range": {
98+
"end": {
99+
"character": 7,
100+
"line": 1
101+
},
102+
"start": {
103+
"character": 6,
104+
"line": 1
105+
}
106+
},
107+
"uri": "file:///test.rad"
108+
}
109+
]
110+
}
111+
### TITLE ###
112+
FromUseSite
113+
### DOCUMENT ###
114+
x = 1
115+
print(x)
116+
print(x)
117+
### REFERENCES 1:6 ###
118+
### STDOUT ###
119+
{
120+
"jsonrpc": "2.0",
121+
"method": "textDocument/publishDiagnostics",
122+
"params": {
123+
"diagnostics": [],
124+
"uri": "file:///test.rad"
125+
}
126+
}
127+
128+
{
129+
"id": 1,
130+
"jsonrpc": "2.0",
131+
"result": [
132+
{
133+
"range": {
134+
"end": {
135+
"character": 7,
136+
"line": 1
137+
},
138+
"start": {
139+
"character": 6,
140+
"line": 1
141+
}
142+
},
143+
"uri": "file:///test.rad"
144+
},
145+
{
146+
"range": {
147+
"end": {
148+
"character": 7,
149+
"line": 2
150+
},
151+
"start": {
152+
"character": 6,
153+
"line": 2
154+
}
155+
},
156+
"uri": "file:///test.rad"
157+
}
158+
]
159+
}
160+
### TITLE ###
161+
OffIdentifierReturnsEmpty
162+
### DOCUMENT ###
163+
x = 1
164+
### REFERENCES 0:4 ###
165+
### STDOUT ###
166+
{
167+
"jsonrpc": "2.0",
168+
"method": "textDocument/publishDiagnostics",
169+
"params": {
170+
"diagnostics": [],
171+
"uri": "file:///test.rad"
172+
}
173+
}
174+
175+
{
176+
"id": 1,
177+
"jsonrpc": "2.0",
178+
"result": []
179+
}
180+
### TITLE ###
181+
NoReferencesForUnusedLocal
182+
### DOCUMENT ###
183+
x = 1
184+
### REFERENCES 0:0 decl ###
185+
### STDOUT ###
186+
{
187+
"jsonrpc": "2.0",
188+
"method": "textDocument/publishDiagnostics",
189+
"params": {
190+
"diagnostics": [],
191+
"uri": "file:///test.rad"
192+
}
193+
}
194+
195+
{
196+
"id": 1,
197+
"jsonrpc": "2.0",
198+
"result": [
199+
{
200+
"range": {
201+
"end": {
202+
"character": 1,
203+
"line": 0
204+
},
205+
"start": {
206+
"character": 0,
207+
"line": 0
208+
}
209+
},
210+
"uri": "file:///test.rad"
211+
}
212+
]
213+
}

0 commit comments

Comments
 (0)