diff --git a/src/services/completions.ts b/src/services/completions.ts
index 3e02ba7c20237..f0ad156956d82 100644
--- a/src/services/completions.ts
+++ b/src/services/completions.ts
@@ -1504,6 +1504,8 @@ namespace ts.Completions {
: KeywordCompletionFilters.TypeKeywords;
}
+ const variableDeclaration = getVariableDeclaration(location);
+
filterMutate(symbols, symbol => {
if (!isSourceFile(location)) {
// export = /**/ here we want to get all meanings, so any symbol is ok
@@ -1511,6 +1513,12 @@ namespace ts.Completions {
return true;
}
+ // Filter out variables from their own initializers
+ // `const a = /* no 'a' here */`
+ if (variableDeclaration && symbol.valueDeclaration === variableDeclaration) {
+ 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)
@@ -1529,6 +1537,19 @@ namespace ts.Completions {
});
}
+ function getVariableDeclaration(property: Node): VariableDeclaration | undefined {
+ const variableDeclaration = findAncestor(property, node =>
+ isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node)
+ ? "quit"
+ : isVariableDeclaration(node));
+
+ return variableDeclaration as VariableDeclaration | undefined;
+ }
+
+ function isArrowFunctionBody(node: Node) {
+ return node.parent && isArrowFunction(node.parent) && node.parent.body === node;
+ };
+
function isTypeOnlyCompletion(): boolean {
return insideJsDocTagTypeExpression
|| !isContextTokenValueLocation(contextToken) &&
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/completionListInObjectLiteral5.ts b/tests/cases/fourslash/completionListInObjectLiteral5.ts
new file mode 100644
index 0000000000000..eb245d748bf41
--- /dev/null
+++ b/tests/cases/fourslash/completionListInObjectLiteral5.ts
@@ -0,0 +1,26 @@
+///
+
+////const o = 'something'
+////const obj = {
+//// prop: o/*1*/,
+//// pro() {
+//// const obj1 = {
+//// p:{
+//// s: {
+//// h: {
+//// hh: o/*2*/
+//// },
+//// someFun() {
+//// o/*3*/
+//// }
+//// }
+//// }
+//// }
+//// },
+//// 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'] });
+verify.completions({ marker: ["4"], includes: ['o'], excludes: ['obj'] });
\ No newline at end of file
diff --git a/tests/cases/fourslash/completionListIsGlobalCompletion.ts b/tests/cases/fourslash/completionListIsGlobalCompletion.ts
index 91cd1a0f9c7e5..7184e50499e00 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: "16", exact: [...x, completion.globalThisEntry, ...completion.globalsVars, completion.undefinedVarEntry], 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].filter(name => name !== 'user'), 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" }] },
);
diff --git a/tests/cases/fourslash/completionListWithoutVariableinitializer.ts b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts
new file mode 100644
index 0000000000000..7ef57ca66e196
--- /dev/null
+++ b/tests/cases/fourslash/completionListWithoutVariableinitializer.ts
@@ -0,0 +1,62 @@
+///
+
+//// const a = a/*1*/;
+//// const b = a && b/*2*/;
+//// const c = [{ prop: [c/*3*/] }];
+//// const d = () => { d/*4*/ };
+//// 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"],
+ excludes: ["a"],
+ isNewIdentifierLocation: true,
+});
+
+verify.completions({
+ marker: ["2"],
+ excludes: ["b"],
+ includes: ["a"],
+});
+
+verify.completions({
+ marker: ["3"],
+ excludes: ["c"],
+ includes: ["a", "b"],
+ isNewIdentifierLocation: true,
+});
+
+verify.completions({
+ marker: ["4"],
+ includes: ["a", "b", "c", "d"],
+});
+
+verify.completions({
+ marker: ["5"],
+ includes: ["a", "b", "c", "d", "e"],
+});
+
+verify.completions({
+ marker: ["6"],
+ includes: ["a", "b", "c", "d", "e"],
+});
+
+verify.completions({
+ marker: ["7"],
+ 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"],
+});
+
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..979b0b2afe767 100644
--- a/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts
+++ b/tests/cases/fourslash/completionPropertyShorthandForObjectLiteral5.ts
@@ -4,10 +4,11 @@
//// export const exportedConstant = 0;
// @Filename: /b.ts
+//// const foo = 'foo'
//// const obj = { exp/**/
verify.completions({
- marker: "",
- exact: completion.globalsPlus(["obj"]),
- preferences: { includeCompletionsForModuleExports: true }
-});
\ No newline at end of file
+ marker: "",
+ exact: completion.globalsPlus(["foo"]),
+ preferences: { includeCompletionsForModuleExports: true },
+});
diff --git a/tests/cases/fourslash/completionTypeAssertion.ts b/tests/cases/fourslash/completionTypeAssertion.ts
index bb5c6f8abda29..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.globalsPlus(["x"]) })
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..256c4280f856d 100644
--- a/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts
+++ b/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts
@@ -1,6 +1,7 @@
///
//@Filename: file.tsx
-//// var x = **/;
+//// var x = 'something'
+//// var y = **/;
verify.completions({ marker: "", exact: [completion.globalThisEntry, ...completion.globalsVars, "x", completion.undefinedVarEntry] });