Skip to content

Commit bba872a

Browse files
committed
JS: Make jump-to-def behave nicer
1 parent b8dc1b3 commit bba872a

File tree

3 files changed

+53
-24
lines changed

3 files changed

+53
-24
lines changed

javascript/ql/lib/definitions.qll

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,7 @@ private predicate jsdocTypeLookup(JSDocNamedTypeExpr ref, AstNode decl, string k
153153
kind = "T"
154154
}
155155

156-
/**
157-
* Gets an element, of kind `kind`, that element `e` uses, if any.
158-
*
159-
* The `kind` is a string representing what kind of use it is:
160-
* - `"M"` for function and method calls
161-
* - `"T"` for uses of types
162-
* - `"V"` for variable accesses
163-
* - `"I"` for imports
164-
*/
165-
cached
166-
AstNode definitionOf(Locatable e, string kind) {
156+
private AstNode definitionOfRaw(Locatable e, string kind) {
167157
variableDefLookup(e, result, kind)
168158
or
169159
// prefer definitions over declarations
@@ -179,3 +169,41 @@ AstNode definitionOf(Locatable e, string kind) {
179169
or
180170
jsdocTypeLookup(e, result, kind)
181171
}
172+
173+
/** Gets a more useful node to show for something that resolves to `node`. */
174+
private AstNode redirectOnce(AstNode node) {
175+
exists(ConstructorDeclaration ctor |
176+
ctor.isSynthetic() and
177+
node = ctor.getBody() and
178+
result = ctor.getDeclaringClass()
179+
)
180+
or
181+
exists(ClassDefinition cls |
182+
node = cls and
183+
result = cls.getIdentifier()
184+
)
185+
or
186+
exists(MethodDeclaration member |
187+
not member instanceof ConstructorDeclaration and
188+
node = member.getBody() and
189+
result = member.getNameExpr()
190+
)
191+
}
192+
193+
private AstNode redirect(AstNode node) {
194+
node = definitionOfRaw(_, _) and
195+
result = redirectOnce*(node) and
196+
not exists(redirectOnce(result))
197+
}
198+
199+
/**
200+
* Gets an element, of kind `kind`, that element `e` uses, if any.
201+
*
202+
* The `kind` is a string representing what kind of use it is:
203+
* - `"M"` for function and method calls
204+
* - `"T"` for uses of types
205+
* - `"V"` for variable accesses
206+
* - `"I"` for imports
207+
*/
208+
cached
209+
AstNode definitionOf(Locatable e, string kind) { result = redirect(definitionOfRaw(e, kind)) }

javascript/ql/test/library-tests/DataFlow/tests.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,7 @@ sources
15141514
| tst2.ts:7:1:9:1 | return of function setX |
15151515
| tst2.ts:8:3:8:5 | A.x |
15161516
| tst2.ts:11:11:11:13 | A.x |
1517+
| tst2.ts:11:11:11:23 | A.x as number |
15171518
| tst2.ts:13:1:13:40 | class S ... ing> {} |
15181519
| tst2.ts:13:26:13:29 | List |
15191520
| tst2.ts:13:39:13:38 | (...arg ... rgs); } |

javascript/ql/test/query-tests/definitions/definitions.expected

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
| b.js:7:1:7:1 | f | b.js:1:1:5:1 | functio ... ar x;\\n} | M |
33
| b.js:8:1:8:1 | g | a.js:2:1:2:15 | function g() {} | M |
44
| client.ts:1:22:1:30 | "./tslib" | tslib.ts:1:1:10:0 | <toplevel> | I |
5-
| client.ts:7:19:7:19 | C | tslib.ts:1:8:3:1 | class C {\\n m() {}\\n} | T |
6-
| client.ts:8:10:8:10 | C | client.ts:3:1:5:1 | class C {\\n m() {}\\n} | T |
7-
| client.ts:9:16:9:16 | C | client.ts:3:1:5:1 | class C {\\n m() {}\\n} | T |
8-
| client.ts:10:16:10:16 | C | tslib.ts:6:10:8:3 | class C ... {}\\n } | T |
9-
| client.ts:13:25:13:25 | C | client.ts:3:1:5:1 | class C {\\n m() {}\\n} | T |
10-
| client.ts:13:35:13:35 | C | tslib.ts:1:8:3:1 | class C {\\n m() {}\\n} | T |
11-
| client.ts:13:47:13:47 | C | tslib.ts:6:10:8:3 | class C ... {}\\n } | T |
5+
| client.ts:7:19:7:19 | C | tslib.ts:1:14:1:14 | C | T |
6+
| client.ts:8:10:8:10 | C | client.ts:3:7:3:7 | C | T |
7+
| client.ts:9:16:9:16 | C | client.ts:3:7:3:7 | C | T |
8+
| client.ts:10:16:10:16 | C | tslib.ts:6:16:6:16 | C | T |
9+
| client.ts:13:25:13:25 | C | client.ts:3:7:3:7 | C | T |
10+
| client.ts:13:35:13:35 | C | tslib.ts:1:14:1:14 | C | T |
11+
| client.ts:13:47:13:47 | C | tslib.ts:6:16:6:16 | C | T |
1212
| client.ts:14:3:14:3 | x | client.ts:13:22:13:22 | x | V |
13-
| client.ts:14:5:14:5 | m | client.ts:4:3:4:8 | m() {} | M |
13+
| client.ts:14:5:14:5 | m | client.ts:4:3:4:3 | m | M |
1414
| client.ts:15:3:15:3 | y | client.ts:13:28:13:28 | y | V |
15-
| client.ts:15:5:15:5 | m | tslib.ts:2:3:2:8 | m() {} | M |
15+
| client.ts:15:5:15:5 | m | tslib.ts:2:3:2:3 | m | M |
1616
| client.ts:16:3:16:3 | z | client.ts:13:38:13:38 | z | V |
17-
| client.ts:16:5:16:5 | m | tslib.ts:7:5:7:10 | m() {} | M |
17+
| client.ts:16:5:16:5 | m | tslib.ts:7:5:7:5 | m | M |
1818
| d.js:1:17:1:21 | './c' | c.js:1:1:1:20 | <toplevel> | I |
1919
| d.js:10:1:10:1 | A | d.js:7:1:9:1 | functio ... = 42;\\n} | V |
20-
| d.js:16:19:16:23 | Super | d.js:12:1:14:1 | class S ... () {}\\n} | V |
20+
| d.js:16:19:16:23 | Super | d.js:12:7:12:11 | Super | V |
2121
| d.js:16:25:16:24 | args | d.js:16:25:16:24 | args | V |
2222
| d.js:20:1:20:1 | o | d.js:3:9:5:1 | {\\n f: ... () {}\\n} | V |
2323
| d.js:20:3:20:3 | f | d.js:4:3:4:18 | f: function() {} | M |
@@ -26,11 +26,11 @@
2626
| d.js:23:3:23:3 | x | d.js:8:3:8:8 | this.x | M |
2727
| d.js:24:1:24:1 | a | d.js:22:5:22:5 | a | V |
2828
| d.js:24:3:24:3 | g | d.js:10:1:10:13 | A.prototype.g | M |
29-
| d.js:26:13:26:15 | Sub | d.js:16:1:18:1 | class S ... () {}\\n} | M |
29+
| d.js:26:13:26:15 | Sub | d.js:16:7:16:9 | Sub | M |
3030
| d.js:27:1:27:1 | x | d.js:26:5:26:5 | x | V |
3131
| d.js:27:3:27:3 | m | d.js:13:3:13:3 | m | M |
3232
| d.js:28:1:28:1 | x | d.js:26:5:26:5 | x | V |
3333
| d.js:28:3:28:3 | n | d.js:17:3:17:3 | n | M |
3434
| tst.js:1:19:1:23 | './m' | m.js:1:1:2:0 | <toplevel> | I |
35-
| tst.js:3:5:3:5 | A | m.js:1:8:1:17 | class A {} | M |
35+
| tst.js:3:5:3:5 | A | m.js:1:14:1:14 | A | M |
3636
| tst.js:5:15:5:19 | './m' | m.js:1:1:2:0 | <toplevel> | I |

0 commit comments

Comments
 (0)