diff options
Diffstat (limited to 'node_modules/tslint/lib/rules/banRule.js')
-rw-r--r-- | node_modules/tslint/lib/rules/banRule.js | 201 |
1 files changed, 126 insertions, 75 deletions
diff --git a/node_modules/tslint/lib/rules/banRule.js b/node_modules/tslint/lib/rules/banRule.js index e7ee21f15..4b402160e 100644 --- a/node_modules/tslint/lib/rules/banRule.js +++ b/node_modules/tslint/lib/rules/banRule.js @@ -1,4 +1,6 @@ "use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var tslib_1 = require("tslib"); /** * @license * Copyright 2013 Palantir Technologies, Inc. @@ -15,8 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -Object.defineProperty(exports, "__esModule", { value: true }); -var tslib_1 = require("tslib"); +var tsutils_1 = require("tsutils"); var ts = require("typescript"); var Lint = require("../index"); var Rule = (function (_super) { @@ -29,95 +30,145 @@ var Rule = (function (_super) { return "Calls to '" + expression + "' are not allowed." + (messageAddition !== undefined ? " " + messageAddition : ""); }; Rule.prototype.apply = function (sourceFile) { - var options = this.getOptions(); - var banFunctionWalker = new BanFunctionWalker(sourceFile, options); - var functionsToBan = options.ruleArguments; - if (functionsToBan !== undefined) { - functionsToBan.forEach(function (f) { return banFunctionWalker.addBannedFunction(f); }); - } - return this.applyWithWalker(banFunctionWalker); + return this.applyWithWalker(new BanFunctionWalker(sourceFile, this.ruleName, parseOptions(this.ruleArguments))); }; - return Rule; -}(Lint.Rules.AbstractRule)); -/* tslint:disable:object-literal-sort-keys */ -Rule.metadata = { - ruleName: "ban", - description: "Bans the use of specific functions or global methods.", - optionsDescription: (_a = ["\n A list of `['object', 'method', 'optional explanation here']` or `['globalMethod']` which ban `object.method()`\n or respectively `globalMethod()`."], _a.raw = ["\n A list of \\`['object', 'method', 'optional explanation here']\\` or \\`['globalMethod']\\` which ban \\`object.method()\\`\n or respectively \\`globalMethod()\\`."], Lint.Utils.dedent(_a)), - options: { - type: "list", - listType: { - type: "array", - items: { type: "string" }, - minLength: 1, - maxLength: 3, + /* tslint:disable:object-literal-sort-keys */ + Rule.metadata = { + ruleName: "ban", + description: "Bans the use of specific functions or global methods.", + optionsDescription: (_a = ["\n A list of banned functions or methods in the following format:\n\n * banning functions:\n * just the name of the function: `\"functionName\"`\n * the name of the function in an array with one element: `[\"functionName\"]`\n * an object in the following format: `{\"name\": \"functionName\", \"message\": \"optional explanation message\"}`\n * banning methods:\n * an array with the object name, method name and optional message: `[\"functionName\", \"methodName\", \"optional message\"]`\n * an object in the following format: `{\"name\": [\"objectName\", \"methodName\"], \"message\": \"optional message\"}`\n * you can also ban deeply nested methods: `{\"name\": [\"foo\", \"bar\", \"baz\"]}` bans `foo.bar.baz()`\n * the first element can contain a wildcard (`*`) that matches everything. `{\"name\": [\"*\", \"forEach\"]}` bans `[].forEach(...)`, `$(...).forEach(...)`, `arr.forEach(...)`, etc.\n "], _a.raw = ["\n A list of banned functions or methods in the following format:\n\n * banning functions:\n * just the name of the function: \\`\"functionName\"\\`\n * the name of the function in an array with one element: \\`[\"functionName\"]\\`\n * an object in the following format: \\`{\"name\": \"functionName\", \"message\": \"optional explanation message\"}\\`\n * banning methods:\n * an array with the object name, method name and optional message: \\`[\"functionName\", \"methodName\", \"optional message\"]\\`\n * an object in the following format: \\`{\"name\": [\"objectName\", \"methodName\"], \"message\": \"optional message\"}\\`\n * you can also ban deeply nested methods: \\`{\"name\": [\"foo\", \"bar\", \"baz\"]}\\` bans \\`foo.bar.baz()\\`\n * the first element can contain a wildcard (\\`*\\`) that matches everything. \\`{\"name\": [\"*\", \"forEach\"]}\\` bans\\\n \\`[].forEach(...)\\`, \\`$(...).forEach(...)\\`, \\`arr.forEach(...)\\`, etc.\n "], Lint.Utils.dedent(_a)), + options: { + type: "list", + listType: { + anyOf: [ + { + type: "string", + }, + { + type: "array", + items: { type: "string" }, + minLength: 1, + maxLength: 3, + }, + { + type: "object", + properties: { + name: { + anyOf: [ + { type: "string" }, + { type: "array", items: { type: "string" }, minLength: 1 }, + ], + }, + message: { type: "string" }, + }, + required: ["name"], + }, + ], + }, }, - }, - optionExamples: [ - [ - true, - ["someGlobalMethod"], - ["someObject", "someFunction"], - ["someObject", "otherFunction", "Optional explanation"], + optionExamples: [ + [ + true, + "eval", + { name: "$", message: "please don't" }, + ["describe", "only"], + { name: ["it", "only"], message: "don't focus tests" }, + { name: ["chai", "assert", "equal"], message: "Use 'strictEqual' instead." }, + { name: ["*", "forEach"], message: "Use a regular for loop instead." }, + ], ], - ], - type: "functionality", - typescriptOnly: false, -}; + type: "functionality", + typescriptOnly: false, + }; + return Rule; +}(Lint.Rules.AbstractRule)); exports.Rule = Rule; +function parseOptions(args) { + var functions = []; + var methods = []; + for (var _i = 0, args_1 = args; _i < args_1.length; _i++) { + var arg = args_1[_i]; + if (typeof arg === "string") { + functions.push({ name: arg }); + } + else if (Array.isArray(arg)) { + switch (arg.length) { + case 0: + break; + case 1: + functions.push({ name: arg[0] }); + break; + default: + methods.push({ object: [arg[0]], name: arg[1], message: arg[2] }); + } + } + else if (!Array.isArray(arg.name)) { + functions.push(arg); + } + else { + switch (arg.name.length) { + case 0: + break; + case 1: + functions.push({ name: arg.name[0], message: arg.message }); + break; + default: + methods.push({ name: arg.name[arg.name.length - 1], object: arg.name.slice(0, -1), message: arg.message }); + } + } + } + return { functions: functions, methods: methods }; +} var BanFunctionWalker = (function (_super) { tslib_1.__extends(BanFunctionWalker, _super); function BanFunctionWalker() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.bannedGlobalFunctions = []; - _this.bannedFunctions = []; - return _this; + return _super !== null && _super.apply(this, arguments) || this; } - BanFunctionWalker.prototype.addBannedFunction = function (bannedFunction) { - if (bannedFunction.length === 1) { - this.bannedGlobalFunctions.push(bannedFunction[0]); - } - else if (bannedFunction.length >= 2) { - this.bannedFunctions.push(bannedFunction); - } - }; - BanFunctionWalker.prototype.visitCallExpression = function (node) { - var expression = node.expression; - this.checkForObjectMethodBan(expression); - this.checkForGlobalBan(expression); - _super.prototype.visitCallExpression.call(this, node); + BanFunctionWalker.prototype.walk = function (sourceFile) { + var _this = this; + var cb = function (node) { + if (tsutils_1.isCallExpression(node)) { + if (tsutils_1.isIdentifier(node.expression)) { + _this.checkFunctionBan(node.expression); + } + else if (tsutils_1.isPropertyAccessExpression(node.expression)) { + _this.checkForObjectMethodBan(node.expression); + } + } + return ts.forEachChild(node, cb); + }; + return ts.forEachChild(sourceFile, cb); }; BanFunctionWalker.prototype.checkForObjectMethodBan = function (expression) { - if (expression.kind === ts.SyntaxKind.PropertyAccessExpression - && expression.getChildCount() >= 3) { - var firstToken = expression.getFirstToken(); - var firstChild = expression.getChildAt(0); - var secondChild = expression.getChildAt(1); - var thirdChild = expression.getChildAt(2); - var rightSideExpression = thirdChild.getFullText(); - var leftSideExpression = firstChild.getChildCount() > 0 - ? firstChild.getLastToken().getText() - : firstToken.getText(); - if (secondChild.kind === ts.SyntaxKind.DotToken) { - for (var _i = 0, _a = this.bannedFunctions; _i < _a.length; _i++) { - var bannedFunction = _a[_i]; - if (leftSideExpression === bannedFunction[0] && rightSideExpression === bannedFunction[1]) { - var failure = Rule.FAILURE_STRING_FACTORY(leftSideExpression + "." + rightSideExpression, bannedFunction[2]); - this.addFailureAtNode(expression, failure); - } + for (var _i = 0, _a = this.options.methods; _i < _a.length; _i++) { + var ban = _a[_i]; + if (expression.name.text !== ban.name) { + continue; + } + var current = expression.expression; + for (var i = ban.object.length - 1; i > 0; --i) { + if (!tsutils_1.isPropertyAccessExpression(current) || current.name.text !== ban.object[i]) { + continue; } + current = current.expression; + } + if (ban.object[0] === "*" || + tsutils_1.isIdentifier(current) && current.text === ban.object[0]) { + this.addFailureAtNode(expression, Rule.FAILURE_STRING_FACTORY(ban.object.join(".") + "." + ban.name, ban.message)); + break; } } }; - BanFunctionWalker.prototype.checkForGlobalBan = function (expression) { - if (expression.kind === ts.SyntaxKind.Identifier) { - var identifierName = expression.text; - if (this.bannedGlobalFunctions.indexOf(identifierName) !== -1) { - this.addFailureAtNode(expression, Rule.FAILURE_STRING_FACTORY("" + identifierName)); + BanFunctionWalker.prototype.checkFunctionBan = function (name) { + var text = name.text; + for (var _i = 0, _a = this.options.functions; _i < _a.length; _i++) { + var ban = _a[_i]; + if (ban.name === text) { + this.addFailureAtNode(name, Rule.FAILURE_STRING_FACTORY(text, ban.message)); + break; } } }; return BanFunctionWalker; -}(Lint.RuleWalker)); -exports.BanFunctionWalker = BanFunctionWalker; +}(Lint.AbstractWalker)); var _a; |