Skip to content

Commit

Permalink
feat(rule): rxjs-throw-error.
Browse files Browse the repository at this point in the history
  • Loading branch information
cartant committed Mar 7, 2018
1 parent 1bb14e9 commit 26beb0e
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 0 deletions.
8 changes: 8 additions & 0 deletions fixtures/throw-error/fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Observable } from "rxjs";
import { _throw } from "rxjs/observable/throw";
import "rxjs/add/observable/throw";

const ob1 = Observable.throw("Boom!");
const ob2 = Observable.throw(new Error("Boom!"));
const ob3 = _throw("Boom!");
const ob4 = _throw(new Error("Boom!"));
13 changes: 13 additions & 0 deletions fixtures/throw-error/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": ["fixture.ts"]
}
8 changes: 8 additions & 0 deletions fixtures/throw-error/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"defaultSeverity": "error",
"jsRules": {},
"rules": {
"rxjs-throw-error": { "severity": "error" }
},
"rulesDirectory": "../../build/rules"
}
11 changes: 11 additions & 0 deletions source/fixtures-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ describe("fixtures", function (): void {
result.failures.forEach(failure => expect(failure).to.have.property("ruleName", "rxjs-no-tap"));
});
});

describe("throw-error", () => {

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

const result = lint("throw-error", "tslint.json");

expect(result).to.have.property("errorCount", 2);
result.failures.forEach(failure => expect(failure).to.have.property("ruleName", "rxjs-throw-error"));
});
});
});

describe("import-related rules", () => {
Expand Down
67 changes: 67 additions & 0 deletions source/rules/rxjsThrowErrorRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* @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 * as tsutils from "tsutils";

import { couldBeType, isReferenceType } from "../support/util";

export class Rule extends Lint.Rules.TypedRule {

public static metadata: Lint.IRuleMetadata = {
description: "Disallows the throwing of non-Error values.",
options: null,
optionsDescription: "Not configurable.",
requiresTypeInfo: true,
ruleName: "rxjs-throw-error",
type: "functionality",
typescriptOnly: true
};

public static FAILURE_STRING = "Throwing non-Error values is forbidden";

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {

return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program));
}
}

export class Walker extends Lint.ProgramAwareRuleWalker {

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

const { arguments: [argument], expression } = node;
const typeChecker = this.getTypeChecker();

if (tsutils.isPropertyAccessExpression(expression)) {

const name = expression.name.getText();
const type = typeChecker.getTypeAtLocation(expression.expression);

if ((name === "throw") && couldBeType(type, "Observable")) {
if (!argument || !couldBeType(typeChecker.getTypeAtLocation(argument), "Error")) {
this.addFailureAtNode(node, Rule.FAILURE_STRING);
}
}

} else if (tsutils.isIdentifier(expression)) {

const name = expression.getText();
const type = typeChecker.getTypeAtLocation(expression);
const [signature] = typeChecker.getSignaturesOfType(type, ts.SignatureKind.Call);
const returnType = typeChecker.getReturnTypeOfSignature(signature);

if (((name === "_throw") || (name === "throwError")) && couldBeType(returnType, "Observable")) {
if (!argument || !couldBeType(typeChecker.getTypeAtLocation(argument), "Error")) {
this.addFailureAtNode(node, Rule.FAILURE_STRING);
}
}
}

super.visitCallExpression(node);
}
}

0 comments on commit 26beb0e

Please sign in to comment.