From c07ac5e085365562301672cef4e59f159b7a84d0 Mon Sep 17 00:00:00 2001 From: Rafael Santana Date: Sat, 23 Mar 2019 17:52:39 -0300 Subject: [PATCH] refactor: walkers/visitors being exported (#793) --- src/angularWhitespaceRule.ts | 19 ++++++------- src/componentClassSuffixRule.ts | 8 +++--- src/componentMaxInlineDeclarationsRule.ts | 6 +++-- src/contextualDecoratorRule.ts | 6 +++-- src/contextualLifecycleRule.ts | 10 ++++--- src/directiveClassSuffixRule.ts | 9 ++++--- src/noInputPrefixRule.ts | 7 ++--- src/noInputRenameRule.ts | 6 +++-- src/noLifecycleCallRule.ts | 6 +++-- src/noOutputNativeRule.ts | 6 +++-- src/noOutputOnPrefixRule.ts | 6 +++-- src/noOutputRenameRule.ts | 6 +++-- src/noPipeImpureRule.ts | 12 +++++---- src/noUnusedCssRule.ts | 27 +++++++++---------- src/pipePrefixRule.ts | 8 +++--- src/preferInlineDecoratorRule.ts | 6 +++-- ...referOnPushComponentChangeDetectionRule.ts | 6 +++-- src/preferOutputReadonlyRule.ts | 6 +++-- src/relativeUrlPrefixRule.ts | 6 +++-- src/templateAccessibilityAltTextRule.ts | 15 +++++------ ...emplateAccessibilityElementsContentRule.ts | 15 +++++------ src/templateAccessibilityLabelForRule.ts | 16 +++++------ ...lateAccessibilityTabindexNoPositiveRule.ts | 13 +++++---- src/templateAccessibilityTableScopeRule.ts | 13 +++++---- src/templateAccessibilityValidAriaRule.ts | 15 +++++------ src/templateBananaInBoxRule.ts | 13 +++++---- src/templateClickEventsHaveKeyEventsRule.ts | 15 +++++------ src/templateConditionalComplexityRule.ts | 13 +++++---- src/templateCyclomaticComplexityRule.ts | 13 +++++---- src/templateI18nRule.ts | 21 +++++++-------- src/templateMouseEventsHaveKeyEventsRule.ts | 13 +++++---- src/templateNoAnyRule.ts | 13 +++++---- src/templateNoAutofocusRule.ts | 13 +++++---- src/templateNoCallExpressionRule.ts | 19 ++++++------- src/templateNoDistractingElementsRule.ts | 13 +++++---- src/templateNoNegatedAsyncRule.ts | 13 +++++---- src/templateUseTrackByFunctionRule.ts | 21 ++++++++------- src/useComponentSelectorRule.ts | 6 +++-- src/useComponentViewEncapsulationRule.ts | 6 +++-- 39 files changed, 233 insertions(+), 212 deletions(-) diff --git a/src/angularWhitespaceRule.ts b/src/angularWhitespaceRule.ts index 977acb17f..8f764f07d 100644 --- a/src/angularWhitespaceRule.ts +++ b/src/angularWhitespaceRule.ts @@ -3,7 +3,7 @@ import * as Lint from 'tslint'; import * as ts from 'typescript'; import { Config } from './angular/config'; import { ExpTypes } from './angular/expressionTypes'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; import { RecursiveAngularExpressionVisitor } from './angular/templates/recursiveAngularExpressionVisitor'; @@ -162,7 +162,7 @@ class SemicolonTemplateVisitor extends BasicTemplateAstVisitor implements Config } } -class WhitespaceTemplateVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { private visitors: (BasicTemplateAstVisitor & ConfigurableVisitor)[] = [ new InterpolationWhitespaceVisitor(this.getSourceFile(), this.getOptions(), this.context, this.templateStart), new SemicolonTemplateVisitor(this.getSourceFile(), this.getOptions(), this.context, this.templateStart) @@ -259,7 +259,7 @@ class PipeWhitespaceVisitor extends RecursiveAngularExpressionVisitor implements } } -class TemplateExpressionVisitor extends RecursiveAngularExpressionVisitor { +class ExpressionVisitorCtrl extends RecursiveAngularExpressionVisitor { private visitors: (RecursiveAngularExpressionVisitor & ConfigurableVisitor)[] = [ new PipeWhitespaceVisitor(this.getSourceFile(), this.getOptions(), this.context, this.basePosition) ]; @@ -310,12 +310,13 @@ export class Rule extends Lint.Rules.AbstractRule { }; apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - expressionVisitorCtrl: TemplateExpressionVisitor, - templateVisitorCtrl: WhitespaceTemplateVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { + expressionVisitorCtrl: ExpressionVisitorCtrl, + templateVisitorCtrl: TemplateVisitorCtrl + }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } isEnabled(): boolean { diff --git a/src/componentClassSuffixRule.ts b/src/componentClassSuffixRule.ts index 83e47cd2f..fdd98bec3 100644 --- a/src/componentClassSuffixRule.ts +++ b/src/componentClassSuffixRule.ts @@ -1,11 +1,11 @@ import { sprintf } from 'sprintf-js'; import * as Lint from 'tslint'; import * as ts from 'typescript'; +import { NgWalker } from './angular'; import { ComponentMetadata } from './angular/metadata'; -import { Maybe, F2 } from './util/function'; +import { F2, Maybe } from './util/function'; import { Failure } from './walkerFactory/walkerFactory'; import { all, validateComponent } from './walkerFactory/walkerFn'; -import { NgWalker } from '.'; export class Rule extends Lint.Rules.AbstractRule { static readonly metadata: Lint.IRuleMetadata = { @@ -51,6 +51,8 @@ export class Rule extends Lint.Rules.AbstractRule { } apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(Rule.walkerBuilder(sourceFile, this.getOptions())); + const walker = Rule.walkerBuilder(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } diff --git a/src/componentMaxInlineDeclarationsRule.ts b/src/componentMaxInlineDeclarationsRule.ts index 6aebb50cf..7f3fd2a68 100644 --- a/src/componentMaxInlineDeclarationsRule.ts +++ b/src/componentMaxInlineDeclarationsRule.ts @@ -66,7 +66,9 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = `Exceeds the maximum allowed inline lines for %s. Defined limit: %s / total lines: %s (${STYLE_GUIDE_LINK})`; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new MaxInlineDeclarationsWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } isEnabled(): boolean { @@ -81,7 +83,7 @@ export class Rule extends AbstractRule { } } -export class MaxInlineDeclarationsWalker extends NgWalker { +class Walker extends NgWalker { private readonly animationsLinesLimit = DEFAULT_ANIMATIONS_LIMIT; private readonly stylesLinesLimit = DEFAULT_STYLES_LIMIT; private readonly templateLinesLimit = DEFAULT_TEMPLATE_LIMIT; diff --git a/src/contextualDecoratorRule.ts b/src/contextualDecoratorRule.ts index efa3d246e..b4c0dc3ba 100644 --- a/src/contextualDecoratorRule.ts +++ b/src/contextualDecoratorRule.ts @@ -39,11 +39,13 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = 'The decorator "%s" is not allowed for class "%s" because it is decorated with "%s"'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new ContextualDecoratorWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -export class ContextualDecoratorWalker extends NgWalker { +class Walker extends NgWalker { protected visitMethodDecorator(decorator: Decorator): void { this.validateDecorator(decorator); super.visitMethodDecorator(decorator); diff --git a/src/contextualLifecycleRule.ts b/src/contextualLifecycleRule.ts index a845b96ef..8335553a8 100644 --- a/src/contextualLifecycleRule.ts +++ b/src/contextualLifecycleRule.ts @@ -1,7 +1,8 @@ import { sprintf } from 'sprintf-js'; import { IRuleMetadata, RuleFailure } from 'tslint/lib'; import { AbstractRule } from 'tslint/lib/rules'; -import { ClassDeclaration, Decorator, SourceFile } from 'typescript'; +import { SourceFile } from 'typescript'; +import { InjectableMetadata, ModuleMetadata, PipeMetadata } from './angular'; import { NgWalker } from './angular/ngWalker'; import { getClassName, @@ -14,7 +15,6 @@ import { MetadataTypeKeys, MetadataTypes } from './util/utils'; -import { InjectableMetadata, ModuleMetadata, PipeMetadata } from './angular'; interface FailureParameters { readonly className: string; @@ -41,11 +41,13 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = 'The method "%s" is not allowed for class "%s" because it is decorated with "%s"'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new ContextualLifecycleWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -class ContextualLifecycleWalker extends NgWalker { +class Walker extends NgWalker { protected visitNgInjectable(metadata: InjectableMetadata): void { this.validateDecorator(metadata, METADATA_TYPE_LIFECYCLE_MAPPER.Injectable); super.visitNgInjectable(metadata); diff --git a/src/directiveClassSuffixRule.ts b/src/directiveClassSuffixRule.ts index 0e63471a1..3941e52f4 100644 --- a/src/directiveClassSuffixRule.ts +++ b/src/directiveClassSuffixRule.ts @@ -1,11 +1,10 @@ import { sprintf } from 'sprintf-js'; import * as Lint from 'tslint'; import * as ts from 'typescript'; +import { DirectiveMetadata } from './angular/metadata'; import { NgWalker } from './angular/ngWalker'; import { getSymbolName } from './util/utils'; -import { DirectiveMetadata } from './angular/metadata'; - const ValidatorSuffix = 'Validator'; export class Rule extends Lint.Rules.AbstractRule { @@ -34,11 +33,13 @@ export class Rule extends Lint.Rules.AbstractRule { } apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new ClassMetadataWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -export class ClassMetadataWalker extends NgWalker { +class Walker extends NgWalker { protected visitNgDirective(metadata: DirectiveMetadata) { const name = metadata.controller.name!; const className = name.text; diff --git a/src/noInputPrefixRule.ts b/src/noInputPrefixRule.ts index 3a4a62e96..ba8ecba44 100644 --- a/src/noInputPrefixRule.ts +++ b/src/noInputPrefixRule.ts @@ -1,7 +1,6 @@ import { sprintf } from 'sprintf-js'; import { IOptions, IRuleMetadata, RuleFailure, Rules, Utils } from 'tslint/lib'; import { Decorator, PropertyDeclaration, SourceFile } from 'typescript'; - import { NgWalker } from './angular/ngWalker'; export class Rule extends Rules.AbstractRule { @@ -30,7 +29,9 @@ export class Rule extends Rules.AbstractRule { static readonly FAILURE_STRING = '@Inputs should not be prefixed by %s'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new NoInputPrefixWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } isEnabled(): boolean { @@ -62,7 +63,7 @@ export const getFailureMessage = (prefixes: string[]): string => { return sprintf(Rule.FAILURE_STRING, getReadablePrefixes(prefixes)); }; -class NoInputPrefixWalker extends NgWalker { +class Walker extends NgWalker { private readonly blacklistedPrefixes: string[]; constructor(source: SourceFile, options: IOptions) { diff --git a/src/noInputRenameRule.ts b/src/noInputRenameRule.ts index 47e5a7106..fdf48bc52 100644 --- a/src/noInputRenameRule.ts +++ b/src/noInputRenameRule.ts @@ -26,7 +26,9 @@ export class Rule extends AbstractRule { `; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new InputMetadataWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } @@ -74,7 +76,7 @@ const whiteListAliases = new Set([ 'aria-valuetext' ]); -export class InputMetadataWalker extends NgWalker { +class Walker extends NgWalker { private directiveSelectors!: ReadonlyArray; protected visitNgDirective(metadata: DirectiveMetadata): void { diff --git a/src/noLifecycleCallRule.ts b/src/noLifecycleCallRule.ts index 3c150dc1d..53bb3ddb9 100644 --- a/src/noLifecycleCallRule.ts +++ b/src/noLifecycleCallRule.ts @@ -18,11 +18,13 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = 'Avoid explicit calls to lifecycle methods'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new ExpressionCallMetadataWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -class ExpressionCallMetadataWalker extends NgWalker { +class Walker extends NgWalker { visitCallExpression(node: CallExpression): void { this.validateCallExpression(node); super.visitCallExpression(node); diff --git a/src/noOutputNativeRule.ts b/src/noOutputNativeRule.ts index 57382cf1f..9765d707f 100644 --- a/src/noOutputNativeRule.ts +++ b/src/noOutputNativeRule.ts @@ -202,11 +202,13 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = 'In the class "%s", the output property "%s" should not be named or renamed as a native event'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new NoOutputNativeWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -class NoOutputNativeWalker extends NgWalker { +class Walker extends NgWalker { protected visitNgOutput(property: PropertyDeclaration, output: Decorator, args: string[]): void { this.validateOutput(property, args); super.visitNgOutput(property, output, args); diff --git a/src/noOutputOnPrefixRule.ts b/src/noOutputOnPrefixRule.ts index 4da05c3ad..73e3b81f3 100644 --- a/src/noOutputOnPrefixRule.ts +++ b/src/noOutputOnPrefixRule.ts @@ -20,11 +20,13 @@ export class Rule extends Lint.Rules.AbstractRule { static readonly FAILURE_STRING = 'In the class "%s", the output property "%s" should not be prefixed with on'; apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new OutputWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -class OutputWalker extends NgWalker { +class Walker extends NgWalker { protected visitNgOutput(property: ts.PropertyDeclaration, output: ts.Decorator, args: string[]) { this.validateOutput(property); super.visitNgOutput(property, output, args); diff --git a/src/noOutputRenameRule.ts b/src/noOutputRenameRule.ts index 084998dea..f94e990c9 100644 --- a/src/noOutputRenameRule.ts +++ b/src/noOutputRenameRule.ts @@ -18,7 +18,9 @@ export class Rule extends Rules.AbstractRule { static readonly FAILURE_STRING = '@Outputs should not be renamed'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new OutputMetadataWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } @@ -26,7 +28,7 @@ export const getFailureMessage = (): string => { return Rule.FAILURE_STRING; }; -export class OutputMetadataWalker extends NgWalker { +class Walker extends NgWalker { private directiveSelectors!: ReadonlySet; protected visitNgDirective(metadata: DirectiveMetadata): void { diff --git a/src/noPipeImpureRule.ts b/src/noPipeImpureRule.ts index 0d0fca0a1..1a0e02177 100644 --- a/src/noPipeImpureRule.ts +++ b/src/noPipeImpureRule.ts @@ -1,10 +1,10 @@ import { sprintf } from 'sprintf-js'; import { IRuleMetadata, RuleFailure } from 'tslint'; import { AbstractRule } from 'tslint/lib/rules'; -import { ClassDeclaration, Decorator, SourceFile, SyntaxKind } from 'typescript'; -import { NgWalker } from './angular/ngWalker'; -import { getClassName, getDecoratorPropertyInitializer } from './util/utils'; +import { SourceFile, SyntaxKind } from 'typescript'; import { PipeMetadata } from './angular'; +import { NgWalker } from './angular/ngWalker'; +import { getClassName } from './util/utils'; interface FailureParameters { readonly className: string; @@ -27,11 +27,13 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = 'Impure pipe declared in class %s'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new ClassMetadataWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -export class ClassMetadataWalker extends NgWalker { +class Walker extends NgWalker { protected visitNgPipe(metadata: PipeMetadata): void { this.validatePipe(metadata); super.visitNgPipe(metadata); diff --git a/src/noUnusedCssRule.ts b/src/noUnusedCssRule.ts index ed4200162..3f09f68fa 100644 --- a/src/noUnusedCssRule.ts +++ b/src/noUnusedCssRule.ts @@ -1,17 +1,15 @@ import { ElementAst, EmbeddedTemplateAst, PropertyBindingType, TemplateAst } from '@angular/compiler'; import * as Lint from 'tslint'; import * as ts from 'typescript'; - -import { NgWalker } from './angular/ngWalker'; +import { ComponentMetadata, StyleMetadata } from './angular/metadata'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicCssAstVisitor } from './angular/styles/basicCssAstVisitor'; import { CssAst, CssSelectorAst, CssSelectorRuleAst } from './angular/styles/cssAst'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; import { parseTemplate } from './angular/templates/templateParser'; -import { getComponentDecorator, getDecoratorPropertyInitializer, getSymbolName } from './util/utils'; - -import { ComponentMetadata, StyleMetadata } from './angular/metadata'; import { logger } from './util/logger'; import { SemVerDSL } from './util/ngVersion'; +import { getComponentDecorator, getDecoratorPropertyInitializer, getSymbolName } from './util/utils'; interface Strategy { attribute(ast: ElementAst): boolean; @@ -126,7 +124,7 @@ class ElementFilterVisitor extends BasicTemplateAstVisitor { } export class Rule extends Lint.Rules.AbstractRule { - public static metadata: Lint.IRuleMetadata = { + static readonly metadata: Lint.IRuleMetadata = { ruleName: 'no-unused-css', type: 'maintainability', description: "Disallows having an unused CSS rule in the component's stylesheet.", @@ -136,16 +134,15 @@ export class Rule extends Lint.Rules.AbstractRule { hasFix: true }; - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker( - new UnusedCssNgVisitor(sourceFile, this.getOptions(), { - cssVisitorCtrl: UnusedCssVisitor - }) - ); + apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + const walkerConfig: NgWalkerConfig = { cssVisitorCtrl: CssVisitorCtrl }; + const walker = new Walker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } -class UnusedCssVisitor extends BasicCssAstVisitor { +class CssVisitorCtrl extends BasicCssAstVisitor { templateAst!: TemplateAst; constructor( @@ -221,7 +218,7 @@ class UnusedCssVisitor extends BasicCssAstVisitor { } // Finds the template and wrapes the parsed content into a root element -export class UnusedCssNgVisitor extends NgWalker { +class Walker extends NgWalker { private templateAst!: TemplateAst; visitClassDeclaration(declaration: ts.ClassDeclaration) { @@ -283,7 +280,7 @@ export class UnusedCssNgVisitor extends NgWalker { } const file = this.getContextSourceFile(styleMetadata.url!, styleMetadata.style.source!); - const visitor = new UnusedCssVisitor(file, this._originalOptions, context, styleMetadata, baseStart); + const visitor = new CssVisitorCtrl(file, this._originalOptions, context, styleMetadata, baseStart); visitor.templateAst = this.templateAst; const d = getComponentDecorator(context.controller)!; const encapsulation = getDecoratorPropertyInitializer(d, 'encapsulation'); diff --git a/src/pipePrefixRule.ts b/src/pipePrefixRule.ts index a309523c0..ea873df43 100644 --- a/src/pipePrefixRule.ts +++ b/src/pipePrefixRule.ts @@ -1,10 +1,10 @@ import { sprintf } from 'sprintf-js'; import * as Lint from 'tslint'; import * as ts from 'typescript'; +import { PipeMetadata } from './angular'; import { NgWalker } from './angular/ngWalker'; import { SelectorValidator } from './util/selectorValidator'; import { getDecoratorArgument } from './util/utils'; -import { PipeMetadata } from './angular'; export class Rule extends Lint.Rules.AbstractRule { static readonly metadata: Lint.IRuleMetadata = { @@ -46,7 +46,9 @@ export class Rule extends Lint.Rules.AbstractRule { } apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new ClassMetadataWalker(sourceFile, this)); + const walker = new Walker(sourceFile, this); + + return this.applyWithWalker(walker); } isEnabled(): boolean { @@ -65,7 +67,7 @@ export class Rule extends Lint.Rules.AbstractRule { } } -export class ClassMetadataWalker extends NgWalker { +class Walker extends NgWalker { constructor(sourceFile: ts.SourceFile, private rule: Rule) { super(sourceFile, rule.getOptions()); } diff --git a/src/preferInlineDecoratorRule.ts b/src/preferInlineDecoratorRule.ts index 6efe16346..1c0a6c103 100644 --- a/src/preferInlineDecoratorRule.ts +++ b/src/preferInlineDecoratorRule.ts @@ -28,7 +28,9 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = 'Consider placing decorators on the same line as the property/method it decorates'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new PreferInlineDecoratorWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } isEnabled(): boolean { @@ -36,7 +38,7 @@ export class Rule extends AbstractRule { } } -export class PreferInlineDecoratorWalker extends NgWalker { +class Walker extends NgWalker { private readonly blacklistedDecorators: ReadonlySet; constructor(source: SourceFile, options: IOptions) { diff --git a/src/preferOnPushComponentChangeDetectionRule.ts b/src/preferOnPushComponentChangeDetectionRule.ts index 3598550ea..c6e0bdcb5 100644 --- a/src/preferOnPushComponentChangeDetectionRule.ts +++ b/src/preferOnPushComponentChangeDetectionRule.ts @@ -31,11 +31,13 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = `The changeDetection value of a component should be set to ChangeDetectionStrategy.${ON_PUSH}`; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new PreferOnPushComponentChangeDetectionWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -class PreferOnPushComponentChangeDetectionWalker extends NgWalker { +class Walker extends NgWalker { protected visitNgComponent(metadata: ComponentMetadata): void { this.validateComponent(metadata); super.visitNgComponent(metadata); diff --git a/src/preferOutputReadonlyRule.ts b/src/preferOutputReadonlyRule.ts index 8b5a2a4e3..0e2c4e88c 100644 --- a/src/preferOutputReadonlyRule.ts +++ b/src/preferOutputReadonlyRule.ts @@ -15,11 +15,13 @@ export class Rule extends Rules.AbstractRule { static readonly FAILURE_STRING = 'Prefer to declare `@Output` as readonly since they are not supposed to be reassigned'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new OutputMetadataWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -export class OutputMetadataWalker extends NgWalker { +class Walker extends NgWalker { protected visitNgOutput(property: PropertyDeclaration, output: Decorator, args: string[]) { this.validateOutput(property); super.visitNgOutput(property, output, args); diff --git a/src/relativeUrlPrefixRule.ts b/src/relativeUrlPrefixRule.ts index 792aa647a..427b97b01 100644 --- a/src/relativeUrlPrefixRule.ts +++ b/src/relativeUrlPrefixRule.ts @@ -18,11 +18,13 @@ export class Rule extends Rules.AbstractRule { static readonly FAILURE_STRING = 'The ./ prefix is standard syntax for relative URLs. (https://angular.io/styleguide#style-05-04)'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new RelativeUrlPrefixWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -class RelativeUrlPrefixWalker extends NgWalker { +class Walker extends NgWalker { constructor(sourceFile: SourceFile, options: IOptions) { super(sourceFile, options); } diff --git a/src/templateAccessibilityAltTextRule.ts b/src/templateAccessibilityAltTextRule.ts index c1bc1d47f..433fa3585 100644 --- a/src/templateAccessibilityAltTextRule.ts +++ b/src/templateAccessibilityAltTextRule.ts @@ -1,8 +1,8 @@ -import { ElementAst, AttrAst, BoundElementPropertyAst, TextAst } from '@angular/compiler'; +import { AttrAst, BoundElementPropertyAst, ElementAst, TextAst } from '@angular/compiler'; import { sprintf } from 'sprintf-js'; import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib'; import { SourceFile } from 'typescript/lib/typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; export class Rule extends Rules.AbstractRule { @@ -20,11 +20,10 @@ export class Rule extends Rules.AbstractRule { static readonly DEFAULT_ELEMENTS = ['img', 'object', 'area', 'input[type="image"]']; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateAccessibilityAltTextVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } @@ -32,7 +31,7 @@ export const getFailureMessage = (name: string): string => { return sprintf(Rule.FAILURE_STRING, name); }; -class TemplateAccessibilityAltTextVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitElement(ast: ElementAst, context: any) { this.validateElement(ast); super.visitElement(ast, context); diff --git a/src/templateAccessibilityElementsContentRule.ts b/src/templateAccessibilityElementsContentRule.ts index 4435977c7..39b26d250 100644 --- a/src/templateAccessibilityElementsContentRule.ts +++ b/src/templateAccessibilityElementsContentRule.ts @@ -1,11 +1,11 @@ import { ElementAst } from '@angular/compiler'; +import { sprintf } from 'sprintf-js'; import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib'; import { SourceFile } from 'typescript'; -import { sprintf } from 'sprintf-js'; -import { NgWalker } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; -class TemplateAccessibilityElementsContentVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitElement(ast: ElementAst, context: any) { this.validateElement(ast); super.visitElement(ast, context); @@ -50,10 +50,9 @@ export class Rule extends Rules.AbstractRule { static readonly ELEMENTS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'a', 'button']; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateAccessibilityElementsContentVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } diff --git a/src/templateAccessibilityLabelForRule.ts b/src/templateAccessibilityLabelForRule.ts index 46a64c26d..db6c6d779 100644 --- a/src/templateAccessibilityLabelForRule.ts +++ b/src/templateAccessibilityLabelForRule.ts @@ -1,8 +1,7 @@ -import { BoundDirectivePropertyAst, ElementAst } from '@angular/compiler'; -import { sprintf } from 'sprintf-js'; +import { ElementAst } from '@angular/compiler'; import { IRuleMetadata, RuleFailure, Rules, Utils } from 'tslint/lib'; import { SourceFile } from 'typescript/lib/typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; import { mayContainChildComponent } from './util/mayContainChildComponent'; @@ -55,15 +54,14 @@ export class Rule extends Rules.AbstractRule { static readonly FORM_ELEMENTS = ['input', 'select', 'textarea']; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateAccessibilityLabelForVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } -class TemplateAccessibilityLabelForVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitElement(element: ElementAst, context: any) { this.validateElement(element); super.visitElement(element, context); diff --git a/src/templateAccessibilityTabindexNoPositiveRule.ts b/src/templateAccessibilityTabindexNoPositiveRule.ts index b90f8204a..2782aa9b7 100644 --- a/src/templateAccessibilityTabindexNoPositiveRule.ts +++ b/src/templateAccessibilityTabindexNoPositiveRule.ts @@ -1,7 +1,7 @@ import { ElementAst } from '@angular/compiler'; import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib'; import { SourceFile } from 'typescript/lib/typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; import { getAttributeValue } from './util/getAttributeValue'; @@ -19,15 +19,14 @@ export class Rule extends Rules.AbstractRule { static readonly FAILURE_MESSAGE = 'tabindex attribute cannot be positive'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateAccessibilityTabindexNoPositiveVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } -class TemplateAccessibilityTabindexNoPositiveVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitElement(ast: ElementAst, context: any): any { this.validateElement(ast); super.visitElement(ast, context); diff --git a/src/templateAccessibilityTableScopeRule.ts b/src/templateAccessibilityTableScopeRule.ts index 0d2344722..20667f81f 100644 --- a/src/templateAccessibilityTableScopeRule.ts +++ b/src/templateAccessibilityTableScopeRule.ts @@ -1,10 +1,10 @@ import { ElementAst } from '@angular/compiler'; import { IRuleMetadata, RuleFailure, Rules, Utils } from 'tslint/lib'; import { SourceFile } from 'typescript'; -import { NgWalker } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; -class TemplateAccessibilityTableScopeVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitElement(ast: ElementAst, context: any) { this.validateElement(ast); super.visitElement(ast, context); @@ -46,10 +46,9 @@ export class Rule extends Rules.AbstractRule { static readonly FAILURE_MESSAGE = 'Scope attribute can only be on element'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateAccessibilityTableScopeVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } diff --git a/src/templateAccessibilityValidAriaRule.ts b/src/templateAccessibilityValidAriaRule.ts index d10190cc9..003cdb38c 100644 --- a/src/templateAccessibilityValidAriaRule.ts +++ b/src/templateAccessibilityValidAriaRule.ts @@ -1,9 +1,9 @@ import { AttrAst, BoundElementPropertyAst } from '@angular/compiler'; +import { aria } from 'aria-query'; import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib'; import { SourceFile } from 'typescript/lib/typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; -import { aria } from 'aria-query'; import { getSuggestion } from './util/getSuggestion'; const ariaAttributes: string[] = [...(Array.from(aria.keys()))]; @@ -20,11 +20,10 @@ export class Rule extends Rules.AbstractRule { }; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateAccessibilityValidAriaVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } @@ -39,7 +38,7 @@ export const getFailureMessage = (name: string): string => { return message; }; -class TemplateAccessibilityValidAriaVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitAttr(ast: AttrAst, context: any) { this.validateAttribute(ast); super.visitAttr(ast, context); diff --git a/src/templateBananaInBoxRule.ts b/src/templateBananaInBoxRule.ts index 629890cbe..788f94aea 100644 --- a/src/templateBananaInBoxRule.ts +++ b/src/templateBananaInBoxRule.ts @@ -2,7 +2,7 @@ import { BoundEventAst } from '@angular/compiler'; import { IRuleMetadata, Replacement, RuleFailure } from 'tslint'; import { AbstractRule } from 'tslint/lib/rules'; import { SourceFile } from 'typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; const INVALID_BOX = /^\[(?!\()(.*)(? { return totalComplexity; }; -class TemplateConditionalComplexityVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitDirectiveProperty(prop: BoundDirectivePropertyAst, context: BasicTemplateAstVisitor): any { this.validateDirective(prop); super.visitDirectiveProperty(prop, context); diff --git a/src/templateCyclomaticComplexityRule.ts b/src/templateCyclomaticComplexityRule.ts index a6f03155a..14527b60d 100644 --- a/src/templateCyclomaticComplexityRule.ts +++ b/src/templateCyclomaticComplexityRule.ts @@ -2,7 +2,7 @@ import { BoundDirectivePropertyAst } from '@angular/compiler'; import { sprintf } from 'sprintf-js'; import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib'; import { SourceFile } from 'typescript/lib/typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; export class Rule extends Rules.AbstractRule { @@ -29,11 +29,10 @@ export class Rule extends Rules.AbstractRule { static readonly DEFAULT_MAX_COMPLEXITY = 5; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateConditionalComplexityVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } isEnabled(): boolean { @@ -52,7 +51,7 @@ export const getFailureMessage = (maxComplexity = Rule.DEFAULT_MAX_COMPLEXITY): return sprintf(Rule.FAILURE_STRING, maxComplexity); }; -class TemplateConditionalComplexityVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { totalComplexity = 0; visitDirectiveProperty(prop: BoundDirectivePropertyAst, context: any): any { diff --git a/src/templateI18nRule.ts b/src/templateI18nRule.ts index 1c54f0b16..88623fdf8 100644 --- a/src/templateI18nRule.ts +++ b/src/templateI18nRule.ts @@ -3,7 +3,7 @@ import { IRuleMetadata, RuleFailure } from 'tslint'; import { AbstractRule } from 'tslint/lib/rules'; import { arrayify, dedent } from 'tslint/lib/utils'; import { SourceFile } from 'typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; import { isNotNullOrUndefined } from './util/is-not-null-or-undefined'; @@ -61,11 +61,10 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING_TEXT = 'Each element containing text node should have an i18n attribute'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateI18NVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } isEnabled(): boolean { @@ -87,7 +86,7 @@ export class Rule extends AbstractRule { } } -class TemplateI18NAttrVisitor extends BasicTemplateAstVisitor implements ConfigurableVisitor { +class TemplateVisitorAttrCtrl extends BasicTemplateAstVisitor implements ConfigurableVisitor { getCheckOption(): CheckOption { return OPTION_CHECK_ID; } @@ -108,7 +107,7 @@ class TemplateI18NAttrVisitor extends BasicTemplateAstVisitor implements Configu } } -class TemplateI18NTextVisitor extends BasicTemplateAstVisitor implements ConfigurableVisitor { +class TemplateVisitorTextCtrl extends BasicTemplateAstVisitor implements ConfigurableVisitor { private hasI18n = false; private readonly nestedElements: string[] = []; private readonly visited = new Set(); @@ -167,10 +166,10 @@ class TemplateI18NTextVisitor extends BasicTemplateAstVisitor implements Configu } } -class TemplateI18NVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { private readonly visitors: ReadonlyArray = [ - new TemplateI18NAttrVisitor(this.getSourceFile(), this.getOptions(), this.context, this.templateStart), - new TemplateI18NTextVisitor(this.getSourceFile(), this.getOptions(), this.context, this.templateStart) + new TemplateVisitorAttrCtrl(this.getSourceFile(), this.getOptions(), this.context, this.templateStart), + new TemplateVisitorTextCtrl(this.getSourceFile(), this.getOptions(), this.context, this.templateStart) ]; visit(node: TemplateAst, context: BasicTemplateAstVisitor): any { diff --git a/src/templateMouseEventsHaveKeyEventsRule.ts b/src/templateMouseEventsHaveKeyEventsRule.ts index 0579488a8..fad54d3b2 100644 --- a/src/templateMouseEventsHaveKeyEventsRule.ts +++ b/src/templateMouseEventsHaveKeyEventsRule.ts @@ -1,7 +1,7 @@ import { ElementAst } from '@angular/compiler'; import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib'; import { SourceFile } from 'typescript/lib/typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; export class Rule extends Rules.AbstractRule { @@ -19,15 +19,14 @@ export class Rule extends Rules.AbstractRule { static readonly FAILURE_STRING_MOUSE_OUT = 'mouseout must be accompanied by blur event for accessibility'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateMouseEventsHaveKeyEventsVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } -class TemplateMouseEventsHaveKeyEventsVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitElement(el: ElementAst, context: any) { this.validateElement(el); super.visitElement(el, context); diff --git a/src/templateNoAnyRule.ts b/src/templateNoAnyRule.ts index 1a0448a7e..eefae5d38 100644 --- a/src/templateNoAnyRule.ts +++ b/src/templateNoAnyRule.ts @@ -3,7 +3,7 @@ import { IRuleMetadata, RuleFailure } from 'tslint'; import { AbstractRule } from 'tslint/lib/rules'; import { dedent } from 'tslint/lib/utils'; import { SourceFile } from 'typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { RecursiveAngularExpressionVisitor } from './angular/templates/recursiveAngularExpressionVisitor'; const ANY_TYPE_CAST_FUNCTION_NAME = '$any'; @@ -25,15 +25,14 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = `Avoid using '${ANY_TYPE_CAST_FUNCTION_NAME}' in templates`; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - expressionVisitorCtrl: ExpressionVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { expressionVisitorCtrl: ExpressionVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } -class ExpressionVisitor extends RecursiveAngularExpressionVisitor { +class ExpressionVisitorCtrl extends RecursiveAngularExpressionVisitor { visitMethodCall(ast: MethodCall, context: any): any { this.validateMethodCall(ast); super.visitMethodCall(ast, context); diff --git a/src/templateNoAutofocusRule.ts b/src/templateNoAutofocusRule.ts index 1304647f0..5fd1f4d99 100644 --- a/src/templateNoAutofocusRule.ts +++ b/src/templateNoAutofocusRule.ts @@ -1,7 +1,7 @@ import { AttrAst, BoundElementPropertyAst } from '@angular/compiler'; import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib'; import { SourceFile } from 'typescript/lib/typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; export class Rule extends Rules.AbstractRule { @@ -18,15 +18,14 @@ export class Rule extends Rules.AbstractRule { static readonly FAILURE_STRING = 'autofocus attribute should not be used, as it reduces usability and accessibility for users.'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateConditionalComplexityVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } -class TemplateConditionalComplexityVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitAttr(ast: AttrAst, context: any) { this.validateAttribute(ast); super.visitAttr(ast, context); diff --git a/src/templateNoCallExpressionRule.ts b/src/templateNoCallExpressionRule.ts index 99ee795f3..dc2fdc4a0 100644 --- a/src/templateNoCallExpressionRule.ts +++ b/src/templateNoCallExpressionRule.ts @@ -2,7 +2,7 @@ import { MethodCall } from '@angular/compiler'; import { IRuleMetadata, RuleFailure } from 'tslint'; import { AbstractRule } from 'tslint/lib/rules'; import { SourceFile } from 'typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; import { RecursiveAngularExpressionVisitor } from './angular/templates/recursiveAngularExpressionVisitor'; @@ -22,20 +22,21 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = 'Avoid calling expressions in templates'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - expressionVisitorCtrl: ExpressionVisitor, - templateVisitorCtrl: TemplateVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { + expressionVisitorCtrl: ExpressionVisitorCtrl, + templateVisitorCtrl: TemplateVisitorCtrl + }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } -class TemplateVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitEvent(): any {} } -class ExpressionVisitor extends RecursiveAngularExpressionVisitor { +class ExpressionVisitorCtrl extends RecursiveAngularExpressionVisitor { visitMethodCall(ast: MethodCall, context: any): any { this.validateMethodCall(ast); super.visitMethodCall(ast, context); diff --git a/src/templateNoDistractingElementsRule.ts b/src/templateNoDistractingElementsRule.ts index a6a52e7fa..01cab1b03 100644 --- a/src/templateNoDistractingElementsRule.ts +++ b/src/templateNoDistractingElementsRule.ts @@ -2,7 +2,7 @@ import { ElementAst } from '@angular/compiler'; import { sprintf } from 'sprintf-js'; import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib'; import { SourceFile } from 'typescript/lib/typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; export class Rule extends Rules.AbstractRule { @@ -19,11 +19,10 @@ export class Rule extends Rules.AbstractRule { static readonly FAILURE_STRING = 'Avoid using <%s/> elements as they create visual accessibility issues.'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - templateVisitorCtrl: TemplateNoDistractingElementsVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } @@ -31,7 +30,7 @@ export function getFailureMessage(element: string) { return sprintf(Rule.FAILURE_STRING, element); } -class TemplateNoDistractingElementsVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { visitElement(prop: ElementAst, context: any): any { this.validateElement(prop); super.visitElement(prop, context); diff --git a/src/templateNoNegatedAsyncRule.ts b/src/templateNoNegatedAsyncRule.ts index 20e5c73d2..91931952b 100644 --- a/src/templateNoNegatedAsyncRule.ts +++ b/src/templateNoNegatedAsyncRule.ts @@ -3,7 +3,7 @@ import { IRuleMetadata, RuleFailure } from 'tslint/lib'; import { AbstractRule } from 'tslint/lib/rules'; import { dedent } from 'tslint/lib/utils'; import { SourceFile } from 'typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { RecursiveAngularExpressionVisitor } from './angular/templates/recursiveAngularExpressionVisitor'; const unstrictEqualityOperator = '=='; @@ -29,15 +29,14 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING_UNSTRICT_EQUALITY = 'Async pipes must use strict equality `===` when comparing with `false`'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker( - new NgWalker(sourceFile, this.getOptions(), { - expressionVisitorCtrl: TemplateToNgTemplateVisitor - }) - ); + const walkerConfig: NgWalkerConfig = { expressionVisitorCtrl: ExpressionVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } -class TemplateToNgTemplateVisitor extends RecursiveAngularExpressionVisitor { +class ExpressionVisitorCtrl extends RecursiveAngularExpressionVisitor { visitBinary(ast: Binary, context: any): any { this.validateBinary(ast); super.visitBinary(ast, context); diff --git a/src/templateUseTrackByFunctionRule.ts b/src/templateUseTrackByFunctionRule.ts index aa0b827cb..b76608824 100644 --- a/src/templateUseTrackByFunctionRule.ts +++ b/src/templateUseTrackByFunctionRule.ts @@ -2,11 +2,11 @@ import { BoundDirectivePropertyAst } from '@angular/compiler'; import { IRuleMetadata, RuleFailure } from 'tslint/lib'; import { AbstractRule } from 'tslint/lib/rules'; import { SourceFile } from 'typescript/lib/typescript'; -import { NgWalker } from './angular/ngWalker'; +import { NgWalker, NgWalkerConfig } from './angular/ngWalker'; import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; // current offset into the template -export let curentOffset = 0; +export let currentOffset = 0; const PATTERN = /\s*ngFor.*\s*trackBy\s*:|\[ngForTrackBy\]\s*=\s*['"].*['"]/; @@ -24,13 +24,16 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = 'Missing trackBy function in ngFor directive'; apply(sourceFile: SourceFile): RuleFailure[] { - curentOffset = 0; + currentOffset = 0; - return this.applyWithWalker(new NgWalker(sourceFile, this.getOptions(), { templateVisitorCtrl: TemplateUseTrackByFunctionVisitor })); + const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl }; + const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig); + + return this.applyWithWalker(walker); } } -class TemplateUseTrackByFunctionTemplateVisitor extends BasicTemplateAstVisitor { +class TemplateUseTrackByFunctionVisitor extends BasicTemplateAstVisitor { visitDirectiveProperty(prop: BoundDirectivePropertyAst, context: BasicTemplateAstVisitor): any { this.validateDirective(prop, context); super.visitDirectiveProperty(prop, context); @@ -48,8 +51,8 @@ class TemplateUseTrackByFunctionTemplateVisitor extends BasicTemplateAstVisitor } } = prop; - if (PATTERN.test((context.codeWithMap.source || '').substr(curentOffset))) { - curentOffset = endOffset; + if (PATTERN.test((context.codeWithMap.source || '').substr(currentOffset))) { + currentOffset = endOffset; return; } @@ -58,9 +61,9 @@ class TemplateUseTrackByFunctionTemplateVisitor extends BasicTemplateAstVisitor } } -class TemplateUseTrackByFunctionVisitor extends BasicTemplateAstVisitor { +class TemplateVisitorCtrl extends BasicTemplateAstVisitor { private readonly visitors: ReadonlySet = new Set([ - new TemplateUseTrackByFunctionTemplateVisitor(this.getSourceFile(), this.getOptions(), this.context, this.templateStart) + new TemplateUseTrackByFunctionVisitor(this.getSourceFile(), this.getOptions(), this.context, this.templateStart) ]); visitDirectiveProperty(prop: BoundDirectivePropertyAst, context: BasicTemplateAstVisitor): any { diff --git a/src/useComponentSelectorRule.ts b/src/useComponentSelectorRule.ts index b726e684b..622290072 100644 --- a/src/useComponentSelectorRule.ts +++ b/src/useComponentSelectorRule.ts @@ -26,11 +26,13 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = 'The selector of the component "%s" is mandatory'; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new UseComponentSelectorWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -class UseComponentSelectorWalker extends NgWalker { +class Walker extends NgWalker { protected visitNgComponent(metadata: ComponentMetadata): void { this.validateComponent(metadata); super.visitNgComponent(metadata); diff --git a/src/useComponentViewEncapsulationRule.ts b/src/useComponentViewEncapsulationRule.ts index b95e11fd8..85e3ef40e 100644 --- a/src/useComponentViewEncapsulationRule.ts +++ b/src/useComponentViewEncapsulationRule.ts @@ -20,11 +20,13 @@ export class Rule extends AbstractRule { static readonly FAILURE_STRING = `Using ViewEncapsulation.${NONE} makes your styles global, which may have an unintended effect`; apply(sourceFile: SourceFile): RuleFailure[] { - return this.applyWithWalker(new ViewEncapsulationWalker(sourceFile, this.getOptions())); + const walker = new Walker(sourceFile, this.getOptions()); + + return this.applyWithWalker(walker); } } -class ViewEncapsulationWalker extends NgWalker { +class Walker extends NgWalker { protected visitNgComponent(metadata: ComponentMetadata): void { this.validateComponent(metadata); super.visitNgComponent(metadata);