From 1bcbd8fa9dff2a9b398b32a8d4dc8f6f5de8e27b Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Sun, 20 Dec 2020 19:40:04 +0800 Subject: [PATCH 01/22] feat: exclude declared variable when Object literal completions --- src/services/completions.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/services/completions.ts b/src/services/completions.ts index 01584d6a5e16b..8e1c399117451 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1508,6 +1508,10 @@ namespace ts.Completions { return true; } + if (isAncestor(location, symbol)) { + return false; + } + symbol = skipAlias(symbol, typeChecker); // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace) @@ -1526,6 +1530,12 @@ namespace ts.Completions { }); } + function isAncestor(node: Node, symbol: Symbol): boolean { + return !!findAncestor(node, (n) => { + return Array.isArray(symbol.declarations) && symbol.declarations.some(declaration => n === declaration) + }) + } + function isTypeOnlyCompletion(): boolean { return insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && From 505b1b63491bb737dc5a37f8f83d843f07d19f63 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Mon, 21 Dec 2020 00:03:44 +0800 Subject: [PATCH 02/22] feat: check undeclareVariable when completion --- src/services/completions.ts | 46 ++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 8e1c399117451..a93f0ca0a3baf 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1501,6 +1501,8 @@ namespace ts.Completions { : KeywordCompletionFilters.TypeKeywords; } + const undeclaredVariable = findUndeclaredVariableIfExist(location); + filterMutate(symbols, symbol => { if (!isSourceFile(location)) { // export = /**/ here we want to get all meanings, so any symbol is ok @@ -1508,10 +1510,10 @@ namespace ts.Completions { return true; } - if (isAncestor(location, symbol)) { + if (isUndeclaredSymbol(undeclaredVariable, symbol)) { return false; } - + symbol = skipAlias(symbol, typeChecker); // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace) @@ -1530,10 +1532,42 @@ namespace ts.Completions { }); } - function isAncestor(node: Node, symbol: Symbol): boolean { - return !!findAncestor(node, (n) => { - return Array.isArray(symbol.declarations) && symbol.declarations.some(declaration => n === declaration) - }) + function findUndeclaredVariableIfExist(node: Node): VariableDeclaration | undefined { + if (!isIdentifier(node)) { + return undefined; + } + + let curNode: Node = node.parent; + while (curNode && curNode.parent) { + if (isPropertyAssignment(curNode) && isObjectLiteralExpression(curNode.parent)) { + curNode = curNode.parent.parent; + + if (isVariableDeclaration(curNode)) { + return curNode; + } + } + else { + return undefined; + } + } + + return undefined; + } + + function isUndeclaredSymbol(undeclaredVariable: VariableDeclaration | undefined, symbol: Symbol): boolean { + if (!undeclaredVariable) { + return false; + } + + if (!symbol.declarations || symbol.declarations.length === 0) { + return false; + } + + if (symbol.declarations.indexOf(undeclaredVariable) > -1) { + return true; + } + + return false; } function isTypeOnlyCompletion(): boolean { From c8079a40c31103f309c4828dfe6b4e35eb9b7164 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Tue, 22 Dec 2020 10:16:08 +0800 Subject: [PATCH 03/22] feat: add completion test case --- .../completionListInObjectLiteral5.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/cases/fourslash/completionListInObjectLiteral5.ts diff --git a/tests/cases/fourslash/completionListInObjectLiteral5.ts b/tests/cases/fourslash/completionListInObjectLiteral5.ts new file mode 100644 index 0000000000000..0bbe23fe97e0b --- /dev/null +++ b/tests/cases/fourslash/completionListInObjectLiteral5.ts @@ -0,0 +1,24 @@ +/// + +////const o = 'something' +////const obj = { +//// prop: o/*1*/, +//// pro() { +//// const obj1 = { +//// p:{ +//// s: { +//// h: { +//// hh: o/*2*/ +//// }, +//// someFun() { +//// o/*3*/ +//// } +//// } +//// } +//// } +//// } +////} + +verify.completions({ marker: ["1"], excludes: ['obj'], includes: ['o'] }); +verify.completions({ marker: ["2"], excludes: ['obj1'], includes: ['o', 'obj'] }); +verify.completions({ marker: ["3"], includes: ['o', 'obj', 'obj1'] }); \ No newline at end of file From 7f2434d35602bedee251c91d50ded9fb1c803ff1 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 23 Dec 2020 09:55:13 +0800 Subject: [PATCH 04/22] feat: code optimization --- src/services/completions.ts | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index a93f0ca0a3baf..1676b5c5400ff 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1501,7 +1501,7 @@ namespace ts.Completions { : KeywordCompletionFilters.TypeKeywords; } - const undeclaredVariable = findUndeclaredVariableIfExist(location); + const objectLiteralVariableDeclaration = getVariableDeclarationOfObjectLiteral(location); filterMutate(symbols, symbol => { if (!isSourceFile(location)) { @@ -1510,7 +1510,8 @@ namespace ts.Completions { return true; } - if (isUndeclaredSymbol(undeclaredVariable, symbol)) { + // Filter out variables from their own initializers, e.g. `const o = { prop: /* no 'o' here */ }` + if (objectLiteralVariableDeclaration && symbol.valueDeclaration === objectLiteralVariableDeclaration) { return false; } @@ -1532,12 +1533,12 @@ namespace ts.Completions { }); } - function findUndeclaredVariableIfExist(node: Node): VariableDeclaration | undefined { - if (!isIdentifier(node)) { + function getVariableDeclarationOfObjectLiteral(property: Node): VariableDeclaration | undefined { + if (!isIdentifier(property)) { return undefined; } - let curNode: Node = node.parent; + let curNode: Node = property.parent; while (curNode && curNode.parent) { if (isPropertyAssignment(curNode) && isObjectLiteralExpression(curNode.parent)) { curNode = curNode.parent.parent; @@ -1554,21 +1555,6 @@ namespace ts.Completions { return undefined; } - function isUndeclaredSymbol(undeclaredVariable: VariableDeclaration | undefined, symbol: Symbol): boolean { - if (!undeclaredVariable) { - return false; - } - - if (!symbol.declarations || symbol.declarations.length === 0) { - return false; - } - - if (symbol.declarations.indexOf(undeclaredVariable) > -1) { - return true; - } - - return false; - } function isTypeOnlyCompletion(): boolean { return insideJsDocTagTypeExpression From fe0f9232516c9f134eb38912b264d4e206bb9618 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 23 Dec 2020 10:11:57 +0800 Subject: [PATCH 05/22] feat: support shorthand property assignment --- src/services/completions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index e3dea1037aff3..c5680ba9c4686 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1543,7 +1543,7 @@ namespace ts.Completions { let curNode: Node = property.parent; while (curNode && curNode.parent) { - if (isPropertyAssignment(curNode) && isObjectLiteralExpression(curNode.parent)) { + if ((isPropertyAssignment(curNode) || isShorthandPropertyAssignment(curNode)) && isObjectLiteralExpression(curNode.parent)) { curNode = curNode.parent.parent; if (isVariableDeclaration(curNode)) { From 71c0db9bda67ba0c71b5e5a5ebde5352347187c7 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 23 Dec 2020 10:12:25 +0800 Subject: [PATCH 06/22] feat: add shorthand property assignment test case --- tests/cases/fourslash/completionListInObjectLiteral5.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/cases/fourslash/completionListInObjectLiteral5.ts b/tests/cases/fourslash/completionListInObjectLiteral5.ts index 0bbe23fe97e0b..eb245d748bf41 100644 --- a/tests/cases/fourslash/completionListInObjectLiteral5.ts +++ b/tests/cases/fourslash/completionListInObjectLiteral5.ts @@ -16,9 +16,11 @@ //// } //// } //// } -//// } +//// }, +//// o/*4*/ ////} verify.completions({ marker: ["1"], excludes: ['obj'], includes: ['o'] }); verify.completions({ marker: ["2"], excludes: ['obj1'], includes: ['o', 'obj'] }); -verify.completions({ marker: ["3"], includes: ['o', 'obj', 'obj1'] }); \ No newline at end of file +verify.completions({ marker: ["3"], includes: ['o', 'obj', 'obj1'] }); +verify.completions({ marker: ["4"], includes: ['o'], excludes: ['obj'] }); \ No newline at end of file From 43a8234b5bce3d725d1a89e364e9e65bf2cca049 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 23 Dec 2020 11:03:23 +0800 Subject: [PATCH 07/22] feat: update completionPropertyShorthandForObjectLiteral test cases --- .../completionPropertyShorthandForObjectLiteral2.ts | 9 +++++++-- .../completionPropertyShorthandForObjectLiteral3.ts | 2 +- .../completionPropertyShorthandForObjectLiteral4.ts | 2 +- .../completionPropertyShorthandForObjectLiteral5.ts | 7 +++---- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral2.ts b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral2.ts index ec54418c77935..40aa223b7eced 100644 --- a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral2.ts +++ b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral2.ts @@ -12,6 +12,11 @@ //// }; verify.completions({ - marker: test.markers(), - exact: completion.globalsPlus(["foo", "bar", "obj1", "obj2"]), + marker: ["1"], + exact: completion.globalsPlus(["foo", "bar", "obj2"]), +}); + +verify.completions({ + marker: ["2"], + exact: completion.globalsPlus(["foo", "bar", "obj1"]), }); diff --git a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral3.ts b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral3.ts index 0a6fad60b293e..70c1f60055425 100644 --- a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral3.ts +++ b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral3.ts @@ -7,5 +7,5 @@ verify.completions({ marker: ["1"], - exact: completion.globalsPlus(["foo", "bar", "obj"]) + exact: completion.globalsPlus(["foo", "bar"]), }); diff --git a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral4.ts b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral4.ts index 35daa6185a3f1..a720bcc1dc6b2 100644 --- a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral4.ts +++ b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral4.ts @@ -7,5 +7,5 @@ verify.completions({ marker: ["1"], - exact: completion.globalsPlus(["foo", "bar", "obj"]) + exact: completion.globalsPlus(["foo", "bar"]), }); diff --git a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts index 74ded23477463..47aeeb83677a7 100644 --- a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts +++ b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts @@ -7,7 +7,6 @@ //// const obj = { exp/**/ verify.completions({ - marker: "", - exact: completion.globalsPlus(["obj"]), - preferences: { includeCompletionsForModuleExports: true } -}); \ No newline at end of file + marker: "", + preferences: { includeCompletionsForModuleExports: true }, +}); From c4cd16e18730acccb8b6e1d0b5f14ca76029d776 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 23 Dec 2020 15:43:47 +0800 Subject: [PATCH 08/22] feat: exclude completions of variable initializers --- src/services/completions.ts | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index c5680ba9c4686..a5e2d79ed6b12 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1504,7 +1504,7 @@ namespace ts.Completions { : KeywordCompletionFilters.TypeKeywords; } - const objectLiteralVariableDeclaration = getVariableDeclarationOfObjectLiteral(location); + const variableDeclaration = getVariableDeclaration(location); filterMutate(symbols, symbol => { if (!isSourceFile(location)) { @@ -1513,8 +1513,13 @@ namespace ts.Completions { return true; } - // Filter out variables from their own initializers, e.g. `const o = { prop: /* no 'o' here */ }` - if (objectLiteralVariableDeclaration && symbol.valueDeclaration === objectLiteralVariableDeclaration) { + // Filter out variables from their own initializers + // e.g. + // 1. `const o = { prop: /* no 'o' here */ }` + // 2. `const a = /* no 'a' here */` + // 3. `const b = a && /* no 'b' here */` + // 4. `const c = [{ prop: [/* no 'c' here */] }]` + if (variableDeclaration && symbol.valueDeclaration === variableDeclaration) { return false; } @@ -1536,29 +1541,25 @@ namespace ts.Completions { }); } - function getVariableDeclarationOfObjectLiteral(property: Node): VariableDeclaration | undefined { + function getVariableDeclaration(property: Node): VariableDeclaration | undefined { if (!isIdentifier(property)) { return undefined; } - let curNode: Node = property.parent; - while (curNode && curNode.parent) { - if ((isPropertyAssignment(curNode) || isShorthandPropertyAssignment(curNode)) && isObjectLiteralExpression(curNode.parent)) { - curNode = curNode.parent.parent; - - if (isVariableDeclaration(curNode)) { - return curNode; - } + const variableDeclaration = findAncestor(property, (node) => { + if (isFunctionLikeDeclaration(node)) { + return "quit"; } - else { - return undefined; + + if (isVariableDeclaration(node)) { + return true; } - } + return false; + }); - return undefined; + return variableDeclaration as VariableDeclaration; } - function isTypeOnlyCompletion(): boolean { return insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && From 6f0f2045508f954bcc28970072c4ad84a8395b0f Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 23 Dec 2020 15:44:45 +0800 Subject: [PATCH 09/22] feat: update test cases --- tests/cases/fourslash/commentsClassMembers.ts | 3 ++- ...ionListBuilderLocations_VariableDeclarations.ts | 9 ++++++++- .../fourslash/completionListIsGlobalCompletion.ts | 5 +++-- .../cases/fourslash/completionListWithMeanings.ts | 14 ++++++++++++-- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/cases/fourslash/commentsClassMembers.ts b/tests/cases/fourslash/commentsClassMembers.ts index 1e17f0327fe7e..3cc9b27172958 100644 --- a/tests/cases/fourslash/commentsClassMembers.ts +++ b/tests/cases/fourslash/commentsClassMembers.ts @@ -201,7 +201,8 @@ verify.completions( ], }, { marker: ["29", "33", "38", "109"], includes: locals }, - { marker: ["35", "40", "87"], includes: locals, isNewIdentifierLocation: true }, + { marker: ["35", "40"], includes: locals, isNewIdentifierLocation: true }, + { marker: ["87"], includes: locals.filter(local => local === 'i1_s_p') , isNewIdentifierLocation: true }, { marker: "31", includes: { name: "b", text: "(parameter) b: number", documentation: "number to add" } }, { marker: "42", includes: { name: "value", text: "(parameter) value: number", documentation: "this is value" }, isNewIdentifierLocation: true }, { marker: ["45", "52", "59"], includes: { name: "b", text: "(parameter) b: number" } }, diff --git a/tests/cases/fourslash/completionListBuilderLocations_VariableDeclarations.ts b/tests/cases/fourslash/completionListBuilderLocations_VariableDeclarations.ts index af119f40be57f..eaad02afcc52f 100644 --- a/tests/cases/fourslash/completionListBuilderLocations_VariableDeclarations.ts +++ b/tests/cases/fourslash/completionListBuilderLocations_VariableDeclarations.ts @@ -26,8 +26,15 @@ ////var y = 10; y=/*var12*/ +// first declaration verify.completions({ - marker: test.markers(), + marker: ["var1"], + exact: completion.globalsPlus(["y", "C"]), + isNewIdentifierLocation: true +}); + +verify.completions({ + marker: ["var2", "var3", "var4", "var5", "var6", "var7", "var8", "var9", "var10", "var11", "var12"], exact: completion.globalsPlus(["x", "y", "C"]), isNewIdentifierLocation: true }); diff --git a/tests/cases/fourslash/completionListIsGlobalCompletion.ts b/tests/cases/fourslash/completionListIsGlobalCompletion.ts index 91cd1a0f9c7e5..eaf83fa526b07 100644 --- a/tests/cases/fourslash/completionListIsGlobalCompletion.ts +++ b/tests/cases/fourslash/completionListIsGlobalCompletion.ts @@ -41,12 +41,13 @@ verify.completions( { marker: ["1", "3", "6", "8", "12", "14"], exact: undefined, isGlobalCompletion: false }, { marker: "2", exact: ["a.ts", "file.ts"], isGlobalCompletion: false, isNewIdentifierLocation: true }, { marker: ["4", "19"], exact: [], isGlobalCompletion: false }, - { marker: ["5", "11", "18"], exact: globals, isGlobalCompletion: true }, + { marker: ["5", "11"], exact: globals, isGlobalCompletion: true }, + { marker: ["18"], exact: globals.filter(name => name !== 'user'), isGlobalCompletion: true }, { marker: "7", exact: completion.globalsInsideFunction(x), isGlobalCompletion: true }, { marker: "9", exact: ["x", "y"], isGlobalCompletion: false }, { marker: "10", exact: completion.classElementKeywords, isGlobalCompletion: false, isNewIdentifierLocation: true }, { marker: "13", exact: globals, isGlobalCompletion: false }, - { marker: "15", exact: globals, isGlobalCompletion: true, isNewIdentifierLocation: true }, + { marker: "15", exact: globals.filter(name => name !== 'x'), isGlobalCompletion: true, isNewIdentifierLocation: true }, { marker: "16", exact: [...x, completion.globalThisEntry, ...completion.globalsVars, completion.undefinedVarEntry], isGlobalCompletion: false }, { marker: "17", exact: completion.globalKeywords, isGlobalCompletion: false }, ); diff --git a/tests/cases/fourslash/completionListWithMeanings.ts b/tests/cases/fourslash/completionListWithMeanings.ts index 034607d08c021..82c69d43a48de 100644 --- a/tests/cases/fourslash/completionListWithMeanings.ts +++ b/tests/cases/fourslash/completionListWithMeanings.ts @@ -36,10 +36,20 @@ const types: ReadonlyArray = [ ...completion.typeKeywords, ]; +const filterValuesByName = (name: string) => { + return values.filter(entry => { + if (typeof entry === 'string') { + return entry !== name; + } + + return entry.name !== name; + }) +} + verify.completions( - { marker: "valueExpr", exact: values, isNewIdentifierLocation: true }, + { marker: "valueExpr", exact: filterValuesByName('tt'), isNewIdentifierLocation: true }, { marker: "typeExpr", exact: types, }, - { marker: "valueExprInObjectLiteral", exact: values }, + { marker: "valueExprInObjectLiteral", exact: filterValuesByName('yy') }, { marker: "membertypeExpr", exact: [{ name: "point3", text: "interface m3.point3" }] }, { marker: "membervalueExpr", exact: [{ name: "zz2", text: "var m3.zz2: number" }] }, ); From a3d428251ca6a0318c02e513cc1c2eeec81df1fc Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 23 Dec 2020 15:45:25 +0800 Subject: [PATCH 10/22] feat: add completionListWithoutVariableinitializer test case --- ...ompletionListWithoutVariableinitializer.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/cases/fourslash/completionListWithoutVariableinitializer.ts diff --git a/tests/cases/fourslash/completionListWithoutVariableinitializer.ts b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts new file mode 100644 index 0000000000000..96151138c581d --- /dev/null +++ b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts @@ -0,0 +1,25 @@ +/// + +//// const a = a/*1*/; +//// const b = a && b/*2*/; +//// const c = [{ prop: [c/*3*/] }]; + +verify.completions({ + marker: ["1"], + excludes: ["a"], + isNewIdentifierLocation: true, +}); + +verify.completions({ + marker: ["2"], + excludes: ["b"], + includes: ["a"], + isNewIdentifierLocation: false, +}); + +verify.completions({ + marker: ["3"], + excludes: ["c"], + includes: ["a", "b"], + isNewIdentifierLocation: true, +}); From ab3be8245508f6c3a2247d323d90c9d928084465 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 23 Dec 2020 16:20:42 +0800 Subject: [PATCH 11/22] feat: perfect the completionListWithoutVariableinitializer test case --- .../completionListWithoutVariableinitializer.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/cases/fourslash/completionListWithoutVariableinitializer.ts b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts index 96151138c581d..c3b8b726f0e91 100644 --- a/tests/cases/fourslash/completionListWithoutVariableinitializer.ts +++ b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts @@ -3,6 +3,8 @@ //// const a = a/*1*/; //// const b = a && b/*2*/; //// const c = [{ prop: [c/*3*/] }]; +//// const d = () => { d/*4*/ }; +//// const e = { prop() { e/*5*/ } }; verify.completions({ marker: ["1"], @@ -14,7 +16,6 @@ verify.completions({ marker: ["2"], excludes: ["b"], includes: ["a"], - isNewIdentifierLocation: false, }); verify.completions({ @@ -23,3 +24,13 @@ verify.completions({ includes: ["a", "b"], isNewIdentifierLocation: true, }); + +verify.completions({ + marker: ["4"], + includes: ["a", "b", "c", "d"], +}); + +verify.completions({ + marker: ["5"], + includes: ["a", "b", "c", "d", "e"], +}); From b4dc72cab304017cb5da45d70a3177f7d7f81042 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Thu, 24 Dec 2020 09:57:22 +0800 Subject: [PATCH 12/22] feat: remove isIdentifier limit --- src/services/completions.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index a5e2d79ed6b12..8ef809d655da7 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1542,10 +1542,6 @@ namespace ts.Completions { } function getVariableDeclaration(property: Node): VariableDeclaration | undefined { - if (!isIdentifier(property)) { - return undefined; - } - const variableDeclaration = findAncestor(property, (node) => { if (isFunctionLikeDeclaration(node)) { return "quit"; From 019bbfb358cd5aa84dd6ccffc0c4ff90a2891009 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Thu, 24 Dec 2020 10:03:06 +0800 Subject: [PATCH 13/22] feat: update test cases --- tests/cases/fourslash/completionListIsGlobalCompletion.ts | 4 ++-- tests/cases/fourslash/completionTypeAssertion.ts | 2 +- .../fourslash/globalCompletionListInsideObjectLiterals.ts | 6 ++++-- .../cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/cases/fourslash/completionListIsGlobalCompletion.ts b/tests/cases/fourslash/completionListIsGlobalCompletion.ts index eaf83fa526b07..7184e50499e00 100644 --- a/tests/cases/fourslash/completionListIsGlobalCompletion.ts +++ b/tests/cases/fourslash/completionListIsGlobalCompletion.ts @@ -46,8 +46,8 @@ verify.completions( { marker: "7", exact: completion.globalsInsideFunction(x), isGlobalCompletion: true }, { marker: "9", exact: ["x", "y"], isGlobalCompletion: false }, { marker: "10", exact: completion.classElementKeywords, isGlobalCompletion: false, isNewIdentifierLocation: true }, - { marker: "13", exact: globals, isGlobalCompletion: false }, + { marker: "13", exact: globals.filter(name => name !== 'z'), isGlobalCompletion: false }, { marker: "15", exact: globals.filter(name => name !== 'x'), isGlobalCompletion: true, isNewIdentifierLocation: true }, - { marker: "16", exact: [...x, completion.globalThisEntry, ...completion.globalsVars, completion.undefinedVarEntry], isGlobalCompletion: false }, + { marker: "16", exact: [...x, completion.globalThisEntry, ...completion.globalsVars, completion.undefinedVarEntry].filter(name => name !== 'user'), isGlobalCompletion: false }, { marker: "17", exact: completion.globalKeywords, isGlobalCompletion: false }, ); diff --git a/tests/cases/fourslash/completionTypeAssertion.ts b/tests/cases/fourslash/completionTypeAssertion.ts index bb5c6f8abda29..bb6b626216916 100644 --- a/tests/cases/fourslash/completionTypeAssertion.ts +++ b/tests/cases/fourslash/completionTypeAssertion.ts @@ -2,4 +2,4 @@ //// var x = this as/*1*/ -verify.completions({marker: "1", exact: completion.globalsPlus(["x"]) }) +verify.completions({marker: "1", exact: completion.globals }) diff --git a/tests/cases/fourslash/globalCompletionListInsideObjectLiterals.ts b/tests/cases/fourslash/globalCompletionListInsideObjectLiterals.ts index 503758461489b..00d5ef2c6e0d6 100644 --- a/tests/cases/fourslash/globalCompletionListInsideObjectLiterals.ts +++ b/tests/cases/fourslash/globalCompletionListInsideObjectLiterals.ts @@ -28,6 +28,8 @@ // 5, 6: Literal member completion after member name with empty member expression. const exact = ["p1", "p2", "p3", "p4", ...completion.globalsPlus(["ObjectLiterals"])]; verify.completions( - { marker: ["1",], exact, isNewIdentifierLocation: true }, - { marker: ["2", "3", "4", "5", "6"], exact } + { marker: ["1",], exact: exact.filter(name => name !== 'p1'), isNewIdentifierLocation: true }, + { marker: ["2", "3"], exact: exact.filter(name => name !== 'p2') }, + { marker: ["4"], exact: exact.filter(name => name !== 'p3' ) }, + { marker: ["5", "6"], exact: exact.filter(name => name !== 'p4') }, ); diff --git a/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts b/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts index c7f3b3f26bebb..e48a6368627ba 100644 --- a/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts +++ b/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts @@ -3,4 +3,4 @@ //@Filename: file.tsx //// var x = Date: Thu, 24 Dec 2020 17:17:07 +0800 Subject: [PATCH 14/22] feat: code optimization and filter out some binding cases --- src/services/completions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 8ef809d655da7..81fc721e7ffb7 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1543,7 +1543,7 @@ namespace ts.Completions { function getVariableDeclaration(property: Node): VariableDeclaration | undefined { const variableDeclaration = findAncestor(property, (node) => { - if (isFunctionLikeDeclaration(node)) { + if (isFunctionBlock(node) || isBindingPattern(node)) { return "quit"; } From f6542e57e3ee41e630087f115c2b7d2af28f71ac Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Thu, 24 Dec 2020 17:17:40 +0800 Subject: [PATCH 15/22] feat: update test case --- ...ompletionListWithoutVariableinitializer.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/cases/fourslash/completionListWithoutVariableinitializer.ts b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts index c3b8b726f0e91..d444aaba8dffa 100644 --- a/tests/cases/fourslash/completionListWithoutVariableinitializer.ts +++ b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts @@ -5,6 +5,9 @@ //// const c = [{ prop: [c/*3*/] }]; //// const d = () => { d/*4*/ }; //// const e = { prop() { e/*5*/ } }; +//// const fn = (p = /*6*/) => {} +//// const { f, g = /*7*/ } = { ... } +//// const [ f1, g1 = /*8*/ ] = [ ... ] verify.completions({ marker: ["1"], @@ -34,3 +37,19 @@ verify.completions({ marker: ["5"], includes: ["a", "b", "c", "d", "e"], }); + +verify.completions({ + marker: ["6"], + includes: ["a", "b", "c", "d", "e"], + excludes: ["fn"], +}); + +verify.completions({ + marker: ["7"], + includes: ["a", "b", "c", "d", "e", "fn"], +}); + +verify.completions({ + marker: ["8"], + includes: ["a", "b", "c", "d", "e", "fn"], +}); From cc6212f51967c8b8e566e9ba9564395131625b2a Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Tue, 29 Dec 2020 10:01:29 +0800 Subject: [PATCH 16/22] feat: handle arrow function expressions without braces --- src/services/completions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 81fc721e7ffb7..62a034af92914 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1543,7 +1543,7 @@ namespace ts.Completions { function getVariableDeclaration(property: Node): VariableDeclaration | undefined { const variableDeclaration = findAncestor(property, (node) => { - if (isFunctionBlock(node) || isBindingPattern(node)) { + if (isFunctionBlock(node) || isBindingPattern(node) || (isArrowFunction(node.parent) && node.parent.body === node)) { return "quit"; } From 5c2e314da186db26c36e28fadfee86426796c7fb Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Tue, 29 Dec 2020 10:01:55 +0800 Subject: [PATCH 17/22] feat: add arrow function expressions without braces test case --- ...ompletionListWithoutVariableinitializer.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/cases/fourslash/completionListWithoutVariableinitializer.ts b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts index d444aaba8dffa..7ef57ca66e196 100644 --- a/tests/cases/fourslash/completionListWithoutVariableinitializer.ts +++ b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts @@ -4,10 +4,11 @@ //// const b = a && b/*2*/; //// const c = [{ prop: [c/*3*/] }]; //// const d = () => { d/*4*/ }; -//// const e = { prop() { e/*5*/ } }; -//// const fn = (p = /*6*/) => {} -//// const { f, g = /*7*/ } = { ... } -//// const [ f1, g1 = /*8*/ ] = [ ... ] +//// const e = () => expression/*5*/ +//// const f = { prop() { e/*6*/ } }; +//// const fn = (p = /*7*/) => {} +//// const { g, h = /*8*/ } = { ... } +//// const [ g1, h1 = /*9*/ ] = [ ... ] verify.completions({ marker: ["1"], @@ -41,15 +42,21 @@ verify.completions({ verify.completions({ marker: ["6"], includes: ["a", "b", "c", "d", "e"], - excludes: ["fn"], }); verify.completions({ marker: ["7"], - includes: ["a", "b", "c", "d", "e", "fn"], + includes: ["a", "b", "c", "d", "e"], + excludes: ["fn"], }); verify.completions({ marker: ["8"], includes: ["a", "b", "c", "d", "e", "fn"], }); + +verify.completions({ + marker: ["9"], + includes: ["a", "b", "c", "d", "e", "fn"], +}); + From 7b7cc249088818a30fcc833c8bd2fe18c73df647 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Tue, 29 Dec 2020 10:29:09 +0800 Subject: [PATCH 18/22] feat: check node.parent exist first --- src/services/completions.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 62a034af92914..91fbe838c4c0d 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1542,8 +1542,13 @@ namespace ts.Completions { } function getVariableDeclaration(property: Node): VariableDeclaration | undefined { + + const isArrowFunctionExpressionWithoutArrow = (node: Node) => { + return node.parent && isArrowFunction(node.parent) && node.parent.body === node; + }; + const variableDeclaration = findAncestor(property, (node) => { - if (isFunctionBlock(node) || isBindingPattern(node) || (isArrowFunction(node.parent) && node.parent.body === node)) { + if (isFunctionBlock(node) || isArrowFunctionExpressionWithoutArrow(node) || isBindingPattern(node)) { return "quit"; } From 0630cfef19faa45dbab883b9c02c0886982dc9be Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 30 Dec 2020 08:27:04 +0800 Subject: [PATCH 19/22] feat: optimization name --- src/services/completions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 91fbe838c4c0d..cfcd1a8bf7c69 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1543,12 +1543,12 @@ namespace ts.Completions { function getVariableDeclaration(property: Node): VariableDeclaration | undefined { - const isArrowFunctionExpressionWithoutArrow = (node: Node) => { + const isArrowFunctionBody = (node: Node) => { return node.parent && isArrowFunction(node.parent) && node.parent.body === node; }; const variableDeclaration = findAncestor(property, (node) => { - if (isFunctionBlock(node) || isArrowFunctionExpressionWithoutArrow(node) || isBindingPattern(node)) { + if (isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node)) { return "quit"; } From 578a1ceacbd7ffa8ce744fab3ad21f8c6c842505 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Wed, 30 Dec 2020 08:27:47 +0800 Subject: [PATCH 20/22] feat: optimize test cases --- .../completionPropertyShorthandForObjectLiteral5.ts | 2 ++ tests/cases/fourslash/completionTypeAssertion.ts | 5 +++-- .../cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts | 5 +++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts index 47aeeb83677a7..979b0b2afe767 100644 --- a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts +++ b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts @@ -4,9 +4,11 @@ //// export const exportedConstant = 0; // @Filename: /b.ts +//// const foo = 'foo' //// const obj = { exp/**/ verify.completions({ marker: "", + exact: completion.globalsPlus(["foo"]), preferences: { includeCompletionsForModuleExports: true }, }); diff --git a/tests/cases/fourslash/completionTypeAssertion.ts b/tests/cases/fourslash/completionTypeAssertion.ts index bb6b626216916..fbfe72ac455cc 100644 --- a/tests/cases/fourslash/completionTypeAssertion.ts +++ b/tests/cases/fourslash/completionTypeAssertion.ts @@ -1,5 +1,6 @@ /// -//// var x = this as/*1*/ +//// var x = 'something' +//// var y = this as/*1*/ -verify.completions({marker: "1", exact: completion.globals }) +verify.completions({marker: "1", exact: completion.globalsPlus(["x"]) }) diff --git a/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts b/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts index e48a6368627ba..256c4280f856d 100644 --- a/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts +++ b/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts @@ -1,6 +1,7 @@ /// //@Filename: file.tsx -//// var x = Date: Wed, 13 Jan 2021 10:53:44 +0800 Subject: [PATCH 21/22] chore: code formatting --- src/services/completions.ts | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index cfcd1a8bf7c69..00a64d8cab79d 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1514,11 +1514,7 @@ namespace ts.Completions { } // Filter out variables from their own initializers - // e.g. - // 1. `const o = { prop: /* no 'o' here */ }` - // 2. `const a = /* no 'a' here */` - // 3. `const b = a && /* no 'b' here */` - // 4. `const c = [{ prop: [/* no 'c' here */] }]` + // `const a = /* no 'a' here */` if (variableDeclaration && symbol.valueDeclaration === variableDeclaration) { return false; } @@ -1542,25 +1538,18 @@ namespace ts.Completions { } function getVariableDeclaration(property: Node): VariableDeclaration | undefined { - - const isArrowFunctionBody = (node: Node) => { - return node.parent && isArrowFunction(node.parent) && node.parent.body === node; - }; - - const variableDeclaration = findAncestor(property, (node) => { - if (isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node)) { - return "quit"; - } - - if (isVariableDeclaration(node)) { - return true; - } - return false; - }); + const variableDeclaration = findAncestor(property, node => + isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node) + ? "quit" + : isVariableDeclaration(node)); return variableDeclaration as VariableDeclaration; } + function isArrowFunctionBody(node: Node) { + return node.parent && isArrowFunction(node.parent) && node.parent.body === node; + }; + function isTypeOnlyCompletion(): boolean { return insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && From 86c30d094be5ad88e439790201bab7c842889d22 Mon Sep 17 00:00:00 2001 From: chenjigeng <178854407@qq.com> Date: Fri, 15 Jan 2021 09:13:48 +0800 Subject: [PATCH 22/22] feat: perfect type --- src/services/completions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 00a64d8cab79d..f0ad156956d82 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1543,7 +1543,7 @@ namespace ts.Completions { ? "quit" : isVariableDeclaration(node)); - return variableDeclaration as VariableDeclaration; + return variableDeclaration as VariableDeclaration | undefined; } function isArrowFunctionBody(node: Node) {