Skip to content

Commit 59765e2

Browse files
author
Andy
authored
goToDefinition: Also add definitions for symbol if it does not match the signature symbol (#23657)
1 parent ac51980 commit 59765e2

File tree

5 files changed

+45
-22
lines changed

5 files changed

+45
-22
lines changed

src/services/goToDefinition.ts

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,22 @@ namespace ts.GoToDefinition {
1818
}
1919

2020
const typeChecker = program.getTypeChecker();
21-
22-
const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node);
23-
if (calledDeclaration) {
24-
return [createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration)];
25-
}
26-
27-
let symbol = typeChecker.getSymbolAtLocation(node);
21+
const symbol = getSymbol(node, typeChecker);
2822

2923
// Could not find a symbol e.g. node is string or number keyword,
3024
// or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
3125
if (!symbol) {
3226
return getDefinitionInfoForIndexSignatures(node, typeChecker);
3327
}
3428

35-
// If this is an alias, and the request came at the declaration location
36-
// get the aliased symbol instead. This allows for goto def on an import e.g.
37-
// import {A, B} from "mod";
38-
// to jump to the implementation directly.
39-
if (symbol.flags & SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) {
40-
const aliased = typeChecker.getAliasedSymbol(symbol);
41-
if (aliased.declarations) {
42-
symbol = aliased;
43-
}
29+
const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node);
30+
if (calledDeclaration) {
31+
const sigInfo = createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration);
32+
// For a function, if this is the original function definition, return just sigInfo.
33+
// If this is the original constructor definition, parent is the class.
34+
return typeChecker.getRootSymbols(symbol).some(s => calledDeclaration.symbol === s || calledDeclaration.symbol.parent === s)
35+
? [sigInfo]
36+
: [sigInfo, ...getDefinitionFromSymbol(typeChecker, symbol, node)];
4437
}
4538

4639
// Because name in short-hand property assignment has two different meanings: property name and property value,
@@ -158,6 +151,21 @@ namespace ts.GoToDefinition {
158151
});
159152
}
160153

154+
function getSymbol(node: Node, checker: TypeChecker): Symbol | undefined {
155+
const symbol = checker.getSymbolAtLocation(node);
156+
// If this is an alias, and the request came at the declaration location
157+
// get the aliased symbol instead. This allows for goto def on an import e.g.
158+
// import {A, B} from "mod";
159+
// to jump to the implementation directly.
160+
if (symbol && symbol.flags & SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) {
161+
const aliased = checker.getAliasedSymbol(symbol);
162+
if (aliased.declarations) {
163+
return aliased;
164+
}
165+
}
166+
return symbol;
167+
}
168+
161169
// Go to the original declaration for cases:
162170
//
163171
// (1) when the aliased symbol was declared in the location(parent).

tests/cases/fourslash/goToDefinitionNewExpressionTargetNotClass.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
////class C2 {
44
////}
5-
////let I: {
5+
////let /*I*/I: {
66
//// /*constructSignature*/new(): C2;
77
////};
88
////new [|/*invokeExpression1*/I|]();
@@ -11,6 +11,6 @@
1111
////new [|/*invokeExpression2*/I2|]();
1212

1313
verify.goToDefinition({
14-
invokeExpression1: "constructSignature",
14+
invokeExpression1: ["constructSignature", "I"],
1515
invokeExpression2: "symbolDeclaration"
1616
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
////function /*f*/f() {}
4+
////const /*g*/g = f;
5+
////const /*h*/h = g;
6+
7+
////[|/*useF*/f|]();
8+
////[|/*useG*/g|]();
9+
////[|/*useH*/h|]();
10+
11+
verify.goToDefinition({
12+
useF: "f",
13+
useG: ["f", "g"],
14+
useH: ["f", "h"],
15+
});

tests/cases/fourslash/goToDefinition_super.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
verify.goToDefinition({
2424
// Super in call position goes to constructor.
25-
super: "ctr",
25+
super: ["ctr", "B"],
2626
// Super in any other position goes to the superclass.
2727
superExpression: "B",
2828
superBroken: []

tests/cases/fourslash/tsxGoToDefinitionUnionElementType1.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
//// return <h1>World </h1>;
1919
//// }
2020

21-
//// var SFCComp = SFC1 || SFC2;
21+
//// var /*def*/SFCComp = SFC1 || SFC2;
2222
//// <[|SFC/*one*/Comp|] x />
2323

2424
verify.goToDefinition({
25-
"one": "pt1"
26-
})
25+
"one": ["pt1", "def"],
26+
});

0 commit comments

Comments
 (0)