From 3c8732fab1cdc524c1cf3a506bda871b09842199 Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Wed, 10 May 2017 17:26:47 -0700 Subject: [PATCH 1/2] Prevent Duplicate String Literal Completions --- src/services/completions.ts | 23 +++++++++++-------- .../fourslash/completionForStringLiteral12.ts | 10 ++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 tests/cases/fourslash/completionForStringLiteral12.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 318c02683ff..948d7349419 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -221,11 +221,12 @@ namespace ts.Completions { function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo, typeChecker: TypeChecker): CompletionInfo | undefined { const candidates: Signature[] = []; const entries: CompletionEntry[] = []; + const uniques = createMap(); typeChecker.getResolvedSignature(argumentInfo.invocation, candidates); for (const candidate of candidates) { - addStringLiteralCompletionsFromType(typeChecker.getParameterType(candidate, argumentInfo.argumentIndex), entries, typeChecker); + addStringLiteralCompletionsFromType(typeChecker.getParameterType(candidate, argumentInfo.argumentIndex), entries, typeChecker, uniques); } if (entries.length) { @@ -258,7 +259,7 @@ namespace ts.Completions { return undefined; } - function addStringLiteralCompletionsFromType(type: Type, result: Push, typeChecker: TypeChecker): void { + function addStringLiteralCompletionsFromType(type: Type, result: Push, typeChecker: TypeChecker, uniques = createMap()): void { if (type && type.flags & TypeFlags.TypeParameter) { type = typeChecker.getBaseConstraintOfType(type); } @@ -267,16 +268,20 @@ namespace ts.Completions { } if (type.flags & TypeFlags.Union) { for (const t of (type).types) { - addStringLiteralCompletionsFromType(t, result, typeChecker); + addStringLiteralCompletionsFromType(t, result, typeChecker, uniques); } } else if (type.flags & TypeFlags.StringLiteral) { - result.push({ - name: (type).text, - kindModifiers: ScriptElementKindModifier.none, - kind: ScriptElementKind.variableElement, - sortText: "0" - }); + const name = (type).text; + if (!uniques.get(name)) { + uniques.set(name, name); + result.push({ + name, + kindModifiers: ScriptElementKindModifier.none, + kind: ScriptElementKind.variableElement, + sortText: "0" + }); + } } } diff --git a/tests/cases/fourslash/completionForStringLiteral12.ts b/tests/cases/fourslash/completionForStringLiteral12.ts new file mode 100644 index 00000000000..22bb2f00a43 --- /dev/null +++ b/tests/cases/fourslash/completionForStringLiteral12.ts @@ -0,0 +1,10 @@ +/// + +////function foo(x: "bla"): void; +////function foo(x: "bla"): void; +////function foo(x: string) {} +////foo("/**/") + +goTo.marker(); +verify.completionListContains("bla"); +verify.completionListCount(1); From cff19ab3d3fc2cb8d405a9c435b364b5b81985c8 Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Thu, 11 May 2017 10:42:25 -0700 Subject: [PATCH 2/2] Switch map to be used as a set rather than a map --- src/services/completions.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 948d7349419..e850bfb4496 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -221,7 +221,7 @@ namespace ts.Completions { function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo, typeChecker: TypeChecker): CompletionInfo | undefined { const candidates: Signature[] = []; const entries: CompletionEntry[] = []; - const uniques = createMap(); + const uniques = createMap(); typeChecker.getResolvedSignature(argumentInfo.invocation, candidates); @@ -259,7 +259,7 @@ namespace ts.Completions { return undefined; } - function addStringLiteralCompletionsFromType(type: Type, result: Push, typeChecker: TypeChecker, uniques = createMap()): void { + function addStringLiteralCompletionsFromType(type: Type, result: Push, typeChecker: TypeChecker, uniques = createMap()): void { if (type && type.flags & TypeFlags.TypeParameter) { type = typeChecker.getBaseConstraintOfType(type); } @@ -273,8 +273,8 @@ namespace ts.Completions { } else if (type.flags & TypeFlags.StringLiteral) { const name = (type).text; - if (!uniques.get(name)) { - uniques.set(name, name); + if (!uniques.has(name)) { + uniques.set(name, true); result.push({ name, kindModifiers: ScriptElementKindModifier.none,