From 12eb519b3f81d0999bbc4ce9a845744f4dfc215e Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 25 Aug 2022 23:01:46 +0300 Subject: [PATCH] fix(50435): Duplicate seeming Code Actions for convert const to let (#50442) * fix(50435): omit fix all in constToLet QF * add FixAll action --- src/compiler/diagnosticMessages.json | 4 ++ src/services/codefixes/convertConstToLet.ts | 41 +++++++++++++++---- tests/cases/fourslash/codeFixConstToLet4.ts | 14 +++++++ .../cases/fourslash/codeFixConstToLet_all1.ts | 14 +++++++ .../cases/fourslash/codeFixConstToLet_all2.ts | 22 ++++++++++ 5 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 tests/cases/fourslash/codeFixConstToLet4.ts create mode 100644 tests/cases/fourslash/codeFixConstToLet_all1.ts create mode 100644 tests/cases/fourslash/codeFixConstToLet_all2.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 54b131fa32ae6..e1f62fe842b32 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -7064,6 +7064,10 @@ "category": "Message", "code": 95101 }, + "Convert all 'const' to 'let'": { + "category": "Message", + "code": 95102 + }, "Convert function expression '{0}' to arrow function": { "category": "Message", "code": 95105 diff --git a/src/services/codefixes/convertConstToLet.ts b/src/services/codefixes/convertConstToLet.ts index 4036f93632e4e..dfcfbd7171e96 100644 --- a/src/services/codefixes/convertConstToLet.ts +++ b/src/services/codefixes/convertConstToLet.ts @@ -7,28 +7,51 @@ namespace ts.codefix { errorCodes, getCodeActions: function getCodeActionsToConvertConstToLet(context) { const { sourceFile, span, program } = context; - const range = getConstTokenRange(sourceFile, span.start, program); - if (range === undefined) return; + const info = getInfo(sourceFile, span.start, program); + if (info === undefined) return; - const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, range)); - return [createCodeFixAction(fixId, changes, Diagnostics.Convert_const_to_let, fixId, Diagnostics.Convert_const_to_let)]; + const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info.token)); + return [createCodeFixActionMaybeFixAll(fixId, changes, Diagnostics.Convert_const_to_let, fixId, Diagnostics.Convert_all_const_to_let)]; + }, + getAllCodeActions: context => { + const { program } = context; + const seen = new Map(); + + return createCombinedCodeActions(textChanges.ChangeTracker.with(context, changes => { + eachDiagnostic(context, errorCodes, diag => { + const info = getInfo(diag.file, diag.start, program); + if (info) { + if (addToSeen(seen, getSymbolId(info.symbol))) { + return doChange(changes, diag.file, info.token); + } + } + return undefined; + }); + })); }, fixIds: [fixId] }); - function getConstTokenRange(sourceFile: SourceFile, pos: number, program: Program) { + interface Info { + symbol: Symbol; + token: Token; + } + + function getInfo(sourceFile: SourceFile, pos: number, program: Program): Info | undefined { const checker = program.getTypeChecker(); const symbol = checker.getSymbolAtLocation(getTokenAtPosition(sourceFile, pos)); + if (symbol === undefined) return; + const declaration = tryCast(symbol?.valueDeclaration?.parent, isVariableDeclarationList); if (declaration === undefined) return; - const constToken = findChildOfKind(declaration, SyntaxKind.ConstKeyword, sourceFile); + const constToken = findChildOfKind>(declaration, SyntaxKind.ConstKeyword, sourceFile); if (constToken === undefined) return; - return createRange(constToken.pos, constToken.end); + return { symbol, token: constToken }; } - function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, range: TextRange) { - changes.replaceRangeWithText(sourceFile, range, "let"); + function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Token) { + changes.replaceNode(sourceFile, token, factory.createToken(SyntaxKind.LetKeyword)); } } diff --git a/tests/cases/fourslash/codeFixConstToLet4.ts b/tests/cases/fourslash/codeFixConstToLet4.ts new file mode 100644 index 0000000000000..401743a914f23 --- /dev/null +++ b/tests/cases/fourslash/codeFixConstToLet4.ts @@ -0,0 +1,14 @@ +/// + +////// Comment +////const a = 1; +////a = 2; + +verify.codeFix({ + description: "Convert 'const' to 'let'", + index: 0, + newFileContent: +`// Comment +let a = 1; +a = 2;` +}); diff --git a/tests/cases/fourslash/codeFixConstToLet_all1.ts b/tests/cases/fourslash/codeFixConstToLet_all1.ts new file mode 100644 index 0000000000000..27f153f90967c --- /dev/null +++ b/tests/cases/fourslash/codeFixConstToLet_all1.ts @@ -0,0 +1,14 @@ +/// + +////const a = 1; +////a = 2; +////a = 3; + +verify.codeFixAll({ + fixId: "fixConvertConstToLet", + fixAllDescription: ts.Diagnostics.Convert_all_const_to_let.message, + newFileContent: +`let a = 1; +a = 2; +a = 3;` +}); diff --git a/tests/cases/fourslash/codeFixConstToLet_all2.ts b/tests/cases/fourslash/codeFixConstToLet_all2.ts new file mode 100644 index 0000000000000..5a4822a02723d --- /dev/null +++ b/tests/cases/fourslash/codeFixConstToLet_all2.ts @@ -0,0 +1,22 @@ +/// + +////const a = 1; +////a = 2; +////a = 3; +//// +////const b = 1; +////b = 2; +////b = 3; + +verify.codeFixAll({ + fixId: "fixConvertConstToLet", + fixAllDescription: ts.Diagnostics.Convert_all_const_to_let.message, + newFileContent: +`let a = 1; +a = 2; +a = 3; + +let b = 1; +b = 2; +b = 3;` +});