JS: Make jump-to-def behave nicer

This commit is contained in:
Asger F
2025-05-12 10:04:59 +02:00
parent b8dc1b3125
commit bba872a3a4
3 changed files with 53 additions and 24 deletions

View File

@@ -153,17 +153,7 @@ private predicate jsdocTypeLookup(JSDocNamedTypeExpr ref, AstNode decl, string k
kind = "T"
}
/**
* Gets an element, of kind `kind`, that element `e` uses, if any.
*
* The `kind` is a string representing what kind of use it is:
* - `"M"` for function and method calls
* - `"T"` for uses of types
* - `"V"` for variable accesses
* - `"I"` for imports
*/
cached
AstNode definitionOf(Locatable e, string kind) {
private AstNode definitionOfRaw(Locatable e, string kind) {
variableDefLookup(e, result, kind)
or
// prefer definitions over declarations
@@ -179,3 +169,41 @@ AstNode definitionOf(Locatable e, string kind) {
or
jsdocTypeLookup(e, result, kind)
}
/** Gets a more useful node to show for something that resolves to `node`. */
private AstNode redirectOnce(AstNode node) {
exists(ConstructorDeclaration ctor |
ctor.isSynthetic() and
node = ctor.getBody() and
result = ctor.getDeclaringClass()
)
or
exists(ClassDefinition cls |
node = cls and
result = cls.getIdentifier()
)
or
exists(MethodDeclaration member |
not member instanceof ConstructorDeclaration and
node = member.getBody() and
result = member.getNameExpr()
)
}
private AstNode redirect(AstNode node) {
node = definitionOfRaw(_, _) and
result = redirectOnce*(node) and
not exists(redirectOnce(result))
}
/**
* Gets an element, of kind `kind`, that element `e` uses, if any.
*
* The `kind` is a string representing what kind of use it is:
* - `"M"` for function and method calls
* - `"T"` for uses of types
* - `"V"` for variable accesses
* - `"I"` for imports
*/
cached
AstNode definitionOf(Locatable e, string kind) { result = redirect(definitionOfRaw(e, kind)) }

View File

@@ -1514,6 +1514,7 @@ sources
| tst2.ts:7:1:9:1 | return of function setX |
| tst2.ts:8:3:8:5 | A.x |
| tst2.ts:11:11:11:13 | A.x |
| tst2.ts:11:11:11:23 | A.x as number |
| tst2.ts:13:1:13:40 | class S ... ing> {} |
| tst2.ts:13:26:13:29 | List |
| tst2.ts:13:39:13:38 | (...arg ... rgs); } |

View File

@@ -2,22 +2,22 @@
| b.js:7:1:7:1 | f | b.js:1:1:5:1 | functio ... ar x;\\n} | M |
| b.js:8:1:8:1 | g | a.js:2:1:2:15 | function g() {} | M |
| client.ts:1:22:1:30 | "./tslib" | tslib.ts:1:1:10:0 | <toplevel> | I |
| client.ts:7:19:7:19 | C | tslib.ts:1:8:3:1 | class C {\\n m() {}\\n} | T |
| client.ts:8:10:8:10 | C | client.ts:3:1:5:1 | class C {\\n m() {}\\n} | T |
| client.ts:9:16:9:16 | C | client.ts:3:1:5:1 | class C {\\n m() {}\\n} | T |
| client.ts:10:16:10:16 | C | tslib.ts:6:10:8:3 | class C ... {}\\n } | T |
| client.ts:13:25:13:25 | C | client.ts:3:1:5:1 | class C {\\n m() {}\\n} | T |
| client.ts:13:35:13:35 | C | tslib.ts:1:8:3:1 | class C {\\n m() {}\\n} | T |
| client.ts:13:47:13:47 | C | tslib.ts:6:10:8:3 | class C ... {}\\n } | T |
| client.ts:7:19:7:19 | C | tslib.ts:1:14:1:14 | C | T |
| client.ts:8:10:8:10 | C | client.ts:3:7:3:7 | C | T |
| client.ts:9:16:9:16 | C | client.ts:3:7:3:7 | C | T |
| client.ts:10:16:10:16 | C | tslib.ts:6:16:6:16 | C | T |
| client.ts:13:25:13:25 | C | client.ts:3:7:3:7 | C | T |
| client.ts:13:35:13:35 | C | tslib.ts:1:14:1:14 | C | T |
| client.ts:13:47:13:47 | C | tslib.ts:6:16:6:16 | C | T |
| client.ts:14:3:14:3 | x | client.ts:13:22:13:22 | x | V |
| client.ts:14:5:14:5 | m | client.ts:4:3:4:8 | m() {} | M |
| client.ts:14:5:14:5 | m | client.ts:4:3:4:3 | m | M |
| client.ts:15:3:15:3 | y | client.ts:13:28:13:28 | y | V |
| client.ts:15:5:15:5 | m | tslib.ts:2:3:2:8 | m() {} | M |
| client.ts:15:5:15:5 | m | tslib.ts:2:3:2:3 | m | M |
| client.ts:16:3:16:3 | z | client.ts:13:38:13:38 | z | V |
| client.ts:16:5:16:5 | m | tslib.ts:7:5:7:10 | m() {} | M |
| client.ts:16:5:16:5 | m | tslib.ts:7:5:7:5 | m | M |
| d.js:1:17:1:21 | './c' | c.js:1:1:1:20 | <toplevel> | I |
| d.js:10:1:10:1 | A | d.js:7:1:9:1 | functio ... = 42;\\n} | V |
| d.js:16:19:16:23 | Super | d.js:12:1:14:1 | class S ... () {}\\n} | V |
| d.js:16:19:16:23 | Super | d.js:12:7:12:11 | Super | V |
| d.js:16:25:16:24 | args | d.js:16:25:16:24 | args | V |
| d.js:20:1:20:1 | o | d.js:3:9:5:1 | {\\n f: ... () {}\\n} | V |
| d.js:20:3:20:3 | f | d.js:4:3:4:18 | f: function() {} | M |
@@ -26,11 +26,11 @@
| d.js:23:3:23:3 | x | d.js:8:3:8:8 | this.x | M |
| d.js:24:1:24:1 | a | d.js:22:5:22:5 | a | V |
| d.js:24:3:24:3 | g | d.js:10:1:10:13 | A.prototype.g | M |
| d.js:26:13:26:15 | Sub | d.js:16:1:18:1 | class S ... () {}\\n} | M |
| d.js:26:13:26:15 | Sub | d.js:16:7:16:9 | Sub | M |
| d.js:27:1:27:1 | x | d.js:26:5:26:5 | x | V |
| d.js:27:3:27:3 | m | d.js:13:3:13:3 | m | M |
| d.js:28:1:28:1 | x | d.js:26:5:26:5 | x | V |
| d.js:28:3:28:3 | n | d.js:17:3:17:3 | n | M |
| tst.js:1:19:1:23 | './m' | m.js:1:1:2:0 | <toplevel> | I |
| tst.js:3:5:3:5 | A | m.js:1:8:1:17 | class A {} | M |
| tst.js:3:5:3:5 | A | m.js:1:14:1:14 | A | M |
| tst.js:5:15:5:19 | './m' | m.js:1:1:2:0 | <toplevel> | I |