From ae4403f5e5f56aacf1882755e5be9135d32917e9 Mon Sep 17 00:00:00 2001 From: Nicholas Jamieson Date: Fri, 18 Jan 2019 12:23:22 +1000 Subject: [PATCH] feat(no-compat): Add no-compat rule. --- package.json | 2 +- source/rules/rxjsNoCompatRule.ts | 47 +++++++++++++++++++ .../no-compat/default/fixture.ts.lint | 25 ++++++++++ .../fixtures/no-compat/default/tsconfig.json | 13 +++++ .../v6/fixtures/no-compat/default/tslint.json | 8 ++++ 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 source/rules/rxjsNoCompatRule.ts create mode 100644 test/v6/fixtures/no-compat/default/fixture.ts.lint create mode 100644 test/v6/fixtures/no-compat/default/tsconfig.json create mode 100644 test/v6/fixtures/no-compat/default/tslint.json diff --git a/package.json b/package.json index e58cee54..4e848840 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "test": "yarn run lint && yarn run test:build && yarn run test:mocha && yarn run test:tslint-v5 && yarn run test:tslint-v6 && yarn run test:tslint-v6-compat", "test:build": "yarn run test:clean && tsc -p tsconfig.json", "test:clean": "rimraf build", - "test:debug": "tslint --test ./test/v6/fixtures/issues/70/tslint.json", + "test:debug": "tslint --test ./test/v6/fixtures/no-compat/default/tslint.json", "test:issues": "yarn run test:clean && tsc -p tsconfig.json && tslint --test ./test/v6/fixtures/issues/**/tslint.json", "test:mocha": "mocha build/**/*-spec.js", "test:tslint-v5": "yarn --cwd ./test/v5 install && yarn --cwd ./test/v5 upgrade && tslint --test ./test/v5/fixtures/**/tslint.json", diff --git a/source/rules/rxjsNoCompatRule.ts b/source/rules/rxjsNoCompatRule.ts new file mode 100644 index 00000000..2f053a81 --- /dev/null +++ b/source/rules/rxjsNoCompatRule.ts @@ -0,0 +1,47 @@ +/** + * @license Use of this source code is governed by an MIT-style license that + * can be found in the LICENSE file at https://github.com/cartant/rxjs-tslint-rules + */ +/*tslint:disable:no-use-before-declare*/ + +import * as Lint from "tslint"; +import * as ts from "typescript"; +import { tsquery } from "@phenomnomnominal/tsquery"; + +export class Rule extends Lint.Rules.AbstractRule { + + public static metadata: Lint.IRuleMetadata = { + deprecationMessage: undefined, + description: "Disallows importation from locations that depend upon 'rxjs-compat'.", + options: null, + optionsDescription: "Not configurable.", + requiresTypeInfo: false, + ruleName: "rxjs-no-compat", + type: "functionality", + typescriptOnly: false + }; + + public static FAILURE_STRING = "'rxjs-compat' dependent import locations are forbidden"; + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + const failures: Lint.RuleFailure[] = []; + const importDeclarations = tsquery( + sourceFile, + `ImportDeclaration:has(StringLiteral[value=/^rxjs/])` + ); + importDeclarations.forEach(node => { + const importDeclaration = node as ts.ImportDeclaration; + const { moduleSpecifier } = importDeclaration; + if (!/^['"]rxjs(\/(ajax|operators|testing|webSocket))?['"]$/.test(moduleSpecifier.getText())) { + failures.push(new Lint.RuleFailure( + sourceFile, + moduleSpecifier.getStart(), + moduleSpecifier.getStart() + moduleSpecifier.getWidth(), + Rule.FAILURE_STRING, + this.ruleName + )); + } + }); + return failures; + } +} diff --git a/test/v6/fixtures/no-compat/default/fixture.ts.lint b/test/v6/fixtures/no-compat/default/fixture.ts.lint new file mode 100644 index 00000000..4a8cea63 --- /dev/null +++ b/test/v6/fixtures/no-compat/default/fixture.ts.lint @@ -0,0 +1,25 @@ +import { Observable } from "rxjs"; +import { ajax } from "rxjs/ajax"; +import { concatMap } from "rxjs/operators"; +import { TestScheduler } from "rxjs/testing"; +import { webSocket } from "rxjs/webSocket"; + +import * as Rx from "rxjs/Rx"; + ~~~~~~~~~ [no-compat] +import { Observable } from "rxjs/Observable"; + ~~~~~~~~~~~~~~~~~ [no-compat] +import { Subject } from "rxjs/Subject"; + ~~~~~~~~~~~~~~ [no-compat] +import { merge } from "rxjs/observable/merge"; + ~~~~~~~~~~~~~~~~~~~~~~~ [no-compat] +import { mergeMap } from "rxjs/operator/mergeMap"; + ~~~~~~~~~~~~~~~~~~~~~~~~ [no-compat] +import { asap } from "rxjs/scheduler/asap"; + ~~~~~~~~~~~~~~~~~~~~~ [no-compat] + +import "rxjs/add/observable/merge"; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ [no-compat] +import "rxjs/add/operator/mergeMap"; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [no-compat] + +[no-compat]: 'rxjs-compat' dependent import locations are forbidden diff --git a/test/v6/fixtures/no-compat/default/tsconfig.json b/test/v6/fixtures/no-compat/default/tsconfig.json new file mode 100644 index 00000000..690be78e --- /dev/null +++ b/test/v6/fixtures/no-compat/default/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "lib": ["es2015"], + "noEmit": true, + "paths": { + "rxjs": ["../../node_modules/rxjs"] + }, + "skipLibCheck": true, + "target": "es5" + }, + "include": ["fixture.ts"] +} diff --git a/test/v6/fixtures/no-compat/default/tslint.json b/test/v6/fixtures/no-compat/default/tslint.json new file mode 100644 index 00000000..03ffb5e5 --- /dev/null +++ b/test/v6/fixtures/no-compat/default/tslint.json @@ -0,0 +1,8 @@ +{ + "defaultSeverity": "error", + "jsRules": {}, + "rules": { + "rxjs-no-compat": { "severity": "error" } + }, + "rulesDirectory": "../../../../../build/rules" +}