From adaba186a75668f451c137c6299f5141e98e4150 Mon Sep 17 00:00:00 2001 From: Boris Cherny Date: Tue, 15 Nov 2016 10:29:08 -0800 Subject: [PATCH] simplify usage, better error message --- README.md | 5 +---- noCircularImportsRule.ts | 26 ++++++++++++++++++-------- package.json | 4 ++-- tslint-no-circular-imports.json | 6 ++++++ 4 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 tslint-no-circular-imports.json diff --git a/README.md b/README.md index 3e8432a..d6c85d8 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,7 @@ Add the following to your tslint.json: ```json { - "rulesDirectory": "node_modules/tslint-no-circular-imports", - "rules": { - "no-circular-imports": true - } + "extends": ["tslint-no-circular-imports"] } ``` diff --git a/noCircularImportsRule.ts b/noCircularImportsRule.ts index 05dfa5b..5a43b29 100644 --- a/noCircularImportsRule.ts +++ b/noCircularImportsRule.ts @@ -1,8 +1,9 @@ +import { basename } from 'path' import * as ts from 'typescript' import * as Lint from 'tslint/lib/lint' export class Rule extends Lint.Rules.AbstractRule { - static FAILURE_STRING = 'circular import detected' + static FAILURE_STRING = 'Circular import detected' static metadata: Lint.IRuleMetadata = { ruleName: 'no-circular-imports', @@ -37,7 +38,11 @@ class NoCircularImportsWalker extends Lint.RuleWalker { // check for cycles if (this.hasCycle(thisModuleName)) { - this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING)) + this.addFailure( + this.createFailure(node.getStart(), node.getWidth(), `${Rule.FAILURE_STRING}: ${ + this.getCycle(thisModuleName).concat(thisModuleName).map(_ => basename(_)).join(' -> ') + }`) + ) } super.visitImportDeclaration(node) @@ -53,12 +58,17 @@ class NoCircularImportsWalker extends Lint.RuleWalker { imports.get(thisModuleName)!.add(importCanonicalName) } - private hasCycle(moduleName: string, accumulator: string[] = []): boolean { - if (!imports.get(moduleName)) return false - if (accumulator.includes(moduleName)) return true - return Array.from(imports.get(moduleName)!.values()).some(_ => - this.hasCycle(_, accumulator.concat(moduleName)) - ) + private hasCycle(moduleName: string): boolean { + return this.getCycle(moduleName).length > 0 + } + + private getCycle(moduleName: string, accumulator: string[] = []): string[] { + if (!imports.get(moduleName)) return [] + if (accumulator.includes(moduleName)) return accumulator + return Array.from(imports.get(moduleName) !.values()).reduce((_prev, _) => { + const c = this.getCycle(_, accumulator.concat(moduleName)) + return c.length ? c : [] + }, [] as string[]) } } \ No newline at end of file diff --git a/package.json b/package.json index 2e58f10..a5da8ab 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "tslint-no-circular-imports", - "version": "0.0.2", + "version": "0.0.3", "description": "TSLint plugin to detect and warn about cicular imports", - "main": "noCircularImportsRule.js", + "main": "./tslint-no-circular-imports.json", "scripts": { "build": "npm run build-sources && npm test", "build-sources": "tsc -p ./tsconfig.json", diff --git a/tslint-no-circular-imports.json b/tslint-no-circular-imports.json new file mode 100644 index 0000000..74b89de --- /dev/null +++ b/tslint-no-circular-imports.json @@ -0,0 +1,6 @@ +{ + "rulesDirectory": "./", + "rules": { + "no-circular-imports": true + } +}