diff --git a/README.md b/README.md index 55109959aa5..2f096324e1a 100644 --- a/README.md +++ b/README.md @@ -252,7 +252,7 @@ Core rules are included in the `tslint` package. * `"arguments"` checks alignment of function call arguments. * `"statements"` checks alignment of statements. * `arrow-parens` requires parentheses around the parameters of arrow function definitions. -* `ban` bans the use of specific functions. Options are ["object", "function"] pairs that ban the use of object.function(). +* `ban` bans the use of specific functions. Options are `["object", "function"]` pairs that ban the use of `object.function()`. An optional 3rd parameter may be provided (`["object", "function", "Use 'object.otherFunc' instead."]`) to offer an explanation as to why the function has been banned or to offer an alternative. * `class-name` enforces PascalCased class and interface names. * `comment-format` enforces rules for single-line comments. Rule options: * `"check-space"` enforces the rule that all single-line comments must begin with a space, as in `// comment` diff --git a/src/rules/banRule.ts b/src/rules/banRule.ts index ec2c6b970b7..c958b6cb81d 100644 --- a/src/rules/banRule.ts +++ b/src/rules/banRule.ts @@ -25,7 +25,7 @@ export class Rule extends Lint.Rules.AbstractRule { ruleName: "ban", description: "Bans the use of specific functions.", descriptionDetails: "At this time, there is no way to disable global methods with this rule.", - optionsDescription: "A list of `['object', 'method']` pairs which ban `object.method()`.", + optionsDescription: "A list of `['object', 'method', 'optional explanation here']` which ban `object.method()`.", options: { type: "list", listType: { @@ -33,15 +33,18 @@ export class Rule extends Lint.Rules.AbstractRule { arrayMembers: [ { type: "string" }, { type: "string" }, + { type: "string" }, ], }, }, - optionExamples: [`[true, ["console", "log"], ["someObject", "someFunction"]]`], + optionExamples: [`[true, ["someObject", "someFunction"], ["someObject", "otherFunction", "Optional explanation"]]`], type: "functionality", }; /* tslint:enable:object-literal-sort-keys */ - public static FAILURE_STRING_PART = "function invocation disallowed: "; + public static FAILURE_STRING_FACTORY = (expression: string, messageAddition?: string) => { + return `Calls to '${expression}' are not allowed.${messageAddition ? " " + messageAddition : ""}`; + }; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { const options = this.getOptions(); @@ -86,7 +89,7 @@ export class BanFunctionWalker extends Lint.RuleWalker { const failure = this.createFailure( expression.getStart(), expression.getWidth(), - `${Rule.FAILURE_STRING_PART}${leftSideExpression}.${rightSideExpression}` + Rule.FAILURE_STRING_FACTORY(`${leftSideExpression}.${rightSideExpression}`, bannedFunction[2]) ); this.addFailure(failure); } diff --git a/test/rules/ban/test.ts.lint b/test/rules/ban/test.ts.lint index c8067440dae..3ac20772ce8 100644 --- a/test/rules/ban/test.ts.lint +++ b/test/rules/ban/test.ts.lint @@ -1,13 +1,15 @@ console.time(); window.toString(); -~~~~~~~~~~~~~~~ [function invocation disallowed: window.toString] +~~~~~~~~~~~~~~~ [Calls to 'window.toString' are not allowed.] console.log(); document.window.toString(); -~~~~~~~~~~~~~~~~~~~~~~~~ [function invocation disallowed: window.toString] +~~~~~~~~~~~~~~~~~~~~~~~~ [Calls to 'window.toString' are not allowed.] reference.randomContainer.window.toString(); -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [function invocation disallowed: window.toString] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Calls to 'window.toString' are not allowed.] globals.getDocument().window.toString(); -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [function invocation disallowed: window.toString] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Calls to 'window.toString' are not allowed.] _.keys(obj).forEach(fun); _.forEach(fun); -~~~~~~~~~ [function invocation disallowed: _.forEach] +~~~~~~~~~ [Calls to '_.forEach' are not allowed.] +_.filter(array); +~~~~~~~~ [Calls to '_.filter' are not allowed. Use the native JavaScript 'myArray.filter' instead.] \ No newline at end of file diff --git a/test/rules/ban/tslint.json b/test/rules/ban/tslint.json index db8ab1b06b3..0271539a492 100644 --- a/test/rules/ban/tslint.json +++ b/test/rules/ban/tslint.json @@ -1,5 +1,10 @@ { "rules": { - "ban": [true, ["window", "toString"], ["_", "forEach"]] + "ban": [ + true, + ["window", "toString"], + ["_", "forEach"], + ["_", "filter", "Use the native JavaScript 'myArray.filter' instead."] + ] } } diff --git a/test/rules/no-console/test.ts.lint b/test/rules/no-console/test.ts.lint index a4062a0aa8c..2ee294b7d6b 100644 --- a/test/rules/no-console/test.ts.lint +++ b/test/rules/no-console/test.ts.lint @@ -1,13 +1,13 @@ console.time(); console.log("log"); -~~~~~~~~~~~ [function invocation disallowed: console.log] +~~~~~~~~~~~ [Calls to 'console.log' are not allowed.] console.dir(object); -~~~~~~~~~~~ [function invocation disallowed: console.dir] +~~~~~~~~~~~ [Calls to 'console.dir' are not allowed.] console.info("info"); console.trace("trace"); console.warn("warn"); -~~~~~~~~~~~~ [function invocation disallowed: console.warn] +~~~~~~~~~~~~ [Calls to 'console.warn' are not allowed.] console.error("error"); -~~~~~~~~~~~~~ [function invocation disallowed: console.error] +~~~~~~~~~~~~~ [Calls to 'console.error' are not allowed.] console.something(); console.timeEnd();