UNPKG

rxjs-tslint-rules

Version:
152 lines (151 loc) 6.65 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 the application of operators after takeUntil.", options: { properties: { alias: { type: "array", items: { type: "string" } }, allow: { type: "array", items: { type: "string" } } }, type: "object" }, optionsDescription: Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n An optional object with optional `alias` and `allow` properties.\n The `alias` property is an array containing the names of operators that aliases for `takeUntil`.\n The `allow` property is an array containing the names of the operators that are allowed to follow `takeUntil`."], ["\n An optional object with optional \\`alias\\` and \\`allow\\` properties.\n The \\`alias\\` property is an array containing the names of operators that aliases for \\`takeUntil\\`.\n The \\`allow\\` property is an array containing the names of the operators that are allowed to follow \\`takeUntil\\`."]))), requiresTypeInfo: true, ruleName: "rxjs-no-unsafe-takeuntil", type: "functionality", typescriptOnly: true }; Rule.FAILURE_STRING = "Applying operators after takeUntil is forbidden"; return Rule; }(Lint.Rules.TypedRule)); exports.Rule = Rule; var Walker = (function (_super) { tslib_1.__extends(Walker, _super); function Walker(sourceFile, options, program) { var _this = _super.call(this, sourceFile, options, program) || this; _this.allow = [ "count", "defaultIfEmpty", "endWith", "every", "finalize", "finally", "isEmpty", "last", "max", "min", "publish", "publishBehavior", "publishLast", "publishReplay", "reduce", "share", "shareReplay", "skipLast", "takeLast", "throwIfEmpty", "toArray" ]; _this.match = /^takeUntil$/; var _a = tslib_1.__read(_this.getOptions(), 1), ruleOptions = _a[0]; if (ruleOptions) { if (ruleOptions.hasOwnProperty("alias")) { _this.match = new RegExp("^(" + ruleOptions.alias.concat("takeUntil").join("|") + ")$"); } if (ruleOptions.hasOwnProperty("allow")) { _this.allow = ruleOptions.allow; } } return _this; } Walker.prototype.visitCallExpression = function (node) { var propertyAccessExpression = node.expression; if (tsutils.isPropertyAccessExpression(propertyAccessExpression)) { var expression = propertyAccessExpression.expression; var propertyName = propertyAccessExpression.name.getText(); var typeChecker = this.getTypeChecker(); var type = typeChecker.getTypeAtLocation(expression); if (util_1.isReferenceType(type) && util_1.couldBeType(type.target, "Observable")) { if (this.match.test(propertyName)) { this.walkPatchedOperators(node, propertyAccessExpression.name); } else if (propertyName === "pipe") { this.walkPipedOperators(node); } } } _super.prototype.visitCallExpression.call(this, node); }; Walker.prototype.walkPatchedOperators = function (node, identifier) { var name = undefined; for (var parent_1 = node.parent; parent_1; parent_1 = parent_1.parent) { if (tsutils.isCallExpression(parent_1)) { if (name) { if (name.getText() === "pipe") { this.walkPipedOperators(parent_1, identifier); } else if (this.allow.indexOf(name.getText()) === -1) { var typeChecker = this.getTypeChecker(); var type = typeChecker.getTypeAtLocation(parent_1); if (util_1.isReferenceType(type) && util_1.couldBeType(type.target, "Observable")) { this.addFailureAtNode(identifier, Rule.FAILURE_STRING); return; } } } } else if (tsutils.isPropertyAccessExpression(parent_1)) { name = parent_1.name; } else { break; } } }; Walker.prototype.walkPipedOperators = function (node, identifier) { var _this = this; if (identifier === void 0) { identifier = null; } var some = function (args) { return args.some(function (arg) { if (tsutils.isCallExpression(arg) && tsutils.isIdentifier(arg.expression) && _this.allow.indexOf(arg.expression.getText()) !== -1) { return false; } return true; }); }; if (identifier) { if (some(node.arguments.slice(0))) { this.addFailureAtNode(identifier, Rule.FAILURE_STRING); } } else { node.arguments.forEach(function (arg, index) { if (tsutils.isCallExpression(arg) && tsutils.isIdentifier(arg.expression) && _this.match.test(arg.expression.text)) { var after_1 = node.arguments.slice(index + 1); if (some(after_1)) { _this.addFailureAtNode(arg.expression, Rule.FAILURE_STRING); } } }); } }; return Walker; }(Lint.ProgramAwareRuleWalker)); var templateObject_1;