mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-14 16:56:06 -05:00
goToTypeDefinition: Go to function return type (#25952)
* goToTypeDefinition: Go to function return type * Add more tests * If a function returns 'void' or some other type with no definition, just return the function definition.
This commit is contained in:
@@ -1674,7 +1674,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
for (const { name, text } of outputFiles) {
|
||||
const fromTestFile = this.getFileContent(name);
|
||||
if (fromTestFile !== text) {
|
||||
this.raiseError("Emit output is not as expected: " + showTextDiff(fromTestFile, text));
|
||||
this.raiseError(`Emit output for ${name} is not as expected: ${showTextDiff(fromTestFile, text)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,9 +136,30 @@ namespace ts.GoToDefinition {
|
||||
}
|
||||
|
||||
const symbol = typeChecker.getSymbolAtLocation(node);
|
||||
const type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, node);
|
||||
return type && flatMap(type.isUnion() && !(type.flags & TypeFlags.Enum) ? type.types : [type], t =>
|
||||
t.symbol && getDefinitionFromSymbol(typeChecker, t.symbol, node));
|
||||
if (!symbol) return undefined;
|
||||
|
||||
const typeAtLocation = typeChecker.getTypeOfSymbolAtLocation(symbol, node);
|
||||
const returnType = tryGetReturnTypeOfFunction(symbol, typeAtLocation, typeChecker);
|
||||
const fromReturnType = returnType && definitionFromType(returnType, typeChecker, node);
|
||||
// If a function returns 'void' or some other type with no definition, just return the function definition.
|
||||
return fromReturnType && fromReturnType.length !== 0 ? fromReturnType : definitionFromType(typeAtLocation, typeChecker, node);
|
||||
}
|
||||
|
||||
function definitionFromType(type: Type, checker: TypeChecker, node: Node): DefinitionInfo[] {
|
||||
return flatMap(type.isUnion() && !(type.flags & TypeFlags.Enum) ? type.types : [type], t =>
|
||||
t.symbol && getDefinitionFromSymbol(checker, t.symbol, node));
|
||||
}
|
||||
|
||||
function tryGetReturnTypeOfFunction(symbol: Symbol, type: Type, checker: TypeChecker): Type | undefined {
|
||||
// If the type is just a function's inferred type,
|
||||
// go-to-type should go to the return type instead, since go-to-definition takes you to the function anyway.
|
||||
if (type.symbol === symbol ||
|
||||
// At `const f = () => {}`, the symbol is `f` and the type symbol is at `() => {}`
|
||||
symbol.valueDeclaration && type.symbol && isVariableDeclaration(symbol.valueDeclaration) && symbol.valueDeclaration.initializer === type.symbol.valueDeclaration as Node) {
|
||||
const sigs = type.getCallSignatures();
|
||||
if (sigs.length === 1) return checker.getReturnTypeOfSignature(first(sigs));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFile, position: number): DefinitionInfoAndBoundSpan | undefined {
|
||||
|
||||
Reference in New Issue
Block a user