Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

applyWithFunction: allow passing TypeChecker or Program directly #3140

Merged
merged 1 commit into from
Aug 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/language/rule/abstractRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,20 @@ export abstract class AbstractRule implements IRule {

protected applyWithFunction(sourceFile: ts.SourceFile, walkFn: (ctx: WalkContext<void>) => void): RuleFailure[];
protected applyWithFunction<T>(sourceFile: ts.SourceFile, walkFn: (ctx: WalkContext<T>) => void, options: NoInfer<T>): RuleFailure[];
protected applyWithFunction<T>(sourceFile: ts.SourceFile, walkFn: (ctx: WalkContext<T | void>) => void, options?: T): RuleFailure[] {
protected applyWithFunction<T, U>(
sourceFile: ts.SourceFile,
walkFn: (ctx: WalkContext<T>, programOrChecker: U) => void,
options: NoInfer<T>,
checker: NoInfer<U>,
): RuleFailure[];
protected applyWithFunction<T, U>(
sourceFile: ts.SourceFile,
walkFn: (ctx: WalkContext<T | void>, programOrChecker?: U) => void,
options?: T,
programOrChecker?: U,
): RuleFailure[] {
const ctx = new WalkContext(sourceFile, this.ruleName, options);
walkFn(ctx);
walkFn(ctx, programOrChecker);
return ctx.failures;
}

Expand Down
6 changes: 3 additions & 3 deletions src/rules/awaitPromiseRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ export class Rule extends Lint.Rules.TypedRule {

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
const promiseTypes = new Set(["Promise", ...this.ruleArguments as string[]]);
const tc = program.getTypeChecker();
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, tc, promiseTypes));
return this.applyWithFunction(sourceFile, walk, promiseTypes, program.getTypeChecker());
}
}

function walk(ctx: Lint.WalkContext<void>, tc: ts.TypeChecker, promiseTypes: Set<string>) {
function walk(ctx: Lint.WalkContext<Set<string>>, tc: ts.TypeChecker) {
const promiseTypes = ctx.options;
return ts.forEachChild(ctx.sourceFile, cb);

function cb(node: ts.Node): void {
Expand Down
2 changes: 1 addition & 1 deletion src/rules/deprecationRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class Rule extends Lint.Rules.TypedRule {
}

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/rules/matchDefaultExportNameRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class Rule extends Lint.Rules.TypedRule {
}

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/rules/noBooleanLiteralCompareRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class Rule extends Lint.Rules.TypedRule {
}

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/rules/noFloatingPromisesRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ export class Rule extends Lint.Rules.TypedRule {
public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(
sourceFile,
(ctx) => walk(ctx, program.getTypeChecker()),
walk,
["Promise", ...this.ruleArguments as string[]],
program.getTypeChecker(),
);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/rules/noForInArrayRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ 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, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

function walk(ctx: Lint.WalkContext<void>, program: ts.Program) {
function walk(ctx: Lint.WalkContext<void>, checker: ts.TypeChecker) {
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.ForInStatement) {
const type = program.getTypeChecker().getTypeAtLocation((node as ts.ForInStatement).expression);
const type = checker.getTypeAtLocation((node as ts.ForInStatement).expression);
if (type.symbol !== undefined && type.symbol.name === "Array" ||
// tslint:disable-next-line:no-bitwise
(type.flags & ts.TypeFlags.StringLike) !== 0) {
Expand Down
11 changes: 8 additions & 3 deletions src/rules/noUnboundMethodRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,14 @@ export class Rule extends Lint.Rules.TypedRule {
public static FAILURE_STRING = "Avoid referencing unbound methods which may cause unintentional scoping of 'this'.";

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()), {
ignoreStatic: this.ruleArguments.indexOf(OPTION_IGNORE_STATIC) !== -1,
});
return this.applyWithFunction(
sourceFile,
walk,
{
ignoreStatic: this.ruleArguments.indexOf(OPTION_IGNORE_STATIC) !== -1,
},
program.getTypeChecker(),
);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/rules/noUnnecessaryQualifierRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class Rule extends Lint.Rules.TypedRule {
}

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/rules/noUnsafeAnyRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class Rule extends Lint.Rules.TypedRule {
public static FAILURE_STRING = "Unsafe use of expression of type 'any'.";

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/rules/noUnusedVariableRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export class Rule extends Lint.Rules.TypedRule {
"the 'no-unused-locals' and 'no-unused-parameters' compiler options are enabled.");
}

return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program, parseOptions(this.ruleArguments)));
return this.applyWithFunction(sourceFile, walk, parseOptions(this.ruleArguments), program);
}
}

Expand All @@ -99,8 +99,8 @@ function parseOptions(options: any[]): Options {
return { checkParameters, ignorePattern };
}

function walk(ctx: Lint.WalkContext<void>, program: ts.Program, { checkParameters, ignorePattern }: Options): void {
const { sourceFile } = ctx;
function walk(ctx: Lint.WalkContext<Options>, program: ts.Program): void {
const { sourceFile, options: { checkParameters, ignorePattern } } = ctx;
const unusedCheckedProgram = getUnusedCheckedProgram(program, checkParameters);
const diagnostics = ts.getPreEmitDiagnostics(unusedCheckedProgram, sourceFile);
const checker = unusedCheckedProgram.getTypeChecker(); // Doesn't matter which program is used for this.
Expand Down Expand Up @@ -151,7 +151,7 @@ function walk(ctx: Lint.WalkContext<void>, program: ts.Program, { checkParameter
* - If all of the import specifiers in an import are unused, add a combined failure for them all.
* - Unused imports are fixable.
*/
function addImportSpecifierFailures(ctx: Lint.WalkContext<void>, failures: Map<ts.Identifier, string>, sourceFile: ts.SourceFile) {
function addImportSpecifierFailures(ctx: Lint.WalkContext<Options>, failures: Map<ts.Identifier, string>, sourceFile: ts.SourceFile) {
forEachImport(sourceFile, (importNode) => {
if (importNode.kind === ts.SyntaxKind.ImportEqualsDeclaration) {
tryRemoveAll(importNode.name);
Expand Down
2 changes: 1 addition & 1 deletion src/rules/noUseBeforeDeclareRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class Rule extends Lint.Rules.TypedRule {
}

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/rules/noVoidExpressionRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ export class Rule extends Lint.Rules.TypedRule {

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
const ignoreArrowFunctionShorthand = this.ruleArguments.indexOf(OPTION_IGNORE_ARROW_FUNCTION_SHORTHAND) !== -1;
return this.applyWithFunction(
sourceFile, (ctx) => walk(ctx, program.getTypeChecker()), { ignoreArrowFunctionShorthand });
return this.applyWithFunction(sourceFile, walk, { ignoreArrowFunctionShorthand }, program.getTypeChecker());
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/rules/objectLiteralSortKeysRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ export class Rule extends Lint.Rules.OptionallyTypedRule {
public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(
sourceFile,
(ctx) => walk(ctx, program.getTypeChecker()),
walk,
parseOptions(this.ruleArguments),
program.getTypeChecker(),
);
}
}
Expand Down
9 changes: 7 additions & 2 deletions src/rules/preferTemplateRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import * as Lint from "../index";

const OPTION_SINGLE_CONCAT = "allow-single-concat";

interface Options {
allowSingleConcat: boolean;
}

export class Rule extends Lint.Rules.AbstractRule {
/* tslint:disable:object-literal-sort-keys */
public static metadata: Lint.IRuleMetadata = {
Expand All @@ -48,11 +52,12 @@ export class Rule extends Lint.Rules.AbstractRule {
}

const allowSingleConcat = this.ruleArguments.indexOf(OPTION_SINGLE_CONCAT) !== -1;
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, allowSingleConcat));
return this.applyWithFunction(sourceFile, walk, {allowSingleConcat});
}
}

function walk(ctx: Lint.WalkContext<void>, allowSingleConcat: boolean): void {
function walk(ctx: Lint.WalkContext<Options>): void {
const allowSingleConcat = ctx.options.allowSingleConcat;
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
const failure = getError(node, allowSingleConcat);
if (failure !== undefined) {
Expand Down
2 changes: 1 addition & 1 deletion src/rules/promiseFunctionAsyncRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class Rule extends Lint.Rules.TypedRule {
public static FAILURE_STRING = "functions that return promises must be async";

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/rules/restrictPlusOperandsRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@ export class Rule extends Lint.Rules.TypedRule {
public static INVALID_TYPES_ERROR = "Operands of '+' operation must either be both strings or both numbers";

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

function walk(ctx: Lint.WalkContext<void>, program: ts.Program) {
function walk(ctx: Lint.WalkContext<void>, tc: ts.TypeChecker) {
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
if (isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.PlusToken) {
const tc = program.getTypeChecker();
const leftType = getBaseTypeOfLiteralType(tc.getTypeAtLocation(node.left));
const rightType = getBaseTypeOfLiteralType(tc.getTypeAtLocation(node.right));
if (leftType === "invalid" || rightType === "invalid" || leftType !== rightType) {
Expand Down
2 changes: 1 addition & 1 deletion src/rules/returnUndefinedRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class Rule extends Lint.Rules.TypedRule {
"`void` function should use `return;`, not `return undefined;`.";

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/rules/strictBooleanExpressionsRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class Rule extends Lint.Rules.TypedRule {

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
const options = parseOptions(this.ruleArguments, Lint.isStrictNullChecksEnabled(program.getCompilerOptions()));
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()), options);
return this.applyWithFunction(sourceFile, walk, options, program.getTypeChecker());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/rules/strictTypePredicatesRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class Rule extends Lint.Rules.TypedRule {
showWarningOnce("strict-type-predicates does not work without --strictNullChecks");
return [];
}
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/rules/useDefaultTypeParameterRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class Rule extends Lint.Rules.TypedRule {
public static FAILURE_STRING = "This is the default value for this type parameter, so it can be omitted.";

public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, (ctx) => walk(ctx, program.getTypeChecker()));
return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
}
}

Expand Down