From 1cd016b2892d923d7da41130adb48d7713d83d14 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 26 Aug 2015 11:59:53 -0700 Subject: [PATCH] Boolean trivia rule --- Jakefile.js | 3 +- scripts/tslint/booleanTriviaRule.ts | 50 +++++++++++++++++++++++++++++ tslint.json | 3 +- 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 scripts/tslint/booleanTriviaRule.ts diff --git a/Jakefile.js b/Jakefile.js index d8f2355abb7..3d7c6d93baf 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -774,7 +774,8 @@ var tslintRuleDir = "scripts/tslint"; var tslintRules = ([ "nextLineRule", "noInferrableTypesRule", - "noNullRule" + "noNullRule", + "booleanTriviaRule" ]); var tslintRulesFiles = tslintRules.map(function(p) { return path.join(tslintRuleDir, p + ".ts"); diff --git a/scripts/tslint/booleanTriviaRule.ts b/scripts/tslint/booleanTriviaRule.ts new file mode 100644 index 00000000000..be32a870ff4 --- /dev/null +++ b/scripts/tslint/booleanTriviaRule.ts @@ -0,0 +1,50 @@ +/// +/// + + +export class Rule extends Lint.Rules.AbstractRule { + public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`; + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + const program = ts.createProgram([sourceFile.fileName], Lint.createCompilerOptions()); + const checker = program.getTypeChecker(); + return this.applyWithWalker(new BooleanTriviaWalker(checker, program.getSourceFile(sourceFile.fileName), this.getOptions())); + } +} + +class BooleanTriviaWalker extends Lint.RuleWalker { + constructor(private checker: ts.TypeChecker, file: ts.SourceFile, opts: Lint.IOptions) { + super(file, opts); + } + + visitCallExpression(node: ts.CallExpression) { + super.visitCallExpression(node); + if (node.arguments) { + const targetCallSignature = this.checker.getResolvedSignature(node); + if (!!targetCallSignature) { + const targetParameters = targetCallSignature.getParameters(); + const source = this.getSourceFile(); + for (let index = 0; index < targetParameters.length; index++) { + const param = targetParameters[index]; + const arg = node.arguments[index]; + if (!(arg && param)) continue; + + const argType = this.checker.getContextualType(arg); + if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) { + if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) { + continue; + } + let triviaContent: string; + const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0); + if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) { + triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); //+/-2 to remove /**/ + } + if (triviaContent !== param.getName()) { + this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent))); + } + } + } + } + } + } +} diff --git a/tslint.json b/tslint.json index 4791e7c937c..1e83ef90ffe 100644 --- a/tslint.json +++ b/tslint.json @@ -39,6 +39,7 @@ "no-internal-module": true, "no-trailing-whitespace": true, "no-inferrable-types": true, - "no-null": true + "no-null": true, + "boolean-trivia": true } }