Skip to content

Commit 266c208

Browse files
committed
Actually lookup type for binding property name definition
1 parent 3926c50 commit 266c208

File tree

4 files changed

+34
-19
lines changed

4 files changed

+34
-19
lines changed

src/services/goToDefinition.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,6 @@ namespace ts.GoToDefinition {
3838
return [createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration)];
3939
}
4040

41-
// If the node is an identifier in bindingelement of ObjectBindingPattern (Note: ArrayBindingPattern can only declaration)
42-
// instead of just return the declaration symbol which is itself. We should try to get to the original type of the ObjectBindingPattern and return the property declaration.
43-
// For example:
44-
// import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo"
45-
//
46-
// function bar<T>(onfulfilled: (value: T) => void) { //....}
47-
// interface Test {
48-
// pr/*destination*/op1: number
49-
// }
50-
// bar<Test>(({pr/*goto*/op1})=>{});
5141
let symbol = typeChecker.getSymbolAtLocation(node);
5242

5343
// Could not find a symbol e.g. node is string or number keyword,
@@ -86,6 +76,26 @@ namespace ts.GoToDefinition {
8676
declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName));
8777
}
8878

79+
// If the node is an identifier in bindingelement of ObjectBindingPattern (Note: ArrayBindingPattern can only declaration)
80+
// instead of just return the declaration symbol which is itself. We should try to get to the original type of the ObjectBindingPattern and return the property declaration.
81+
// For example:
82+
// import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo"
83+
//
84+
// function bar<T>(onfulfilled: (value: T) => void) { //....}
85+
// interface Test {
86+
// pr/*destination*/op1: number
87+
// }
88+
// bar<Test>(({pr/*goto*/op1})=>{});
89+
if (isPropertyName(node) && isBindingElement(node.parent) && isObjectBindingPattern(node.parent.parent) && (node.parent.propertyName ? node.parent.propertyName === node : node.parent.name === node)) {
90+
const type = typeChecker.getTypeAtLocation(node.parent.parent);
91+
if (type) {
92+
const propSymbols = getPropertySymbolsFromType(type, node);
93+
if (propSymbols) {
94+
return flatMap(propSymbols, propSymbol => getDefinitionFromSymbol(typeChecker, propSymbol, node));
95+
}
96+
}
97+
}
98+
8999
// If the current location we want to find its definition is in an object literal, try to get the contextual type for the
90100
// object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
91101
// For example

src/services/services.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,12 +2138,17 @@ namespace ts {
21382138
export function getPropertySymbolsFromContextualType(typeChecker: TypeChecker, node: ObjectLiteralElement): Symbol[] {
21392139
const objectLiteral = <ObjectLiteralExpression | JsxAttributes>node.parent;
21402140
const contextualType = typeChecker.getContextualType(objectLiteral);
2141-
const name = unescapeLeadingUnderscores(getTextOfPropertyName(node.name));
2142-
if (name && contextualType) {
2141+
return getPropertySymbolsFromType(contextualType, node.name);
2142+
}
2143+
2144+
/* @internal */
2145+
export function getPropertySymbolsFromType(type: Type, propName: PropertyName) {
2146+
const name = unescapeLeadingUnderscores(getTextOfPropertyName(propName));
2147+
if (name && type) {
21432148
const result: Symbol[] = [];
2144-
const symbol = contextualType.getProperty(name);
2145-
if (contextualType.flags & TypeFlags.Union) {
2146-
forEach((<UnionType>contextualType).types, t => {
2149+
const symbol = type.getProperty(name);
2150+
if (type.flags & TypeFlags.Union) {
2151+
forEach((<UnionType>type).types, t => {
21472152
const symbol = t.getProperty(name);
21482153
if (symbol) {
21492154
result.push(symbol);

tests/cases/fourslash/gotoDefinitionInObjectBindingPattern1.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
//// }
66

77
//// interface Test {
8-
//// pro/*destination*/p2: number
8+
//// /*destination*/prop2: number
99
//// }
1010
//// bar<Test>(({pr/*goto*/op2})=>{});
1111

12-
verify.goToDefinition("goto", "destination")
12+
verify.goToDefinition("goto", "destination");
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/// <reference path='fourslash.ts' />
22

33
//// var p0 = ({a/*1*/a}) => {console.log(aa)};
4-
//// function f2({ a/*a1*/1, b/*b1*/1 }: { a/*a1_dest*/1: number, b/*b1_dest*/1: number } = { a1: 0, b1: 0 }) {}
4+
//// function f2({ a/*a1*/1, b/*b1*/1 }: { /*a1_dest*/a1: number, /*b1_dest*/b1: number } = { a1: 0, b1: 0 }) {}
55

6-
verify.goToDefinition("1", "1");
6+
verify.goToDefinition("1", []);
77
verify.goToDefinition("a1", "a1_dest");
88
verify.goToDefinition("b1", "b1_dest");

0 commit comments

Comments
 (0)