allow calling goToDef on modifiers of named declarations (#60384)

This commit is contained in:
Isabel Duan
2025-01-23 17:30:35 -08:00
committed by GitHub
parent f28c5180df
commit c5058f0066
14 changed files with 1249 additions and 36 deletions

View File

@@ -64,7 +64,9 @@ import {
isJSDocOverrideTag,
isJsxOpeningLikeElement,
isJumpStatementTarget,
isModifier,
isModuleSpecifierLike,
isNamedDeclaration,
isNameOfFunctionDeclaration,
isNewExpressionTarget,
isObjectBindingPattern,
@@ -128,7 +130,10 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile
const typeChecker = program.getTypeChecker();
if (node.kind === SyntaxKind.OverrideKeyword || (isIdentifier(node) && isJSDocOverrideTag(parent) && parent.tagName === node)) {
return getDefinitionFromOverriddenMember(typeChecker, node) || emptyArray;
const def = getDefinitionFromOverriddenMember(typeChecker, node);
if (def !== undefined || node.kind !== SyntaxKind.OverrideKeyword) {
return def || emptyArray;
}
}
// Labels
@@ -137,15 +142,8 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile
return label ? [createDefinitionInfoFromName(typeChecker, label, ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217
}
// for switch statments
switch (node.kind) {
case SyntaxKind.ReturnKeyword:
const functionDeclaration = findAncestor(node.parent, n =>
isClassStaticBlockDeclaration(n)
? "quit"
: isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined;
return functionDeclaration
? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)]
: undefined;
case SyntaxKind.DefaultKeyword:
if (!isDefaultClause(node.parent)) {
break;
@@ -159,16 +157,15 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile
break;
}
if (node.kind === SyntaxKind.AwaitKeyword) {
const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n));
const isAsyncFunction = functionDeclaration && some(functionDeclaration.modifiers, node => node.kind === SyntaxKind.AsyncKeyword);
return isAsyncFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
}
if (node.kind === SyntaxKind.YieldKeyword) {
const functionDeclaration = findAncestor(node, n => isFunctionLikeDeclaration(n));
const isGeneratorFunction = functionDeclaration && functionDeclaration.asteriskToken;
return isGeneratorFunction ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
// for keywords related to function or method definitions
let findFunctionDecl: ((n: Node) => boolean | "quit") | undefined;
switch (node.kind) {
case SyntaxKind.ReturnKeyword:
case SyntaxKind.AwaitKeyword:
case SyntaxKind.YieldKeyword:
findFunctionDecl = isFunctionLikeDeclaration;
const functionDeclaration = findAncestor(node, findFunctionDecl) as FunctionLikeDeclaration | undefined;
return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined;
}
if (isStaticModifier(node) && isClassStaticBlockDeclaration(node.parent)) {
@@ -217,6 +214,10 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile
}
}
if (isModifier(node) && (isClassElement(parent) || isNamedDeclaration(parent))) {
symbol = parent.symbol;
}
// 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
if (!symbol) {
@@ -457,7 +458,11 @@ export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile
if (isImportMeta(node.parent) && node.parent.name === node) {
return definitionFromType(typeChecker.getTypeAtLocation(node.parent), typeChecker, node.parent, /*failedAliasResolution*/ false);
}
const { symbol, failedAliasResolution } = getSymbol(node, typeChecker, /*stopAtAlias*/ false);
let { symbol, failedAliasResolution } = getSymbol(node, typeChecker, /*stopAtAlias*/ false);
if (isModifier(node) && (isClassElement(node.parent) || isNamedDeclaration(node.parent))) {
symbol = node.parent.symbol;
failedAliasResolution = false;
}
if (!symbol) return undefined;
const typeAtLocation = typeChecker.getTypeOfSymbolAtLocation(symbol, node);