goToDefinition: Also add definitions for symbol if it does not match the signature symbol (#23657)
This commit is contained in:
parent
ac519804e0
commit
59765e2d86
5 changed files with 45 additions and 22 deletions
|
@ -18,13 +18,7 @@ namespace ts.GoToDefinition {
|
|||
}
|
||||
|
||||
const typeChecker = program.getTypeChecker();
|
||||
|
||||
const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node);
|
||||
if (calledDeclaration) {
|
||||
return [createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration)];
|
||||
}
|
||||
|
||||
let symbol = typeChecker.getSymbolAtLocation(node);
|
||||
const symbol = getSymbol(node, typeChecker);
|
||||
|
||||
// Could not find a symbol e.g. node is string or number keyword,
|
||||
// or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
|
||||
|
@ -32,15 +26,14 @@ namespace ts.GoToDefinition {
|
|||
return getDefinitionInfoForIndexSignatures(node, typeChecker);
|
||||
}
|
||||
|
||||
// If this is an alias, and the request came at the declaration location
|
||||
// get the aliased symbol instead. This allows for goto def on an import e.g.
|
||||
// import {A, B} from "mod";
|
||||
// to jump to the implementation directly.
|
||||
if (symbol.flags & SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) {
|
||||
const aliased = typeChecker.getAliasedSymbol(symbol);
|
||||
if (aliased.declarations) {
|
||||
symbol = aliased;
|
||||
}
|
||||
const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node);
|
||||
if (calledDeclaration) {
|
||||
const sigInfo = createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration);
|
||||
// For a function, if this is the original function definition, return just sigInfo.
|
||||
// If this is the original constructor definition, parent is the class.
|
||||
return typeChecker.getRootSymbols(symbol).some(s => calledDeclaration.symbol === s || calledDeclaration.symbol.parent === s)
|
||||
? [sigInfo]
|
||||
: [sigInfo, ...getDefinitionFromSymbol(typeChecker, symbol, node)];
|
||||
}
|
||||
|
||||
// Because name in short-hand property assignment has two different meanings: property name and property value,
|
||||
|
@ -158,6 +151,21 @@ namespace ts.GoToDefinition {
|
|||
});
|
||||
}
|
||||
|
||||
function getSymbol(node: Node, checker: TypeChecker): Symbol | undefined {
|
||||
const symbol = checker.getSymbolAtLocation(node);
|
||||
// If this is an alias, and the request came at the declaration location
|
||||
// get the aliased symbol instead. This allows for goto def on an import e.g.
|
||||
// import {A, B} from "mod";
|
||||
// to jump to the implementation directly.
|
||||
if (symbol && symbol.flags & SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) {
|
||||
const aliased = checker.getAliasedSymbol(symbol);
|
||||
if (aliased.declarations) {
|
||||
return aliased;
|
||||
}
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
// Go to the original declaration for cases:
|
||||
//
|
||||
// (1) when the aliased symbol was declared in the location(parent).
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
////class C2 {
|
||||
////}
|
||||
////let I: {
|
||||
////let /*I*/I: {
|
||||
//// /*constructSignature*/new(): C2;
|
||||
////};
|
||||
////new [|/*invokeExpression1*/I|]();
|
||||
|
@ -11,6 +11,6 @@
|
|||
////new [|/*invokeExpression2*/I2|]();
|
||||
|
||||
verify.goToDefinition({
|
||||
invokeExpression1: "constructSignature",
|
||||
invokeExpression1: ["constructSignature", "I"],
|
||||
invokeExpression2: "symbolDeclaration"
|
||||
});
|
||||
|
|
15
tests/cases/fourslash/goToDefinitionSignatureAlias.ts
Normal file
15
tests/cases/fourslash/goToDefinitionSignatureAlias.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function /*f*/f() {}
|
||||
////const /*g*/g = f;
|
||||
////const /*h*/h = g;
|
||||
|
||||
////[|/*useF*/f|]();
|
||||
////[|/*useG*/g|]();
|
||||
////[|/*useH*/h|]();
|
||||
|
||||
verify.goToDefinition({
|
||||
useF: "f",
|
||||
useG: ["f", "g"],
|
||||
useH: ["f", "h"],
|
||||
});
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
verify.goToDefinition({
|
||||
// Super in call position goes to constructor.
|
||||
super: "ctr",
|
||||
super: ["ctr", "B"],
|
||||
// Super in any other position goes to the superclass.
|
||||
superExpression: "B",
|
||||
superBroken: []
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
//// return <h1>World </h1>;
|
||||
//// }
|
||||
|
||||
//// var SFCComp = SFC1 || SFC2;
|
||||
//// var /*def*/SFCComp = SFC1 || SFC2;
|
||||
//// <[|SFC/*one*/Comp|] x />
|
||||
|
||||
verify.goToDefinition({
|
||||
"one": "pt1"
|
||||
})
|
||||
"one": ["pt1", "def"],
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue