diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dfccfca1b8f..97bebeadfb3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12755,7 +12755,7 @@ namespace ts { * @param node the expression whose contextual type will be returned. * @returns the contextual type of an expression. */ - function getContextualType(node: Expression): Type { + function getContextualType(node: Expression): Type | undefined { if (isInsideWithStatementBody(node)) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 74670352c34..d89c7877da6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2528,7 +2528,7 @@ namespace ts { getFullyQualifiedName(symbol: Symbol): string; getAugmentedPropertiesOfType(type: Type): Symbol[]; getRootSymbols(symbol: Symbol): Symbol[]; - getContextualType(node: Expression): Type; + getContextualType(node: Expression): Type | undefined; getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 09d1f2a248c..07b1e4448bd 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -85,17 +85,6 @@ namespace ts.GoToDefinition { declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName)); } - if (isJsxOpeningLikeElement(node.parent)) { - // If there are errors when trying to figure out stateless component function, just return the first declaration - // For example: - // declare function /*firstSource*/MainButton(buttonProps: ButtonProps): JSX.Element; - // declare function /*secondSource*/MainButton(linkProps: LinkProps): JSX.Element; - // declare function /*thirdSource*/MainButton(props: ButtonProps | LinkProps): JSX.Element; - // let opt =
; // Error - We get undefined for resolved signature indicating an error, then just return the first declaration - const {symbolName, symbolKind, containerName} = getSymbolInfo(typeChecker, symbol, node); - return [createDefinitionInfo(symbol.valueDeclaration, symbolKind, symbolName, containerName)]; - } - // If the current location we want to find its definition is in an object literal, try to get the contextual type for the // object literal, lookup the property symbol in the contextual type, and use this for goto-definition. // For example @@ -106,15 +95,9 @@ namespace ts.GoToDefinition { // function Foo(arg: Props) {} // Foo( { pr/*1*/op1: 10, prop2: true }) const element = getContainingObjectLiteralElement(node); - if (element) { - if (typeChecker.getContextualType(element.parent as Expression)) { - const result: DefinitionInfo[] = []; - const propertySymbols = getPropertySymbolsFromContextualType(typeChecker, element); - for (const propertySymbol of propertySymbols) { - result.push(...getDefinitionFromSymbol(typeChecker, propertySymbol, node)); - } - return result; - } + if (element && typeChecker.getContextualType(element.parent as Expression)) { + return flatMap(getPropertySymbolsFromContextualType(typeChecker, element), propertySymbol => + getDefinitionFromSymbol(typeChecker, propertySymbol, node)); } return getDefinitionFromSymbol(typeChecker, symbol, node); } diff --git a/tests/cases/fourslash/tsxGoToDefinitionClassInDifferentFile.ts b/tests/cases/fourslash/tsxGoToDefinitionClassInDifferentFile.ts new file mode 100644 index 00000000000..f217e4096fc --- /dev/null +++ b/tests/cases/fourslash/tsxGoToDefinitionClassInDifferentFile.ts @@ -0,0 +1,15 @@ +/// + +// @jsx: preserve + +// @Filename: C.tsx +////export default class C {} + +// @Filename: a.tsx +////import /*def*/C from "./C"; +////const foo = ; + +verify.noErrors(); + +goTo.marker("use"); +verify.goToDefinitionIs("def");