|
| 1 | +/// <reference path="../../node_modules/tslint/typings/typescriptServices.d.ts" /> |
| 2 | +/// <reference path="../../node_modules/tslint/lib/tslint.d.ts" /> |
| 3 | + |
| 4 | + |
| 5 | +export class Rule extends Lint.Rules.AbstractRule { |
| 6 | + public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`; |
| 7 | + |
| 8 | + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { |
| 9 | + const program = ts.createProgram([sourceFile.fileName], Lint.createCompilerOptions()); |
| 10 | + const checker = program.getTypeChecker(); |
| 11 | + return this.applyWithWalker(new BooleanTriviaWalker(checker, program.getSourceFile(sourceFile.fileName), this.getOptions())); |
| 12 | + } |
| 13 | +} |
| 14 | + |
| 15 | +class BooleanTriviaWalker extends Lint.RuleWalker { |
| 16 | + constructor(private checker: ts.TypeChecker, file: ts.SourceFile, opts: Lint.IOptions) { |
| 17 | + super(file, opts); |
| 18 | + } |
| 19 | + |
| 20 | + visitCallExpression(node: ts.CallExpression) { |
| 21 | + super.visitCallExpression(node); |
| 22 | + if (node.arguments) { |
| 23 | + const targetCallSignature = this.checker.getResolvedSignature(node); |
| 24 | + if (!!targetCallSignature) { |
| 25 | + const targetParameters = targetCallSignature.getParameters(); |
| 26 | + const source = this.getSourceFile(); |
| 27 | + for (let index = 0; index < targetParameters.length; index++) { |
| 28 | + const param = targetParameters[index]; |
| 29 | + const arg = node.arguments[index]; |
| 30 | + if (!(arg && param)) continue; |
| 31 | + |
| 32 | + const argType = this.checker.getContextualType(arg); |
| 33 | + if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) { |
| 34 | + if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) { |
| 35 | + continue; |
| 36 | + } |
| 37 | + let triviaContent: string; |
| 38 | + const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0); |
| 39 | + if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) { |
| 40 | + triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); //+/-2 to remove /**/ |
| 41 | + } |
| 42 | + if (triviaContent !== param.getName()) { |
| 43 | + this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent))); |
| 44 | + } |
| 45 | + } |
| 46 | + } |
| 47 | + } |
| 48 | + } |
| 49 | + } |
| 50 | +} |
0 commit comments