From 3431eca3863e6eecdd5076c3418e9c24a9b4395e Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Mon, 26 Jun 2023 17:49:23 +0000 Subject: [PATCH] Cherry-pick PR #54656 into release-5.1 Component commits: 1d77caae6a fix: no variable suggestions without semicolon 9c87f3a928 tests! f67c9a3b13 lint 862807be79 make sure parameter takes priority 4c2bcc9355 better formatting --- src/services/completions.ts | 16 +++++++++++----- tests/cases/fourslash/completionEntryForConst.ts | 10 ++++++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 75ec22e3528e4..b4563b0312034 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -2394,7 +2394,7 @@ export function getCompletionEntriesFromSymbols( includeSymbol = false ): UniqueNameSet { const start = timestamp(); - const variableOrParameterDeclaration = getVariableOrParameterDeclaration(contextToken); + const variableOrParameterDeclaration = getVariableOrParameterDeclaration(contextToken, location); const useSemicolons = probablyUsesSemicolons(sourceFile); const typeChecker = program.getTypeChecker(); // Tracks unique names. @@ -5464,14 +5464,20 @@ function isModuleSpecifierMissingOrEmpty(specifier: ModuleReference | Expression return !tryCast(isExternalModuleReference(specifier) ? specifier.expression : specifier, isStringLiteralLike)?.text; } -function getVariableOrParameterDeclaration(contextToken: Node | undefined) { +function getVariableOrParameterDeclaration(contextToken: Node | undefined, location: Node) { if (!contextToken) return; - const declaration = findAncestor(contextToken, node => + const possiblyParameterDeclaration = findAncestor(contextToken, node => isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node) ? "quit" - : isVariableDeclaration(node) || ((isParameter(node) || isTypeParameterDeclaration(node)) && !isIndexSignatureDeclaration(node.parent))); - return declaration as ParameterDeclaration | TypeParameterDeclaration | VariableDeclaration | undefined; + : ((isParameter(node) || isTypeParameterDeclaration(node)) && !isIndexSignatureDeclaration(node.parent))); + + const possiblyVariableDeclaration = findAncestor(location, node => + isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node) + ? "quit" + : isVariableDeclaration(node)); + + return (possiblyParameterDeclaration || possiblyVariableDeclaration) as ParameterDeclaration | TypeParameterDeclaration | VariableDeclaration | undefined; } function isArrowFunctionBody(node: Node) { diff --git a/tests/cases/fourslash/completionEntryForConst.ts b/tests/cases/fourslash/completionEntryForConst.ts index c89dd82124580..39d85df6de4c7 100644 --- a/tests/cases/fourslash/completionEntryForConst.ts +++ b/tests/cases/fourslash/completionEntryForConst.ts @@ -1,6 +1,12 @@ /// ////const c = "s"; -/////**/ +/////*1*/ +////const d = 1 +////d/*2*/ +////const e = 1 +/////*3*/ -verify.completions({ marker: "", includes: { name: "c", text: 'const c: "s"', kind: "const" } }); +verify.completions({ marker: ["1"], includes: { name: "c", text: 'const c: "s"', kind: "const" } }); +verify.completions({ marker: ["2"], includes: { name: "d", text: 'const d: 1', kind: "const" } }); +verify.completions({ marker: ["3"], includes: { name: "e", text: 'const e: 1', kind: "const" } });