From dc9dd3e667d9d99a487741f4633c7caad8df9515 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 26 Aug 2015 14:47:25 -0700 Subject: [PATCH] Give up on real typechecking, just check literals --- scripts/tslint/noInferrableTypesRule.ts | 46 ++++++++++++++++++------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/scripts/tslint/noInferrableTypesRule.ts b/scripts/tslint/noInferrableTypesRule.ts index 16e0633c872..e1c6614170c 100644 --- a/scripts/tslint/noInferrableTypesRule.ts +++ b/scripts/tslint/noInferrableTypesRule.ts @@ -3,30 +3,52 @@ export class Rule extends Lint.Rules.AbstractRule { - public static FAILURE_STRING = "LHS type inferred by RHS expression, remove type annotation"; + public static FAILURE_STRING_FACTORY = (type: string) => `LHS type (${type}) inferred by RHS expression, remove type annotation`; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - const program = ts.createProgram([sourceFile.fileName], Lint.createCompilerOptions()); - return this.applyWithWalker(new InferrableTypeWalker(sourceFile, this.getOptions(), program)); + return this.applyWithWalker(new InferrableTypeWalker(sourceFile, this.getOptions())); } } class InferrableTypeWalker extends Lint.RuleWalker { - constructor(file: ts.SourceFile, opts: Lint.IOptions, private program: ts.Program) { - super(program.getSourceFile(file.fileName), opts); + private originalService: ts.LanguageService; + private fileName: string; + private originalContent: string; + + constructor(file: ts.SourceFile, opts: Lint.IOptions) { + this.fileName = file.fileName; + this.originalContent = file.getFullText(); + this.originalService = ts.createLanguageService(Lint.createLanguageServiceHost(this.fileName, this.originalContent)); + super(this.originalService.getSourceFile(this.fileName), opts); } visitVariableStatement(node: ts.VariableStatement) { node.declarationList.declarations.forEach(e => { - if ( - (!!e.type) && - (!!e.initializer) && - (this.program.getTypeChecker().getTypeAtLocation(e.type) === this.program.getTypeChecker().getContextualType(e.initializer)) - ) { - this.addFailure(this.createFailure(e.type.getStart(), e.type.getWidth(), Rule.FAILURE_STRING)); + if ((!!e.type) && (!!e.initializer)) { + let failure: string; + switch (e.type.kind) { + case ts.SyntaxKind.BooleanKeyword: + if (e.initializer.kind === ts.SyntaxKind.TrueKeyword || e.initializer.kind === ts.SyntaxKind.FalseKeyword) { + failure = 'boolean'; + } + break; + case ts.SyntaxKind.NumberKeyword: + if (e.initializer.kind === ts.SyntaxKind.NumericLiteral) { + failure = 'number'; + } + break; + case ts.SyntaxKind.StringKeyword: + if (e.initializer.kind === ts.SyntaxKind.StringLiteral || e.initializer.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral) { + failure = 'string'; + } + break; + } + if (failure) { + this.addFailure(this.createFailure(e.type.getStart(), e.type.getWidth(), Rule.FAILURE_STRING_FACTORY(failure))); + } } }); - + super.visitVariableStatement(node); } }