diff --git a/src/services/codefixes/unusedIdentifierFixes.ts b/src/services/codefixes/unusedIdentifierFixes.ts index 2784a09a504..0ca01a81eb1 100644 --- a/src/services/codefixes/unusedIdentifierFixes.ts +++ b/src/services/codefixes/unusedIdentifierFixes.ts @@ -25,7 +25,7 @@ namespace ts.codefix { const forStatement = token.parent.parent.parent; const forInitializer = forStatement.initializer; if (forInitializer.declarations.length === 1) { - return createCodeFix("", forInitializer.pos, forInitializer.end - forInitializer.pos); + return createCodeFixToRemoveNode(forInitializer); } else { return removeSingleItem(forInitializer.declarations, token); @@ -35,7 +35,7 @@ namespace ts.codefix { const forOfStatement = token.parent.parent.parent; if (forOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) { const forOfInitializer = forOfStatement.initializer; - return createCodeFix("{}", forOfInitializer.declarations[0].pos, forOfInitializer.declarations[0].end - forOfInitializer.declarations[0].pos); + return createCodeFix("{}", forOfInitializer.declarations[0].getStart(), forOfInitializer.declarations[0].getWidth()); } break; @@ -47,12 +47,12 @@ namespace ts.codefix { case SyntaxKind.CatchClause: const catchClause = token.parent.parent; const parameter = catchClause.variableDeclaration.getChildren()[0]; - return createCodeFix("", parameter.pos, parameter.end - parameter.pos); + return createCodeFixToRemoveNode(parameter); default: const variableStatement = token.parent.parent.parent; if (variableStatement.declarationList.declarations.length === 1) { - return createCodeFix("", variableStatement.pos, variableStatement.end - variableStatement.pos); + return createCodeFixToRemoveNode(variableStatement); } else { const declarations = variableStatement.declarationList.declarations; @@ -72,7 +72,7 @@ namespace ts.codefix { case ts.SyntaxKind.Parameter: const functionDeclaration = token.parent.parent; if (functionDeclaration.parameters.length === 1) { - return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos); + return createCodeFixToRemoveNode(token.parent); } else { return removeSingleItem(functionDeclaration.parameters, token); @@ -81,14 +81,14 @@ namespace ts.codefix { // handle case where 'import a = A;' case SyntaxKind.ImportEqualsDeclaration: const importEquals = findImportDeclaration(token); - return createCodeFix("", importEquals.pos, importEquals.end - importEquals.pos); + return createCodeFixToRemoveNode(importEquals); case SyntaxKind.ImportSpecifier: const namedImports = token.parent.parent; if (namedImports.elements.length === 1) { // Only 1 import and it is unused. So the entire declaration should be removed. const importSpec = findImportDeclaration(token); - return createCodeFix("", importSpec.pos, importSpec.end - importSpec.pos); + return createCodeFixToRemoveNode(importSpec); } else { return removeSingleItem(namedImports.elements, token); @@ -100,17 +100,24 @@ namespace ts.codefix { const importClause = token.parent; if (!importClause.namedBindings) { // |import d from './file'| or |import * as ns from './file'| const importDecl = findImportDeclaration(importClause); - return createCodeFix("", importDecl.pos, importDecl.end - importDecl.pos); + return createCodeFixToRemoveNode(importDecl); } - else { // import |d,| * as ns from './file' - return createCodeFix("", importClause.name.pos, importClause.namedBindings.pos - importClause.name.pos); + else { + // import |d,| * as ns from './file' + const start = importClause.name.getStart(); + let end = findFirstNonSpaceCharPosStarting(importClause.name.end); + if (sourceFile.text.charCodeAt(end) === CharacterCodes.comma) { + end = findFirstNonSpaceCharPosStarting(end + 1); + } + + return createCodeFix("", start, end - start); } case SyntaxKind.NamespaceImport: const namespaceImport = token.parent; if (namespaceImport.name == token && !(namespaceImport.parent).name) { const importDecl = findImportDeclaration(namespaceImport); - return createCodeFix("", importDecl.pos, importDecl.end - importDecl.pos); + return createCodeFixToRemoveNode(importDecl); } else { const start = (namespaceImport.parent).name.end; @@ -120,16 +127,14 @@ namespace ts.codefix { break; case SyntaxKind.PropertyDeclaration: - return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos); - case SyntaxKind.NamespaceImport: - return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos); + return createCodeFixToRemoveNode(token.parent); } if (isDeclarationName(token)) { - return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos); + return createCodeFixToRemoveNode(token.parent); } else if (isLiteralComputedPropertyDeclarationName(token)) { - return createCodeFix("", token.parent.parent.pos, token.parent.parent.end - token.parent.parent.pos); + return createCodeFixToRemoveNode(token.parent.parent); } else { return undefined; @@ -144,6 +149,17 @@ namespace ts.codefix { return importDecl; } + function createCodeFixToRemoveNode(node: Node) { + return createCodeFix("", node.getStart(), node.getWidth()); + } + + function findFirstNonSpaceCharPosStarting(start: number) { + while (isWhiteSpace(sourceFile.text.charCodeAt(start))) { + start += 1; + } + return start; + } + function createCodeFix(newText: string, start: number, length: number): CodeAction[] { return [{ description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Remove_declaration_for_Colon_0), { 0: token.getText() }), diff --git a/tests/cases/fourslash/unusedFunctionInNamespace1.ts b/tests/cases/fourslash/unusedFunctionInNamespace1.ts index 8ebf1f7072a..288573608f2 100644 --- a/tests/cases/fourslash/unusedFunctionInNamespace1.ts +++ b/tests/cases/fourslash/unusedFunctionInNamespace1.ts @@ -2,9 +2,11 @@ // @noUnusedLocals: true //// [| namespace greeter { +//// // some legit comments //// function function1() { //// }/*1*/ //// } |] verify.rangeAfterCodeFix(`namespace greeter { + // some legit comments }`); diff --git a/tests/cases/fourslash/unusedImports3FS.ts b/tests/cases/fourslash/unusedImports3FS.ts index 98dc30c4336..6926f97bb4f 100644 --- a/tests/cases/fourslash/unusedImports3FS.ts +++ b/tests/cases/fourslash/unusedImports3FS.ts @@ -2,7 +2,7 @@ // @noUnusedLocals: true // @Filename: file2.ts -////[| import {Calculator, test, test2} from "./file1" |] +////[| import {Calculator, /*some comments*/ test, test2} from "./file1" |] //// test(); //// test2(); @@ -20,5 +20,5 @@ //// //// } -verify.rangeAfterCodeFix(`import {test, test2} from "./file1"`); +verify.rangeAfterCodeFix(`import {/*some comments*/ test, test2} from "./file1"`);