Skip to content

Commit 896a2b4

Browse files
authored
fix(42923): add go-to-definition on unresolved shorthand properties (#42924)
1 parent 5f5437a commit 896a2b4

File tree

4 files changed

+56
-20
lines changed

4 files changed

+56
-20
lines changed

src/services/goToDefinition.ts

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ namespace ts.GoToDefinition {
5151
// assignment. This case and others are handled by the following code.
5252
if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
5353
const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
54-
return shorthandSymbol ? shorthandSymbol.declarations.map(decl => createDefinitionInfo(decl, typeChecker, shorthandSymbol, node)) : [];
54+
const definitions = shorthandSymbol ? shorthandSymbol.declarations.map(decl => createDefinitionInfo(decl, typeChecker, shorthandSymbol, node)) : emptyArray;
55+
return concatenate(definitions, getDefinitionFromObjectLiteralElement(typeChecker, node) || emptyArray);
5556
}
5657

5758
// If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the
@@ -75,25 +76,7 @@ namespace ts.GoToDefinition {
7576
});
7677
}
7778

78-
// If the current location we want to find its definition is in an object literal, try to get the contextual type for the
79-
// object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
80-
// For example
81-
// interface Props{
82-
// /*first*/prop1: number
83-
// prop2: boolean
84-
// }
85-
// function Foo(arg: Props) {}
86-
// Foo( { pr/*1*/op1: 10, prop2: true })
87-
const element = getContainingObjectLiteralElement(node);
88-
if (element) {
89-
const contextualType = element && typeChecker.getContextualType(element.parent);
90-
if (contextualType) {
91-
return flatMap(getPropertySymbolsFromContextualType(element, typeChecker, contextualType, /*unionSymbolOk*/ false), propertySymbol =>
92-
getDefinitionFromSymbol(typeChecker, propertySymbol, node));
93-
}
94-
}
95-
96-
return getDefinitionFromSymbol(typeChecker, symbol, node);
79+
return getDefinitionFromObjectLiteralElement(typeChecker, node) || getDefinitionFromSymbol(typeChecker, symbol, node);
9780
}
9881

9982
/**
@@ -108,6 +91,26 @@ namespace ts.GoToDefinition {
10891
|| (!isCallLikeExpression(calledDeclaration.parent) && s === calledDeclaration.parent.symbol);
10992
}
11093

94+
// If the current location we want to find its definition is in an object literal, try to get the contextual type for the
95+
// object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
96+
// For example
97+
// interface Props{
98+
// /*first*/prop1: number
99+
// prop2: boolean
100+
// }
101+
// function Foo(arg: Props) {}
102+
// Foo( { pr/*1*/op1: 10, prop2: true })
103+
function getDefinitionFromObjectLiteralElement(typeChecker: TypeChecker, node: Node) {
104+
const element = getContainingObjectLiteralElement(node);
105+
if (element) {
106+
const contextualType = element && typeChecker.getContextualType(element.parent);
107+
if (contextualType) {
108+
return flatMap(getPropertySymbolsFromContextualType(element, typeChecker, contextualType, /*unionSymbolOk*/ false), propertySymbol =>
109+
getDefinitionFromSymbol(typeChecker, propertySymbol, node));
110+
}
111+
}
112+
}
113+
111114
export function getReferenceAtPosition(sourceFile: SourceFile, position: number, program: Program): { reference: FileReference, file: SourceFile } | undefined {
112115
const referencePath = findReferenceInPosition(sourceFile.referencedFiles, position);
113116
if (referencePath) {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path="./fourslash.ts"/>
2+
3+
////interface Foo {
4+
//// /*2*/foo(): void
5+
////}
6+
////
7+
////let x: Foo = {
8+
//// [|f/*1*/oo|]
9+
////}
10+
11+
verify.goToDefinition("1", "2");
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path="./fourslash.ts"/>
2+
3+
////interface Foo {
4+
//// /*3*/foo(): void
5+
////}
6+
////const /*2*/foo = 1;
7+
////let x: Foo = {
8+
//// [|f/*1*/oo|]
9+
////}
10+
11+
verify.goToDefinition("1", ["2", "3"]);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path="./fourslash.ts"/>
2+
3+
////interface Foo {
4+
//// /*2*/foo(): void
5+
////}
6+
////const foo = 1;
7+
////let x: Foo = {
8+
//// [|f/*1*/oo|]()
9+
////}
10+
11+
verify.goToDefinition("1", "2");

0 commit comments

Comments
 (0)