mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #10593 from Microsoft/goto_definition_super
Make goto-definition go to a signature declaration if possible
This commit is contained in:
@@ -1035,6 +1035,18 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function isCallLikeExpression(node: Node): node is CallLikeExpression {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.NewExpression:
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.Decorator:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getInvokedExpression(node: CallLikeExpression): Expression {
|
||||
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
return (<TaggedTemplateExpression>node).tag;
|
||||
|
||||
@@ -1564,7 +1564,7 @@ namespace FourSlash {
|
||||
public goToDefinition(definitionIndex: number) {
|
||||
const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
if (!definitions || !definitions.length) {
|
||||
this.raiseError("goToDefinition failed - expected to at least one definition location but got 0");
|
||||
this.raiseError("goToDefinition failed - expected to find at least one definition location but got 0");
|
||||
}
|
||||
|
||||
if (definitionIndex >= definitions.length) {
|
||||
@@ -1579,7 +1579,7 @@ namespace FourSlash {
|
||||
public goToTypeDefinition(definitionIndex: number) {
|
||||
const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
if (!definitions || !definitions.length) {
|
||||
this.raiseError("goToTypeDefinition failed - expected to at least one definition location but got 0");
|
||||
this.raiseError("goToTypeDefinition failed - expected to find at least one definition location but got 0");
|
||||
}
|
||||
|
||||
if (definitionIndex >= definitions.length) {
|
||||
@@ -1600,7 +1600,7 @@ namespace FourSlash {
|
||||
this.raiseError(`goToDefinition - expected to 0 definition locations but got ${definitions.length}`);
|
||||
}
|
||||
else if (!foundDefinitions && !negative) {
|
||||
this.raiseError("goToDefinition - expected to at least one definition location but got 0");
|
||||
this.raiseError("goToDefinition - expected to find at least one definition location but got 0");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
-10
@@ -2792,20 +2792,36 @@ namespace ts {
|
||||
return node && node.parent && node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node;
|
||||
}
|
||||
|
||||
function climbPastPropertyAccess(node: Node) {
|
||||
return isRightSideOfPropertyAccess(node) ? node.parent : node;
|
||||
}
|
||||
|
||||
function climbPastManyPropertyAccesses(node: Node): Node {
|
||||
return isRightSideOfPropertyAccess(node) ? climbPastManyPropertyAccesses(node.parent) : node;
|
||||
}
|
||||
|
||||
function isCallExpressionTarget(node: Node): boolean {
|
||||
if (isRightSideOfPropertyAccess(node)) {
|
||||
node = node.parent;
|
||||
}
|
||||
node = climbPastPropertyAccess(node);
|
||||
return node && node.parent && node.parent.kind === SyntaxKind.CallExpression && (<CallExpression>node.parent).expression === node;
|
||||
}
|
||||
|
||||
function isNewExpressionTarget(node: Node): boolean {
|
||||
if (isRightSideOfPropertyAccess(node)) {
|
||||
node = node.parent;
|
||||
}
|
||||
node = climbPastPropertyAccess(node);
|
||||
return node && node.parent && node.parent.kind === SyntaxKind.NewExpression && (<CallExpression>node.parent).expression === node;
|
||||
}
|
||||
|
||||
/** Returns a CallLikeExpression where `node` is the target being invoked. */
|
||||
function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined {
|
||||
const target = climbPastManyPropertyAccesses(node);
|
||||
const callLike = target.parent;
|
||||
return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target && callLike;
|
||||
}
|
||||
|
||||
function tryGetSignatureDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined {
|
||||
const callLike = getAncestorCallLikeExpression(node);
|
||||
return callLike && typeChecker.getResolvedSignature(callLike).declaration;
|
||||
}
|
||||
|
||||
function isNameOfModuleDeclaration(node: Node) {
|
||||
return node.parent.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>node.parent).name === node;
|
||||
}
|
||||
@@ -5072,14 +5088,25 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function getSymbolInfo(typeChecker: TypeChecker, symbol: Symbol, node: Node) {
|
||||
return {
|
||||
symbolName: typeChecker.symbolToString(symbol), // Do not get scoped name, just the name of the symbol
|
||||
symbolKind: getSymbolKind(symbol, node),
|
||||
containerName: symbol.parent ? typeChecker.symbolToString(symbol.parent, node) : ""
|
||||
};
|
||||
}
|
||||
|
||||
function createDefinitionFromSignatureDeclaration(decl: SignatureDeclaration): DefinitionInfo {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const { symbolName, symbolKind, containerName } = getSymbolInfo(typeChecker, decl.symbol, decl);
|
||||
return createDefinitionInfo(decl, symbolKind, symbolName, containerName);
|
||||
}
|
||||
|
||||
function getDefinitionFromSymbol(symbol: Symbol, node: Node): DefinitionInfo[] {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const result: DefinitionInfo[] = [];
|
||||
const declarations = symbol.getDeclarations();
|
||||
const symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol
|
||||
const symbolKind = getSymbolKind(symbol, node);
|
||||
const containerSymbol = symbol.parent;
|
||||
const containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : "";
|
||||
const { symbolName, symbolKind, containerName } = getSymbolInfo(typeChecker, symbol, node);
|
||||
|
||||
if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) &&
|
||||
!tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) {
|
||||
@@ -5205,6 +5232,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
const typeChecker = program.getTypeChecker();
|
||||
|
||||
const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node);
|
||||
if (calledDeclaration) {
|
||||
return [createDefinitionFromSignatureDeclaration(calledDeclaration)];
|
||||
}
|
||||
|
||||
let symbol = typeChecker.getSymbolAtLocation(node);
|
||||
|
||||
// Could not find a symbol e.g. node is string or number keyword,
|
||||
|
||||
Reference in New Issue
Block a user