From a8b634d3e503104f75fd3c59fcce1cd75f84670f Mon Sep 17 00:00:00 2001 From: Nicholas Jamieson Date: Sat, 30 Mar 2019 06:57:15 +1000 Subject: [PATCH] fix(unused): Don't delete imports more than once. --- fixtures/issues/15/example-1.ts.fix | 7 ++++++ fixtures/issues/15/example-1.ts.lint | 19 +++++++++++++++ fixtures/issues/15/example-2.ts.fix | 7 ++++++ fixtures/issues/15/example-2.ts.lint | 23 +++++++++++++++++++ fixtures/issues/15/example-3.ts.fix | 8 +++++++ fixtures/issues/15/example-3.ts.lint | 20 ++++++++++++++++ fixtures/issues/15/tsconfig.json | 5 ++++ fixtures/issues/15/tslint.json | 8 +++++++ .../unused-imports/fixture.ts.fix | 3 +++ .../unused-imports/fixture.ts.lint | 14 ++++++++++- package.json | 2 +- source/rules/noUnusedDeclarationRule.ts | 8 +++++++ 12 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 fixtures/issues/15/example-1.ts.fix create mode 100644 fixtures/issues/15/example-1.ts.lint create mode 100644 fixtures/issues/15/example-2.ts.fix create mode 100644 fixtures/issues/15/example-2.ts.lint create mode 100644 fixtures/issues/15/example-3.ts.fix create mode 100644 fixtures/issues/15/example-3.ts.lint create mode 100644 fixtures/issues/15/tsconfig.json create mode 100644 fixtures/issues/15/tslint.json diff --git a/fixtures/issues/15/example-1.ts.fix b/fixtures/issues/15/example-1.ts.fix new file mode 100644 index 0000000..112efb9 --- /dev/null +++ b/fixtures/issues/15/example-1.ts.fix @@ -0,0 +1,7 @@ +import * as dotenv from "dotenv"; +import * as Hapi from "hapi"; +import * as path from "path"; +dotenv.config({ path: path.join(__dirname, "../.env") }); +import "./arrayIncludesShim"; +const server = new Hapi.Server(); + diff --git a/fixtures/issues/15/example-1.ts.lint b/fixtures/issues/15/example-1.ts.lint new file mode 100644 index 0000000..2fd7918 --- /dev/null +++ b/fixtures/issues/15/example-1.ts.lint @@ -0,0 +1,19 @@ +import * as dotenv from "dotenv"; +import * as Hapi from "hapi"; +import * as path from "path"; +dotenv.config({ path: path.join(__dirname, "../.env") }); +import { ResetTemplateCache } from "./getTemplate"; + ~~~~~~~~~~~~~~~~~~ [no-unused-declaration] +import { +RequestMethod, +~~~~~~~~~~~~~ [no-unused-declaration] +sendAsanaRequest, +~~~~~~~~~~~~~~~~ [no-unused-declaration] +} from "./sendAsanaRequest"; +import "./arrayIncludesShim"; +import { startAsanaTimer } from "./startAsanaTimer"; + ~~~~~~~~~~~~~~~ [no-unused-declaration] +const server = new Hapi.Server(); + ~~~~~~ [no-unused-declaration] + +[no-unused-declaration]: Unused declarations are forbidden diff --git a/fixtures/issues/15/example-2.ts.fix b/fixtures/issues/15/example-2.ts.fix new file mode 100644 index 0000000..112efb9 --- /dev/null +++ b/fixtures/issues/15/example-2.ts.fix @@ -0,0 +1,7 @@ +import * as dotenv from "dotenv"; +import * as Hapi from "hapi"; +import * as path from "path"; +dotenv.config({ path: path.join(__dirname, "../.env") }); +import "./arrayIncludesShim"; +const server = new Hapi.Server(); + diff --git a/fixtures/issues/15/example-2.ts.lint b/fixtures/issues/15/example-2.ts.lint new file mode 100644 index 0000000..963031b --- /dev/null +++ b/fixtures/issues/15/example-2.ts.lint @@ -0,0 +1,23 @@ +import * as dotenv from "dotenv"; +import * as Hapi from "hapi"; +import * as path from "path"; +dotenv.config({ path: path.join(__dirname, "../.env") }); +import { +ResetTemplateCache, +~~~~~~~~~~~~~~~~~~ [no-unused-declaration] +} from "./getTemplate"; +import { +hasActiveRequest, +~~~~~~~~~~~~~~~~ [no-unused-declaration] +RequestMethod, +~~~~~~~~~~~~~ [no-unused-declaration] +sendAsanaRequest, +~~~~~~~~~~~~~~~~ [no-unused-declaration] +} from "./sendAsanaRequest"; +import "./arrayIncludesShim"; +import { startAsanaTimer } from "./startAsanaTimer"; + ~~~~~~~~~~~~~~~ [no-unused-declaration] +const server = new Hapi.Server(); + ~~~~~~ [no-unused-declaration] + +[no-unused-declaration]: Unused declarations are forbidden diff --git a/fixtures/issues/15/example-3.ts.fix b/fixtures/issues/15/example-3.ts.fix new file mode 100644 index 0000000..315b842 --- /dev/null +++ b/fixtures/issues/15/example-3.ts.fix @@ -0,0 +1,8 @@ +import * as dotenv from "dotenv"; +import * as Hapi from "hapi"; +import * as path from "path"; +dotenv.config({ path: path.join(__dirname, "../.env") }); +// Just import the module to run the code inside and create global Array shim +import "./arrayIncludesShim"; +const server = new Hapi.Server(); + diff --git a/fixtures/issues/15/example-3.ts.lint b/fixtures/issues/15/example-3.ts.lint new file mode 100644 index 0000000..9c26ca7 --- /dev/null +++ b/fixtures/issues/15/example-3.ts.lint @@ -0,0 +1,20 @@ +import * as dotenv from "dotenv"; +import * as Hapi from "hapi"; +import * as path from "path"; +dotenv.config({ path: path.join(__dirname, "../.env") }); +import { ResetTemplateCache } from "./getTemplate"; + ~~~~~~~~~~~~~~~~~~ [no-unused-declaration] +import { +RequestMethod, +~~~~~~~~~~~~~ [no-unused-declaration] +sendAsanaRequest, +~~~~~~~~~~~~~~~~ [no-unused-declaration] +} from "./sendAsanaRequest"; +// Just import the module to run the code inside and create global Array shim +import "./arrayIncludesShim"; +import { startAsanaTimer } from "./startAsanaTimer"; + ~~~~~~~~~~~~~~~ [no-unused-declaration] +const server = new Hapi.Server(); + ~~~~~~ [no-unused-declaration] + +[no-unused-declaration]: Unused declarations are forbidden diff --git a/fixtures/issues/15/tsconfig.json b/fixtures/issues/15/tsconfig.json new file mode 100644 index 0000000..391488a --- /dev/null +++ b/fixtures/issues/15/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "module": "commonjs" + } +} diff --git a/fixtures/issues/15/tslint.json b/fixtures/issues/15/tslint.json new file mode 100644 index 0000000..a01d134 --- /dev/null +++ b/fixtures/issues/15/tslint.json @@ -0,0 +1,8 @@ +{ + "defaultSeverity": "error", + "jsRules": {}, + "rules": { + "no-unused-declaration": { "severity": "error" } + }, + "rulesDirectory": "../../../build/rules" +} diff --git a/fixtures/no-unused-declaration/unused-imports/fixture.ts.fix b/fixtures/no-unused-declaration/unused-imports/fixture.ts.fix index 03c5022..4919772 100644 --- a/fixtures/no-unused-declaration/unused-imports/fixture.ts.fix +++ b/fixtures/no-unused-declaration/unused-imports/fixture.ts.fix @@ -1,4 +1,7 @@ +import { b } from "./letters"; +import { b as basil } from "./letters"; +console.log(b, basil); console.log("the end"); diff --git a/fixtures/no-unused-declaration/unused-imports/fixture.ts.lint b/fixtures/no-unused-declaration/unused-imports/fixture.ts.lint index 33726f7..4281310 100644 --- a/fixtures/no-unused-declaration/unused-imports/fixture.ts.lint +++ b/fixtures/no-unused-declaration/unused-imports/fixture.ts.lint @@ -1,12 +1,24 @@ import { a } from "./letters"; ~ [no-unused-declaration] -import { a as alias } from "./letters"; +import { b } from "./letters"; +import { c, d } from "./letters"; + ~ [no-unused-declaration] + ~ [no-unused-declaration] +import { a as anise } from "./letters"; ~~~~~ [no-unused-declaration] +import { b as basil } from "./letters"; +import { + c as carrot, + ~~~~~~ [no-unused-declaration] + d as dill + ~~~~ [no-unused-declaration] +} from "./letters"; import * as l from "./letters"; ~ [no-unused-declaration] import letters from "./letters"; ~~~~~~~ [no-unused-declaration] +console.log(b, basil); console.log("the end"); [no-unused-declaration]: Unused declarations are forbidden diff --git a/package.json b/package.json index f875f91..8d9c8a3 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "test": "yarn run lint && yarn run test:build && yarn run test:tslint", "test:build": "yarn run test:clean && tsc -p tsconfig.json", "test:clean": "rimraf build", - "test:debug": "tslint --test fixtures/no-unused-declaration/used-destructuring/tslint.json", + "test:debug": "tslint --test fixtures/no-unused-declaration/unused-imports/tslint.json", "test:tslint": "tslint --test fixtures/**/tslint.json" }, "version": "1.4.3" diff --git a/source/rules/noUnusedDeclarationRule.ts b/source/rules/noUnusedDeclarationRule.ts index a1b52b5..d1fc3e5 100644 --- a/source/rules/noUnusedDeclarationRule.ts +++ b/source/rules/noUnusedDeclarationRule.ts @@ -41,6 +41,7 @@ export class Walker extends Lint.ProgramAwareRuleWalker { private _associationsByIdentifier = new Map(); private _declarationsByIdentifier = new Map(); + private _deletes = new Set(); private _scopes = [new Map()]; private _withoutDeclarations = new Set(); private _usageByIdentifier = new Map(); @@ -258,7 +259,9 @@ export class Walker extends Lint.ProgramAwareRuleWalker { private getFix(identifier: ts.Node, declaration: ts.Node): Lint.Fix | undefined { + const { _deletes } = this; if (tsutils.isImportDeclaration(declaration)) { + _deletes.add(declaration); return Lint.Replacement.deleteFromTo( declaration.getFullStart(), declaration.getFullStart() + declaration.getFullWidth() @@ -269,6 +272,10 @@ export class Walker extends Lint.ProgramAwareRuleWalker { if (elements.every(element => _usageByIdentifier.get(element.name) === "declared")) { const importClause = declaration.parent as ts.ImportClause; const importDeclaration = importClause.parent as ts.ImportDeclaration; + if (_deletes.has(importDeclaration)) { + return undefined; + } + _deletes.add(importDeclaration); return Lint.Replacement.deleteFromTo( importDeclaration.getFullStart(), importDeclaration.getFullStart() + importDeclaration.getFullWidth() @@ -285,6 +292,7 @@ export class Walker extends Lint.ProgramAwareRuleWalker { } else if (tsutils.isNamespaceImport(declaration)) { const importClause = declaration.parent as ts.ImportClause; const importDeclaration = importClause.parent as ts.ImportDeclaration; + _deletes.add(importDeclaration); return Lint.Replacement.deleteFromTo( importDeclaration.getFullStart(), importDeclaration.getFullStart() + importDeclaration.getFullWidth()