Skip to content

Commit

Permalink
feat(rxjs-add): Add file option.
Browse files Browse the repository at this point in the history
  • Loading branch information
cartant committed May 30, 2017
1 parent 8a40381 commit 3743ccd
Show file tree
Hide file tree
Showing 16 changed files with 311 additions and 8 deletions.
3 changes: 3 additions & 0 deletions fixtures/no-errors-with-file/adds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import "rxjs/add/observable/of";
import "rxjs/add/operator/filter";
import "rxjs/add/operator/map";
38 changes: 38 additions & 0 deletions fixtures/no-errors-with-file/fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Observable } from "rxjs/Observable";

const ob1 = Observable.of(1).map((value) => value + 1);

const ob2 = Observable.of(2);
ob2.filter((value) => value > 1);

function ob3(): Observable<number> {
return Observable.of(3);
}
ob3().filter((value) => value > 1);

class Thing {

public ob4 = Observable.of(4);

get ob5(): Observable<number> {
return Observable.of(5);
}

ob6(): Observable<number> {
return Observable.of(6);
}
};

const thing = new Thing();
thing.ob4.filter((value) => value > 1);
thing.ob5.filter((value) => value > 1);
thing.ob6().filter((value) => value > 1);

const array = [Observable.of(7)];
array[0].filter((value) => value > 1);

const OtherObservable = Observable;
const ob8 = OtherObservable.of(8);

const OtherObservables = [Observable];
const ob9 = OtherObservables[0].of(9);
13 changes: 13 additions & 0 deletions fixtures/no-errors-with-file/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"baseUrl": ".",
"lib": ["es2015"],
"noEmit": true,
"paths": {
"rxjs": ["../node_modules/rxjs"]
},
"skipLibCheck": true,
"target": "es5"
},
"include": ["adds.ts", "fixture.ts"]
}
13 changes: 13 additions & 0 deletions fixtures/no-errors-with-file/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"defaultSeverity": "error",
"jsRules": {},
"rules": {
"rxjs-add": {
"options": [{
"file": "./adds.ts"
}],
"severity": "error"
}
},
"rulesDirectory": "../../build/rules"
}
2 changes: 2 additions & 0 deletions fixtures/no-observable-with-file/adds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import "rxjs/add/operator/filter";
import "rxjs/add/operator/map";
38 changes: 38 additions & 0 deletions fixtures/no-observable-with-file/fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Observable } from "rxjs/Observable";

const ob1 = Observable.of(1).map((value) => value + 1);

const ob2 = Observable.of(2);
ob2.filter((value) => value > 1);

function ob3(): Observable<number> {
return Observable.of(3);
}
ob3().filter((value) => value > 1);

class Thing {

public ob4 = Observable.of(4);

get ob5(): Observable<number> {
return Observable.of(5);
}

ob6(): Observable<number> {
return Observable.of(6);
}
};

const thing = new Thing();
thing.ob4.filter((value) => value > 1);
thing.ob5.filter((value) => value > 1);
thing.ob6().filter((value) => value > 1);

const array = [Observable.of(7)];
array[0].filter((value) => value > 1);

const OtherObservable = Observable;
const ob8 = OtherObservable.of(8);

const OtherObservables = [Observable];
const ob9 = OtherObservables[0].of(9);
13 changes: 13 additions & 0 deletions fixtures/no-observable-with-file/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"baseUrl": ".",
"lib": ["es2015"],
"noEmit": true,
"paths": {
"rxjs": ["../node_modules/rxjs"]
},
"skipLibCheck": true,
"target": "es5"
},
"include": ["adds.ts", "fixture.ts"]
}
13 changes: 13 additions & 0 deletions fixtures/no-observable-with-file/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"defaultSeverity": "error",
"jsRules": {},
"rules": {
"rxjs-add": {
"options": [{
"file": "./adds.ts"
}],
"severity": "error"
}
},
"rulesDirectory": "../../build/rules"
}
2 changes: 2 additions & 0 deletions fixtures/no-operator-with-file/adds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import "rxjs/add/observable/of";
import "rxjs/add/operator/map";
38 changes: 38 additions & 0 deletions fixtures/no-operator-with-file/fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Observable } from "rxjs/Observable";

const ob1 = Observable.of(1).map((value) => value + 1);

const ob2 = Observable.of(2);
ob2.filter((value) => value > 1);

function ob3(): Observable<number> {
return Observable.of(3);
}
ob3().filter((value) => value > 1);

class Thing {

public ob4 = Observable.of(4);

get ob5(): Observable<number> {
return Observable.of(5);
}

ob6(): Observable<number> {
return Observable.of(6);
}
};

const thing = new Thing();
thing.ob4.filter((value) => value > 1);
thing.ob5.filter((value) => value > 1);
thing.ob6().filter((value) => value > 1);

const array = [Observable.of(7)];
array[0].filter((value) => value > 1);

const OtherObservable = Observable;
const ob8 = OtherObservable.of(8);

const OtherObservables = [Observable];
const ob9 = OtherObservables[0].of(9);
13 changes: 13 additions & 0 deletions fixtures/no-operator-with-file/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"baseUrl": ".",
"lib": ["es2015"],
"noEmit": true,
"paths": {
"rxjs": ["../node_modules/rxjs"]
},
"skipLibCheck": true,
"target": "es5"
},
"include": ["adds.ts", "fixture.ts"]
}
13 changes: 13 additions & 0 deletions fixtures/no-operator-with-file/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"defaultSeverity": "error",
"jsRules": {},
"rules": {
"rxjs-add": {
"options": [{
"file": "./adds.ts"
}],
"severity": "error"
}
},
"rulesDirectory": "../../build/rules"
}
45 changes: 45 additions & 0 deletions source/fixtures-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ describe("fixtures", function (): void {
});
});

describe("no-errors-with-file", () => {

it("should effect no errors", () => {

const result = lint("no-errors-with-file", "tslint.json");

expect(result).to.have.property("errorCount", 0);
});
});

describe("no-observable", () => {

it("should effect 'rxjs-add' errors", () => {
Expand All @@ -96,6 +106,25 @@ describe("fixtures", function (): void {
});
});

describe("no-observable-with-file", () => {

it("should effect 'rxjs-add' errors", () => {

const result = lint("no-observable-with-file", "tslint.json");

expect(result).to.have.property("errorCount", 9);
expect(result.failures[0]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[1]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[2]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[3]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[4]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[5]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[6]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[7]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[8]).to.have.property("ruleName", "rxjs-add");
});
});

describe("no-operator", () => {

it("should effect 'rxjs-add' errors", () => {
Expand All @@ -112,6 +141,22 @@ describe("fixtures", function (): void {
});
});

describe("no-operator-with-file", () => {

it("should effect 'rxjs-add' errors", () => {

const result = lint("no-operator-with-file", "tslint.json");

expect(result).to.have.property("errorCount", 6);
expect(result.failures[0]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[1]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[2]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[3]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[4]).to.have.property("ruleName", "rxjs-add");
expect(result.failures[5]).to.have.property("ruleName", "rxjs-add");
});
});

describe("observable-create", () => {

it("should effect an error unless explicit typing is used", () => {
Expand Down
67 changes: 63 additions & 4 deletions source/rules/rxjsAddRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
/*tslint:disable:no-use-before-declare*/

import * as Lint from "tslint";
import * as path from "path";
import * as ts from "typescript";

import { AddedWalker } from "../support/added-walker";
import { UsedWalker } from "../support/used-walker";

export class Rule extends Lint.Rules.TypedRule {
Expand All @@ -24,24 +26,81 @@ class Walker extends UsedWalker {

protected onSourceFileEnd(): void {

let { addedObservables, addedOperators } = this;
let failure = Rule.FAILURE_STRING;

const [options] = this.getOptions();
if (options && options.file) {
const walker = this.walkFile(options.file);
addedObservables = walker.addedObservables;
addedOperators = walker.addedOperators;
failure = `${Rule.FAILURE_STRING} from ${options.file}`;
}

Object.keys(this.usedObservables).forEach((key) => {

if (!this.addedObservables[key]) {
if (!addedObservables[key]) {
this.usedObservables[key].forEach((node) => this.addFailureAtNode(
node,
`${Rule.FAILURE_STRING}: ${key}`
`${failure}: ${key}`
));
}
});

Object.keys(this.usedOperators).forEach((key) => {

if (!this.addedOperators[key]) {
if (!addedOperators[key]) {
this.usedOperators[key].forEach((node) => this.addFailureAtNode(
node,
`${Rule.FAILURE_STRING}: ${key}`
`${failure}: ${key}`
));
}
});
}

private findSourceFile(file: string): ts.SourceFile {

const program = this.getProgram();
const rootFiles = program.getRootFileNames();

for (let i = 0, length = rootFiles.length; i < length; ++i) {
const configFile = ts.findConfigFile(
this.normalizeFile(path.dirname(rootFiles[i])),
ts.sys.fileExists
);
if (configFile) {
const resolvedFile = this.normalizeFile(
path.resolve(path.dirname(configFile), file)
);
const sourceFile = program.getSourceFileByPath(resolvedFile as any);
if (sourceFile) {
return sourceFile;
} else {
break;
}
}
}

throw new Error(`Cannot find ${file}`);
}

private normalizeFile(file: string): string {

const normalized = ts["normalizeSlashes"](file);
return ts.sys.useCaseSensitiveFileNames ? normalized : normalized.toLowerCase();
}

private walkFile(file: string): AddedWalker {

const sourceFile = this.findSourceFile(file);
const fileWalker = new AddedWalker(sourceFile, {
disabledIntervals: [],
ruleArguments: [],
ruleName: this.getRuleName(),
ruleSeverity: "error"
}, this.getProgram());

fileWalker.walk(sourceFile);
return fileWalker;
}
}
4 changes: 2 additions & 2 deletions source/support/added-walker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import * as ts from "typescript";

export class AddedWalker extends Lint.ProgramAwareRuleWalker {

protected addedObservables: { [key: string]: ts.Node[] } = {};
protected addedOperators: { [key: string]: ts.Node[] } = {};
public addedObservables: { [key: string]: ts.Node[] } = {};
public addedOperators: { [key: string]: ts.Node[] } = {};

protected add(
map: { [key: string]: ts.Node[] },
Expand Down
4 changes: 2 additions & 2 deletions source/support/used-walker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { knownObservables, knownOperators } from "./knowns";

export class UsedWalker extends AddedWalker {

protected usedObservables: { [key: string]: ts.Node[] } = {};
protected usedOperators: { [key: string]: ts.Node[] } = {};
public usedObservables: { [key: string]: ts.Node[] } = {};
public usedOperators: { [key: string]: ts.Node[] } = {};

protected visitCallExpression(node: ts.CallExpression): void {

Expand Down

0 comments on commit 3743ccd

Please sign in to comment.