Skip to content

Commit d1e1e9d

Browse files
authored
Feat/exclude completions of variable initializers (#42087)
* feat: exclude declared variable when Object literal completions * feat: check undeclareVariable when completion * feat: add completion test case * feat: code optimization * feat: support shorthand property assignment * feat: add shorthand property assignment test case * feat: update completionPropertyShorthandForObjectLiteral test cases * feat: exclude completions of variable initializers * feat: update test cases * feat: add completionListWithoutVariableinitializer test case * feat: perfect the completionListWithoutVariableinitializer test case * feat: remove isIdentifier limit * feat: update test cases * feat: code optimization and filter out some binding cases * feat: update test case * feat: handle arrow function expressions without braces * feat: add arrow function expressions without braces test case * feat: check node.parent exist first * feat: optimization name * feat: optimize test cases * chore: code formatting * feat: perfect type
1 parent 0aa77fc commit d1e1e9d

14 files changed

+158
-20
lines changed

src/services/completions.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,13 +1504,21 @@ namespace ts.Completions {
15041504
: KeywordCompletionFilters.TypeKeywords;
15051505
}
15061506

1507+
const variableDeclaration = getVariableDeclaration(location);
1508+
15071509
filterMutate(symbols, symbol => {
15081510
if (!isSourceFile(location)) {
15091511
// export = /**/ here we want to get all meanings, so any symbol is ok
15101512
if (isExportAssignment(location.parent)) {
15111513
return true;
15121514
}
15131515

1516+
// Filter out variables from their own initializers
1517+
// `const a = /* no 'a' here */`
1518+
if (variableDeclaration && symbol.valueDeclaration === variableDeclaration) {
1519+
return false;
1520+
}
1521+
15141522
symbol = skipAlias(symbol, typeChecker);
15151523

15161524
// import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
@@ -1529,6 +1537,19 @@ namespace ts.Completions {
15291537
});
15301538
}
15311539

1540+
function getVariableDeclaration(property: Node): VariableDeclaration | undefined {
1541+
const variableDeclaration = findAncestor(property, node =>
1542+
isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node)
1543+
? "quit"
1544+
: isVariableDeclaration(node));
1545+
1546+
return variableDeclaration as VariableDeclaration | undefined;
1547+
}
1548+
1549+
function isArrowFunctionBody(node: Node) {
1550+
return node.parent && isArrowFunction(node.parent) && node.parent.body === node;
1551+
};
1552+
15321553
function isTypeOnlyCompletion(): boolean {
15331554
return insideJsDocTagTypeExpression
15341555
|| !isContextTokenValueLocation(contextToken) &&

tests/cases/fourslash/commentsClassMembers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ verify.completions(
201201
],
202202
},
203203
{ marker: ["29", "33", "38", "109"], includes: locals },
204-
{ marker: ["35", "40", "87"], includes: locals, isNewIdentifierLocation: true },
204+
{ marker: ["35", "40"], includes: locals, isNewIdentifierLocation: true },
205+
{ marker: ["87"], includes: locals.filter(local => local === 'i1_s_p') , isNewIdentifierLocation: true },
205206
{ marker: "31", includes: { name: "b", text: "(parameter) b: number", documentation: "number to add" } },
206207
{ marker: "42", includes: { name: "value", text: "(parameter) value: number", documentation: "this is value" }, isNewIdentifierLocation: true },
207208
{ marker: ["45", "52", "59"], includes: { name: "b", text: "(parameter) b: number" } },

tests/cases/fourslash/completionListBuilderLocations_VariableDeclarations.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,15 @@
2626

2727
////var y = 10; y=/*var12*/
2828

29+
// first declaration
2930
verify.completions({
30-
marker: test.markers(),
31+
marker: ["var1"],
32+
exact: completion.globalsPlus(["y", "C"]),
33+
isNewIdentifierLocation: true
34+
});
35+
36+
verify.completions({
37+
marker: ["var2", "var3", "var4", "var5", "var6", "var7", "var8", "var9", "var10", "var11", "var12"],
3138
exact: completion.globalsPlus(["x", "y", "C"]),
3239
isNewIdentifierLocation: true
3340
});
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////const o = 'something'
4+
////const obj = {
5+
//// prop: o/*1*/,
6+
//// pro() {
7+
//// const obj1 = {
8+
//// p:{
9+
//// s: {
10+
//// h: {
11+
//// hh: o/*2*/
12+
//// },
13+
//// someFun() {
14+
//// o/*3*/
15+
//// }
16+
//// }
17+
//// }
18+
//// }
19+
//// },
20+
//// o/*4*/
21+
////}
22+
23+
verify.completions({ marker: ["1"], excludes: ['obj'], includes: ['o'] });
24+
verify.completions({ marker: ["2"], excludes: ['obj1'], includes: ['o', 'obj'] });
25+
verify.completions({ marker: ["3"], includes: ['o', 'obj', 'obj1'] });
26+
verify.completions({ marker: ["4"], includes: ['o'], excludes: ['obj'] });

tests/cases/fourslash/completionListIsGlobalCompletion.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,13 @@ verify.completions(
4141
{ marker: ["1", "3", "6", "8", "12", "14"], exact: undefined, isGlobalCompletion: false },
4242
{ marker: "2", exact: ["a.ts", "file.ts"], isGlobalCompletion: false, isNewIdentifierLocation: true },
4343
{ marker: ["4", "19"], exact: [], isGlobalCompletion: false },
44-
{ marker: ["5", "11", "18"], exact: globals, isGlobalCompletion: true },
44+
{ marker: ["5", "11"], exact: globals, isGlobalCompletion: true },
45+
{ marker: ["18"], exact: globals.filter(name => name !== 'user'), isGlobalCompletion: true },
4546
{ marker: "7", exact: completion.globalsInsideFunction(x), isGlobalCompletion: true },
4647
{ marker: "9", exact: ["x", "y"], isGlobalCompletion: false },
4748
{ marker: "10", exact: completion.classElementKeywords, isGlobalCompletion: false, isNewIdentifierLocation: true },
48-
{ marker: "13", exact: globals, isGlobalCompletion: false },
49-
{ marker: "15", exact: globals, isGlobalCompletion: true, isNewIdentifierLocation: true },
50-
{ marker: "16", exact: [...x, completion.globalThisEntry, ...completion.globalsVars, completion.undefinedVarEntry], isGlobalCompletion: false },
49+
{ marker: "13", exact: globals.filter(name => name !== 'z'), isGlobalCompletion: false },
50+
{ marker: "15", exact: globals.filter(name => name !== 'x'), isGlobalCompletion: true, isNewIdentifierLocation: true },
51+
{ marker: "16", exact: [...x, completion.globalThisEntry, ...completion.globalsVars, completion.undefinedVarEntry].filter(name => name !== 'user'), isGlobalCompletion: false },
5152
{ marker: "17", exact: completion.globalKeywords, isGlobalCompletion: false },
5253
);

tests/cases/fourslash/completionListWithMeanings.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,20 @@ const types: ReadonlyArray<FourSlashInterface.ExpectedCompletionEntry> = [
3636
...completion.typeKeywords,
3737
];
3838

39+
const filterValuesByName = (name: string) => {
40+
return values.filter(entry => {
41+
if (typeof entry === 'string') {
42+
return entry !== name;
43+
}
44+
45+
return entry.name !== name;
46+
})
47+
}
48+
3949
verify.completions(
40-
{ marker: "valueExpr", exact: values, isNewIdentifierLocation: true },
50+
{ marker: "valueExpr", exact: filterValuesByName('tt'), isNewIdentifierLocation: true },
4151
{ marker: "typeExpr", exact: types, },
42-
{ marker: "valueExprInObjectLiteral", exact: values },
52+
{ marker: "valueExprInObjectLiteral", exact: filterValuesByName('yy') },
4353
{ marker: "membertypeExpr", exact: [{ name: "point3", text: "interface m3.point3" }] },
4454
{ marker: "membervalueExpr", exact: [{ name: "zz2", text: "var m3.zz2: number" }] },
4555
);
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const a = a/*1*/;
4+
//// const b = a && b/*2*/;
5+
//// const c = [{ prop: [c/*3*/] }];
6+
//// const d = () => { d/*4*/ };
7+
//// const e = () => expression/*5*/
8+
//// const f = { prop() { e/*6*/ } };
9+
//// const fn = (p = /*7*/) => {}
10+
//// const { g, h = /*8*/ } = { ... }
11+
//// const [ g1, h1 = /*9*/ ] = [ ... ]
12+
13+
verify.completions({
14+
marker: ["1"],
15+
excludes: ["a"],
16+
isNewIdentifierLocation: true,
17+
});
18+
19+
verify.completions({
20+
marker: ["2"],
21+
excludes: ["b"],
22+
includes: ["a"],
23+
});
24+
25+
verify.completions({
26+
marker: ["3"],
27+
excludes: ["c"],
28+
includes: ["a", "b"],
29+
isNewIdentifierLocation: true,
30+
});
31+
32+
verify.completions({
33+
marker: ["4"],
34+
includes: ["a", "b", "c", "d"],
35+
});
36+
37+
verify.completions({
38+
marker: ["5"],
39+
includes: ["a", "b", "c", "d", "e"],
40+
});
41+
42+
verify.completions({
43+
marker: ["6"],
44+
includes: ["a", "b", "c", "d", "e"],
45+
});
46+
47+
verify.completions({
48+
marker: ["7"],
49+
includes: ["a", "b", "c", "d", "e"],
50+
excludes: ["fn"],
51+
});
52+
53+
verify.completions({
54+
marker: ["8"],
55+
includes: ["a", "b", "c", "d", "e", "fn"],
56+
});
57+
58+
verify.completions({
59+
marker: ["9"],
60+
includes: ["a", "b", "c", "d", "e", "fn"],
61+
});
62+

tests/cases/fourslash/completionPropertyShorthandForObjectLiteral2.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
//// };
1313

1414
verify.completions({
15-
marker: test.markers(),
16-
exact: completion.globalsPlus(["foo", "bar", "obj1", "obj2"]),
15+
marker: ["1"],
16+
exact: completion.globalsPlus(["foo", "bar", "obj2"]),
17+
});
18+
19+
verify.completions({
20+
marker: ["2"],
21+
exact: completion.globalsPlus(["foo", "bar", "obj1"]),
1722
});

tests/cases/fourslash/completionPropertyShorthandForObjectLiteral3.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77

88
verify.completions({
99
marker: ["1"],
10-
exact: completion.globalsPlus(["foo", "bar", "obj"])
10+
exact: completion.globalsPlus(["foo", "bar"]),
1111
});

tests/cases/fourslash/completionPropertyShorthandForObjectLiteral4.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77

88
verify.completions({
99
marker: ["1"],
10-
exact: completion.globalsPlus(["foo", "bar", "obj"])
10+
exact: completion.globalsPlus(["foo", "bar"]),
1111
});

tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
//// export const exportedConstant = 0;
55

66
// @Filename: /b.ts
7+
//// const foo = 'foo'
78
//// const obj = { exp/**/
89

910
verify.completions({
10-
marker: "",
11-
exact: completion.globalsPlus(["obj"]),
12-
preferences: { includeCompletionsForModuleExports: true }
13-
});
11+
marker: "",
12+
exact: completion.globalsPlus(["foo"]),
13+
preferences: { includeCompletionsForModuleExports: true },
14+
});
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/// <reference path="fourslash.ts" />
22

3-
//// var x = this as/*1*/
3+
//// var x = 'something'
4+
//// var y = this as/*1*/
45

56
verify.completions({marker: "1", exact: completion.globalsPlus(["x"]) })

tests/cases/fourslash/globalCompletionListInsideObjectLiterals.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
// 5, 6: Literal member completion after member name with empty member expression.
2929
const exact = ["p1", "p2", "p3", "p4", ...completion.globalsPlus(["ObjectLiterals"])];
3030
verify.completions(
31-
{ marker: ["1",], exact, isNewIdentifierLocation: true },
32-
{ marker: ["2", "3", "4", "5", "6"], exact }
31+
{ marker: ["1",], exact: exact.filter(name => name !== 'p1'), isNewIdentifierLocation: true },
32+
{ marker: ["2", "3"], exact: exact.filter(name => name !== 'p2') },
33+
{ marker: ["4"], exact: exact.filter(name => name !== 'p3' ) },
34+
{ marker: ["5", "6"], exact: exact.filter(name => name !== 'p4') },
3335
);
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/// <reference path='fourslash.ts' />
22

33
//@Filename: file.tsx
4-
//// var x = </**/;
4+
//// var x = 'something'
5+
//// var y = </**/;
56

67
verify.completions({ marker: "", exact: [completion.globalThisEntry, ...completion.globalsVars, "x", completion.undefinedVarEntry] });

0 commit comments

Comments
 (0)