From 6cfa64daa3a9e1cd6967cd98c6d302cab1294709 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 17 Mar 2016 11:37:52 -0700 Subject: [PATCH 1/2] show completion in destructured parameter if containing function was contextually typed --- src/services/services.ts | 6 +++++- .../fourslash/objectLiteralBindingInParameter.ts | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/objectLiteralBindingInParameter.ts diff --git a/src/services/services.ts b/src/services/services.ts index 1c079b8402..08d3fc843c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3504,7 +3504,11 @@ namespace ts { // We don't want to complete using the type acquired by the shape // of the binding pattern; we are only interested in types acquired // through type declaration or inference. - if (rootDeclaration.initializer || rootDeclaration.type) { + // Also proceed if rootDeclaration is parameter and if its containing function expression\arrow function is contextually typed - + // type of parameter will flow in from the contextual type of the function + if (rootDeclaration.initializer || + rootDeclaration.type || + (rootDeclaration.kind === SyntaxKind.Parameter && isExpression(rootDeclaration.parent) && typeChecker.getContextualType(rootDeclaration.parent))) { typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); existingMembers = (objectLikeContainer).elements; } diff --git a/tests/cases/fourslash/objectLiteralBindingInParameter.ts b/tests/cases/fourslash/objectLiteralBindingInParameter.ts new file mode 100644 index 0000000000..dfde6095bb --- /dev/null +++ b/tests/cases/fourslash/objectLiteralBindingInParameter.ts @@ -0,0 +1,15 @@ +/// + +////interface I { x1: number; x2: string } +////function f(cb: (ev: I) => any) { } +////f(({/*1*/}) => 0); + +////[null].reduce(({/*2*/}, b) => b); + +goTo.marker("1"); +verify.completionListContains("x1"); +verify.completionListContains("x2"); + +goTo.marker("2"); +verify.completionListContains("x1"); +verify.completionListContains("x2"); \ No newline at end of file From 112e4b1e80c132eed27f20af9f17d4dc0271dfca Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 17 Mar 2016 14:40:05 -0700 Subject: [PATCH 2/2] Addressed PR feedback --- src/services/services.ts | 13 +++++++++--- .../objectLiteralBindingInParameter.ts | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 08d3fc843c..72255b5547 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3506,9 +3506,16 @@ namespace ts { // through type declaration or inference. // Also proceed if rootDeclaration is parameter and if its containing function expression\arrow function is contextually typed - // type of parameter will flow in from the contextual type of the function - if (rootDeclaration.initializer || - rootDeclaration.type || - (rootDeclaration.kind === SyntaxKind.Parameter && isExpression(rootDeclaration.parent) && typeChecker.getContextualType(rootDeclaration.parent))) { + let canGetType = !!(rootDeclaration.initializer || rootDeclaration.type); + if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) { + if (isExpression(rootDeclaration.parent)) { + canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); + } + else if (rootDeclaration.parent.kind === SyntaxKind.MethodDeclaration || rootDeclaration.parent.kind === SyntaxKind.SetAccessor) { + canGetType = isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); + } + } + if (canGetType) { typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); existingMembers = (objectLikeContainer).elements; } diff --git a/tests/cases/fourslash/objectLiteralBindingInParameter.ts b/tests/cases/fourslash/objectLiteralBindingInParameter.ts index dfde6095bb..b1cbd21d92 100644 --- a/tests/cases/fourslash/objectLiteralBindingInParameter.ts +++ b/tests/cases/fourslash/objectLiteralBindingInParameter.ts @@ -6,10 +6,30 @@ ////[null].reduce(({/*2*/}, b) => b); +////interface Foo { +//// m(x: { x1: number, x2: number }): void; +//// prop: I; +////} +////let x: Foo = { +//// m({ /*3*/ }) { +//// }, +//// get prop(): I { return undefined; }, +//// set prop({ /*4*/ }) { +//// } +////}; + goTo.marker("1"); verify.completionListContains("x1"); verify.completionListContains("x2"); goTo.marker("2"); verify.completionListContains("x1"); +verify.completionListContains("x2"); + +goTo.marker("3"); +verify.completionListContains("x1"); +verify.completionListContains("x2"); + +goTo.marker("4"); +verify.completionListContains("x1"); verify.completionListContains("x2"); \ No newline at end of file