From 9e1c64765029a83a2e43580e022293616861c447 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 28 Sep 2016 07:00:07 -0700 Subject: [PATCH] Always pass a language service to rule.apply* --- src/language/rule/abstractRule.ts | 2 +- src/language/rule/rule.ts | 2 +- src/language/rule/typedRule.ts | 2 +- src/rules/noForInArrayRule.ts | 2 +- src/rules/noMergeableNamespaceRule.ts | 3 +-- src/rules/noUnusedVariableRule.ts | 14 +++++--------- src/rules/noUseBeforeDeclareRule.ts | 3 +-- src/rules/preferForOfRule.ts | 5 ++--- src/rules/restrictPlusOperandsRule.ts | 2 +- src/tslintMulti.ts | 5 +++-- 10 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/language/rule/abstractRule.ts b/src/language/rule/abstractRule.ts index c05c1f25fb4..08c3b11bdd3 100644 --- a/src/language/rule/abstractRule.ts +++ b/src/language/rule/abstractRule.ts @@ -43,7 +43,7 @@ export abstract class AbstractRule implements IRule { return this.options; } - public abstract apply(sourceFile: ts.SourceFile): RuleFailure[]; + public abstract apply(sourceFile: ts.SourceFile, languageService: ts.LanguageService): RuleFailure[]; public applyWithWalker(walker: RuleWalker): RuleFailure[] { walker.walk(walker.getSourceFile()); diff --git a/src/language/rule/rule.ts b/src/language/rule/rule.ts index a4311e425b7..75627cc15d3 100644 --- a/src/language/rule/rule.ts +++ b/src/language/rule/rule.ts @@ -85,7 +85,7 @@ export interface IDisabledInterval { export interface IRule { getOptions(): IOptions; isEnabled(): boolean; - apply(sourceFile: ts.SourceFile): RuleFailure[]; + apply(sourceFile: ts.SourceFile, languageService: ts.LanguageService): RuleFailure[]; applyWithWalker(walker: RuleWalker): RuleFailure[]; } diff --git a/src/language/rule/typedRule.ts b/src/language/rule/typedRule.ts index 026a582a75d..ca2e9a6aa0a 100644 --- a/src/language/rule/typedRule.ts +++ b/src/language/rule/typedRule.ts @@ -21,7 +21,7 @@ import {AbstractRule} from "./abstractRule"; import {RuleFailure} from "./rule"; export abstract class TypedRule extends AbstractRule { - public apply(sourceFile: ts.SourceFile): RuleFailure[] { + public apply(sourceFile: ts.SourceFile, languageService: ts.LanguageService): RuleFailure[] { // if no program is given to the linter, throw an error throw new Error(`${this.getOptions().ruleName} requires type checking`); } diff --git a/src/rules/noForInArrayRule.ts b/src/rules/noForInArrayRule.ts index 51d2c51655e..94151f4dcdc 100644 --- a/src/rules/noForInArrayRule.ts +++ b/src/rules/noForInArrayRule.ts @@ -48,7 +48,7 @@ export class Rule extends Lint.Rules.TypedRule { public static FAILURE_STRING = "for-in loops over arrays are forbidden. Use for-of or array.forEach instead."; - public applyWithProgram(sourceFile: ts.SourceFile, langSvc: Lint.TslintLanguageService): Lint.RuleFailure[] { + public applyWithProgram(sourceFile: ts.SourceFile, langSvc: ts.LanguageService): Lint.RuleFailure[] { const noForInArrayWalker = new NoForInArrayWalker(sourceFile, this.getOptions(), langSvc.getProgram()); return this.applyWithWalker(noForInArrayWalker); } diff --git a/src/rules/noMergeableNamespaceRule.ts b/src/rules/noMergeableNamespaceRule.ts index d3466c5e286..1ffdfc05b13 100644 --- a/src/rules/noMergeableNamespaceRule.ts +++ b/src/rules/noMergeableNamespaceRule.ts @@ -35,8 +35,7 @@ export class Rule extends Lint.Rules.AbstractRule { return `Mergeable namespace ${identifier} found. Merge its contents with the namespace on line ${locationToMerge.line}.`; } - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - const languageService = Lint.createLanguageService(sourceFile.fileName, sourceFile.getFullText()); + public apply(sourceFile: ts.SourceFile, languageService: ts.LanguageService): Lint.RuleFailure[] { const noMergeableNamespaceWalker = new NoMergeableNamespaceWalker(sourceFile, this.getOptions(), languageService); return this.applyWithWalker(noMergeableNamespaceWalker); } diff --git a/src/rules/noUnusedVariableRule.ts b/src/rules/noUnusedVariableRule.ts index ad6930faf3a..22e76b06068 100644 --- a/src/rules/noUnusedVariableRule.ts +++ b/src/rules/noUnusedVariableRule.ts @@ -76,12 +76,12 @@ export class Rule extends Lint.Rules.TypedRule { public static FAILURE_STRING_FACTORY = (type: string, name: string) => `Unused ${type}: '${name}'`; // no-undefined-variable optionally allows type-checking - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithProgram(sourceFile, undefined); + public apply(sourceFile: ts.SourceFile, languageService: ts.LanguageService): Lint.RuleFailure[] { + return this.applyWithProgram(sourceFile, languageService); } - public applyWithProgram(sourceFile: ts.SourceFile, langSvc?: ts.LanguageService): Lint.RuleFailure[] { - return this.applyWithWalker(new NoUnusedVariablesWalker(sourceFile, this.getOptions(), langSvc)); + public applyWithProgram(sourceFile: ts.SourceFile, languageService: ts.LanguageService): Lint.RuleFailure[] { + return this.applyWithWalker(new NoUnusedVariablesWalker(sourceFile, this.getOptions(), languageService)); } } @@ -98,16 +98,12 @@ class NoUnusedVariablesWalker extends Lint.RuleWalker { private possibleFailures: Lint.RuleFailure[] = []; constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, - private languageService?: ts.LanguageService) { + private languageService: ts.LanguageService) { super(sourceFile, options); this.skipVariableDeclaration = false; this.skipParameterDeclaration = false; this.hasSeenJsxElement = false; this.isReactUsed = false; - if (!languageService) { - this.dummyLanguageService = true; - this.languageService = Lint.createLanguageService(sourceFile.fileName, sourceFile.getFullText()); - } const ignorePatternOption = this.getOptions().filter((option: any) => { return typeof option === "object" && option["ignore-pattern"] != null; diff --git a/src/rules/noUseBeforeDeclareRule.ts b/src/rules/noUseBeforeDeclareRule.ts index 1f126607356..c51250d0948 100644 --- a/src/rules/noUseBeforeDeclareRule.ts +++ b/src/rules/noUseBeforeDeclareRule.ts @@ -37,8 +37,7 @@ export class Rule extends Lint.Rules.AbstractRule { public static FAILURE_STRING_PREFIX = "variable '"; public static FAILURE_STRING_POSTFIX = "' used before declaration"; - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - const languageService = Lint.createLanguageService(sourceFile.fileName, sourceFile.getFullText()); + public apply(sourceFile: ts.SourceFile, languageService: ts.LanguageService): Lint.RuleFailure[] { return this.applyWithWalker(new NoUseBeforeDeclareWalker(sourceFile, this.getOptions(), languageService)); } } diff --git a/src/rules/preferForOfRule.ts b/src/rules/preferForOfRule.ts index cd1078cfb31..5fc05b4bfd8 100644 --- a/src/rules/preferForOfRule.ts +++ b/src/rules/preferForOfRule.ts @@ -33,8 +33,7 @@ export class Rule extends Lint.Rules.AbstractRule { public static FAILURE_STRING = "Expected a 'for-of' loop instead of a 'for' loop with this simple iteration"; - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - const languageService = Lint.createLanguageService(sourceFile.fileName, sourceFile.getFullText()); + public apply(sourceFile: ts.SourceFile, languageService: ts.LanguageService): Lint.RuleFailure[] { return this.applyWithWalker(new PreferForOfWalker(sourceFile, this.getOptions(), languageService)); } } @@ -67,7 +66,7 @@ class PreferForOfWalker extends Lint.RuleWalker { // so remove those from the count to get the count inside the loop block const incrementorCount = highlights[0].highlightSpans.length - 3; - // Find `array[i]`-like usages by building up a regex + // Find `array[i]`-like usages by building up a regex const arrayTokenForRegex = arrayToken.getText().replace(".", "\\."); const incrementorForRegex = incrementorVariable.getText().replace(".", "\\."); const regex = new RegExp(`${arrayTokenForRegex}\\[\\s*${incrementorForRegex}\\s*\\]`, "g"); diff --git a/src/rules/restrictPlusOperandsRule.ts b/src/rules/restrictPlusOperandsRule.ts index 3f374aec838..996fbe5c9b9 100644 --- a/src/rules/restrictPlusOperandsRule.ts +++ b/src/rules/restrictPlusOperandsRule.ts @@ -35,7 +35,7 @@ export class Rule extends Lint.Rules.TypedRule { public static MISMATCHED_TYPES_FAILURE = "Types of values used in '+' operation must match"; public static UNSUPPORTED_TYPE_FAILURE_FACTORY = (type: string) => `cannot add type ${type}`; - public applyWithProgram(sourceFile: ts.SourceFile, langSvc: Lint.TslintLanguageService): Lint.RuleFailure[] { + public applyWithProgram(sourceFile: ts.SourceFile, langSvc: ts.LanguageService): Lint.RuleFailure[] { return this.applyWithWalker(new RestrictPlusOperandsWalker(sourceFile, this.getOptions(), langSvc.getProgram())); } } diff --git a/src/tslintMulti.ts b/src/tslintMulti.ts index 39d5c24529d..1387b4d2864 100644 --- a/src/tslintMulti.ts +++ b/src/tslintMulti.ts @@ -28,7 +28,7 @@ import { } from "./configuration"; import { EnableDisableRulesWalker } from "./enableDisableRules"; import { findFormatter } from "./formatterLoader"; -import { wrapProgram } from "./language/languageServiceHost"; +import { createLanguageService, wrapProgram } from "./language/languageServiceHost"; import { IFormatter } from "./language/formatter/formatter"; import { RuleFailure } from "./language/rule/rule"; import { TypedRule } from "./language/rule/typedRule"; @@ -101,6 +101,7 @@ class MultiLinter { } } else { sourceFile = getSourceFile(fileName, source); + this.languageService = createLanguageService(fileName, source); } if (sourceFile === undefined) { @@ -125,7 +126,7 @@ class MultiLinter { if (this.program && rule instanceof TypedRule) { ruleFailures = rule.applyWithProgram(sourceFile, this.languageService); } else { - ruleFailures = rule.apply(sourceFile); + ruleFailures = rule.apply(sourceFile, this.languageService); } for (let ruleFailure of ruleFailures) { if (!this.containsRule(this.failures, ruleFailure)) {