diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts
index f97a8338b05..977f9617353 100644
--- a/src/services/goToDefinition.ts
+++ b/src/services/goToDefinition.ts
@@ -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).
diff --git a/tests/cases/fourslash/goToDefinitionNewExpressionTargetNotClass.ts b/tests/cases/fourslash/goToDefinitionNewExpressionTargetNotClass.ts
index 02a6dca9d52..00f83323a0b 100644
--- a/tests/cases/fourslash/goToDefinitionNewExpressionTargetNotClass.ts
+++ b/tests/cases/fourslash/goToDefinitionNewExpressionTargetNotClass.ts
@@ -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"
});
diff --git a/tests/cases/fourslash/goToDefinitionSignatureAlias.ts b/tests/cases/fourslash/goToDefinitionSignatureAlias.ts
new file mode 100644
index 00000000000..07a5678f5d2
--- /dev/null
+++ b/tests/cases/fourslash/goToDefinitionSignatureAlias.ts
@@ -0,0 +1,15 @@
+///