diff --git a/Jakefile.js b/Jakefile.js index 1ab189a79c..398b897097 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -113,7 +113,8 @@ var scriptSources = [ "tslint/nextLineRule.ts", "tslint/noNullRule.ts", "tslint/preferConstRule.ts", - "tslint/typeOperatorSpacingRule.ts" + "tslint/typeOperatorSpacingRule.ts", + "tslint/noInOperatorRule.ts" ].map(function (f) { return path.join(scriptsDirectory, f); }); @@ -875,7 +876,8 @@ var tslintRules = ([ "noNullRule", "preferConstRule", "booleanTriviaRule", - "typeOperatorSpacingRule" + "typeOperatorSpacingRule", + "noInOperatorRule" ]); var tslintRulesFiles = tslintRules.map(function(p) { return path.join(tslintRuleDir, p + ".ts"); diff --git a/scripts/tslint/noInOperatorRule.ts b/scripts/tslint/noInOperatorRule.ts new file mode 100644 index 0000000000..527e8c1b89 --- /dev/null +++ b/scripts/tslint/noInOperatorRule.ts @@ -0,0 +1,20 @@ +import * as Lint from "tslint/lib/lint"; +import * as ts from "typescript"; + + +export class Rule extends Lint.Rules.AbstractRule { + public static FAILURE_STRING = "Don't use the 'in' keyword - use 'hasProperty' to check for key presence instead"; + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + return this.applyWithWalker(new InWalker(sourceFile, this.getOptions())); + } +} + +class InWalker extends Lint.RuleWalker { + visitNode(node: ts.Node) { + super.visitNode(node); + if (node.kind === ts.SyntaxKind.InKeyword && node.parent && node.parent.kind === ts.SyntaxKind.BinaryExpression) { + this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING)); + } + } +} diff --git a/tslint.json b/tslint.json index 3cafdbfd39..9b010d9a89 100644 --- a/tslint.json +++ b/tslint.json @@ -40,6 +40,7 @@ "no-null": true, "boolean-trivia": true, "type-operator-spacing": true, - "prefer-const": true + "prefer-const": true, + "no-in-operator": true } }