UNPKG

rxjs-tslint-rules

Version:
146 lines (145 loc) 6.68 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var Lint = require("tslint"); var tsutils = require("tsutils"); var util_1 = require("../support/util"); var Rule = (function (_super) { tslib_1.__extends(Rule, _super); function Rule() { return _super !== null && _super.apply(this, arguments) || this; } Rule.prototype.applyWithProgram = function (sourceFile, program) { return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program)); }; Rule.metadata = { description: "Disallows unsafe first/take usage in effects and epics.", options: { properties: { observable: { oneOf: [ { type: "string" }, { type: "array", items: { type: "string" } } ] } }, type: "object" }, optionsDescription: Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n An optional object with an optional `observable` property.\n The property can be specifed as a regular expression string or as an array of words and is used to identify the action observables from which effects and epics are composed."], ["\n An optional object with an optional \\`observable\\` property.\n The property can be specifed as a regular expression string or as an array of words and is used to identify the action observables from which effects and epics are composed."]))), requiresTypeInfo: true, ruleName: "rxjs-no-unsafe-first", type: "functionality", typescriptOnly: true }; Rule.FAILURE_STRING = "Unsafe first usage in effects and epics is forbidden"; return Rule; }(Lint.Rules.TypedRule)); exports.Rule = Rule; var Walker = (function (_super) { tslib_1.__extends(Walker, _super); function Walker(sourceFile, rawOptions, program) { var _this = _super.call(this, sourceFile, rawOptions, program) || this; var _a = tslib_1.__read(_this.getOptions(), 1), options = _a[0]; if (options && (options.allow || options.disallow)) { _this.observableRegExp = new RegExp(options.observable || Walker.DEFAULT_OBSERVABLE, "i"); } else { _this.observableRegExp = new RegExp(Walker.DEFAULT_OBSERVABLE, "i"); } return _this; } Walker.prototype.visitCallExpression = function (node) { var propertyAccessExpression = node.expression; if (tsutils.isPropertyAccessExpression(propertyAccessExpression)) { var observableExpression = propertyAccessExpression.expression; var observableIdentifier = undefined; if (tsutils.isIdentifier(observableExpression)) { observableIdentifier = observableExpression; } else if (tsutils.isPropertyAccessExpression(observableExpression)) { observableIdentifier = observableExpression.name; } if (observableIdentifier && this.observableRegExp.test(observableIdentifier.getText())) { var propertyName = propertyAccessExpression.name.getText(); var typeChecker = this.getTypeChecker(); var type = typeChecker.getTypeAtLocation(observableExpression); if (util_1.isReferenceType(type) && Walker.METHODS_REGEXP.test(propertyName) && util_1.couldBeType(type.target, "Observable")) { switch (propertyName) { case "ofType": this.walkPatchedTypes(node); break; case "pipe": this.walkPipedTypes(node); break; default: break; } } } } _super.prototype.visitCallExpression.call(this, node); }; Walker.prototype.walkPatchedOperators = function (node) { var name = undefined; for (var parent_1 = node.parent; parent_1; parent_1 = parent_1.parent) { if (tsutils.isCallExpression(parent_1)) { if (name) { switch (name.getText()) { case "first": this.addFailureAtNode(name, Rule.FAILURE_STRING); break; case "take": this.addFailureAtNode(name, Rule.FAILURE_STRING); break; case "pipe": this.walkPipedOperators(parent_1); break; default: break; } } } else if (tsutils.isPropertyAccessExpression(parent_1)) { name = parent_1.name; } else { break; } } }; Walker.prototype.walkPatchedTypes = function (node) { this.walkPatchedOperators(node); }; Walker.prototype.walkPipedOperators = function (node) { var _this = this; node.arguments.forEach(function (arg) { if (tsutils.isCallExpression(arg)) { var expression = arg.expression; if (tsutils.isIdentifier(expression) && (expression.getText() === "first" || expression.getText() === "take")) { _this.addFailureAtNode(expression, Rule.FAILURE_STRING); } } }); }; Walker.prototype.walkPipedTypes = function (node) { var _this = this; node.arguments.forEach(function (arg) { if (tsutils.isCallExpression(arg)) { var expression = arg.expression; if (tsutils.isIdentifier(expression) && expression.getText() === "ofType") { _this.walkPipedOperators(node); } } }); }; Walker.METHODS_REGEXP = /(ofType|pipe)/; Walker.DEFAULT_OBSERVABLE = String.raw(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["action(s|$)?"], ["action(s|\\$)?"]))); return Walker; }(Lint.ProgramAwareRuleWalker)); exports.Walker = Walker; var templateObject_1, templateObject_2;