Skip to content

Commit f04c359

Browse files
committed
Rust: Add more jump-to-def test cases and refine logic
1 parent c81a1c2 commit f04c359

File tree

3 files changed

+55
-15
lines changed

3 files changed

+55
-15
lines changed

rust/ql/lib/codeql/rust/internal/Definitions.qll

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -179,26 +179,46 @@ private class MethodUse extends Use instanceof NameRef {
179179
override string getUseType() { result = "method" }
180180
}
181181

182+
// We don't have entities for the operator symbols, so we approximate a location.
183+
// The location spans are chosen so that they align with rust-analyzer's jump-to-def
184+
// behavior in VS Code, which means using weird locations where the end column is
185+
// before the start column in the case of unary prefix operations.
186+
private predicate operatorHasLocationInfo(
187+
Operation o, string filepath, int startline, int startcolumn, int endline, int endcolumn
188+
) {
189+
o =
190+
// `-x`; placing the cursor before `-` jumps to `neg`, placing it after jumps to `x`
191+
any(PrefixExpr pe |
192+
pe.getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
193+
endline = startline and
194+
endcolumn = startcolumn - 1
195+
)
196+
or
197+
o =
198+
// `x + y`: placing the cursor before or after `+` jumps to `add`
199+
// `x+ y`: placing the cursor before `+` jumps to `x`, after `+` jumps to `add`
200+
any(BinaryExpr be |
201+
be.getLhs().getLocation().hasLocationInfo(filepath, _, _, startline, startcolumn - 2) and
202+
be.getRhs().getLocation().hasLocationInfo(filepath, endline, endcolumn + 2, _, _) and
203+
(
204+
startline < endline
205+
or
206+
endcolumn = startcolumn
207+
)
208+
)
209+
}
210+
182211
private class OperationUse extends Use instanceof Operation {
212+
OperationUse() { operatorHasLocationInfo(this, _, _, _, _, _) }
213+
183214
override Definition getDefinition() { result.asItemNode() = this.(Call).getStaticTarget() }
184215

185216
override string getUseType() { result = "method" }
186217

187218
override predicate hasLocationInfo(
188219
string filepath, int startline, int startcolumn, int endline, int endcolumn
189220
) {
190-
// We don't have entities for the operator symbols, so approximate a location
191-
this =
192-
any(PrefixExpr pe |
193-
pe.getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
194-
pe.getExpr().getLocation().hasLocationInfo(_, endline, endcolumn + 2, _, _)
195-
)
196-
or
197-
this =
198-
any(BinaryExpr be |
199-
be.getLhs().getLocation().hasLocationInfo(filepath, _, _, startline, startcolumn - 2) and
200-
be.getRhs().getLocation().hasLocationInfo(filepath, endline, endcolumn + 2, _, _)
201-
)
221+
operatorHasLocationInfo(this, filepath, startline, startcolumn, endline, endcolumn)
202222
}
203223
}
204224

@@ -207,10 +227,13 @@ private class IndexExprUse extends Use instanceof IndexExpr {
207227

208228
override string getUseType() { result = "method" }
209229

230+
// We don't have entities for the bracket symbols, so approximate a location
231+
// The location spans are chosen so that they align with rust-analyzer's jump-to-def
232+
// behavior in VS Code.
210233
override predicate hasLocationInfo(
211234
string filepath, int startline, int startcolumn, int endline, int endcolumn
212235
) {
213-
// We don't have entities for the brackets, so approximate a location
236+
// `x[y]`: placing the cursor after `]` jumps to `index`
214237
super.getIndex().getLocation().hasLocationInfo(filepath, _, _, startline, startcolumn - 2) and
215238
this.getLocation().hasLocationInfo(_, _, _, endline, endcolumn)
216239
}

rust/ql/test/library-tests/definitions/Definitions.expected

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,13 @@
7373
| main.rs:68:5:68:5 | S | main.rs:3:1:4:9 | struct S | path |
7474
| main.rs:68:7:68:7 | ... + ... | main.rs:19:5:21:5 | fn add | method |
7575
| main.rs:68:9:68:9 | S | main.rs:3:1:4:9 | struct S | path |
76-
| main.rs:69:5:69:5 | S | main.rs:3:1:4:9 | struct S | path |
77-
| main.rs:69:9:69:8 | S[0] | main.rs:27:5:29:5 | fn index | method |
76+
| main.rs:70:13:70:13 | S | main.rs:3:1:4:9 | struct S | path |
77+
| main.rs:70:15:70:15 | S | main.rs:3:1:4:9 | struct S | path |
78+
| main.rs:72:13:72:13 | S | main.rs:3:1:4:9 | struct S | path |
79+
| main.rs:72:15:73:4 | ... + ... | main.rs:19:5:21:5 | fn add | method |
80+
| main.rs:73:6:73:6 | S | main.rs:3:1:4:9 | struct S | path |
81+
| main.rs:75:13:75:13 | S | main.rs:3:1:4:9 | struct S | path |
82+
| main.rs:75:15:77:3 | ... + ... | main.rs:19:5:21:5 | fn add | method |
83+
| main.rs:77:5:77:5 | S | main.rs:3:1:4:9 | struct S | path |
84+
| main.rs:78:5:78:5 | S | main.rs:3:1:4:9 | struct S | path |
85+
| main.rs:78:9:78:8 | S[0] | main.rs:27:5:29:5 | fn index | method |

rust/ql/test/library-tests/definitions/main.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,14 @@ fn main() {
6666
M1::S2::<S>::new(S);
6767
-S;
6868
S + S;
69+
#[rustfmt::skip]
70+
let x = S+S;
71+
#[rustfmt::skip]
72+
let x = S
73+
+S;
74+
#[rustfmt::skip]
75+
let x = S
76+
+
77+
S;
6978
S[0];
7079
}

0 commit comments

Comments
 (0)