A comprehensive static code analysis tool for Angular TypeScript projects that implements TSLint rules enforcing Angular's official style guide.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Core classes and utilities for Angular AST analysis and custom rule development. These components provide the foundation for analyzing Angular components, directives, and templates.
import { RuleWalker, IOptions } from 'tslint';
import { SourceFile, ClassDeclaration, Decorator, PropertyDeclaration, MethodDeclaration, BooleanLiteral } from 'typescript';
import { RawSourceMap } from 'source-map';Base walker class for traversing Angular AST structures and analyzing Angular-specific code patterns.
/**
* Base walker class for traversing Angular AST structures
* Provides Angular-specific node visiting capabilities
*/
export class NgWalker extends RuleWalker {
constructor(
sourceFile: SourceFile,
options: IOptions,
config?: NgWalkerConfig,
metadataReader?: MetadataReader
);
/** Visit Angular component declarations */
protected visitNgComponent(metadata: ComponentMetadata): void;
/** Visit Angular directive declarations */
protected visitNgDirective(metadata: DirectiveMetadata): void;
/** Visit Angular pipe declarations */
protected visitNgPipe(metadata: PipeMetadata): void;
/** Visit Angular module declarations */
protected visitNgModule(metadata: ModuleMetadata): void;
/** Visit Angular injectable declarations */
protected visitNgInjectable(metadata: InjectableMetadata): void;
/** Visit class decorators */
protected visitClassDecorator(decorator: ts.Decorator): void;
/** Visit method decorators */
protected visitMethodDecorator(decorator: ts.Decorator): void;
/** Visit property decorators */
protected visitPropertyDecorator(decorator: ts.Decorator): void;
/** Visit host listener decorators */
protected visitNgHostListener(method: ts.MethodDeclaration, decorator: ts.Decorator, args: string[]): void;
/** Visit Input property decorators */
protected visitNgInput(property: ts.PropertyDeclaration, input: ts.Decorator, args: string[]): void;
/** Visit Output property decorators */
protected visitNgOutput(property: ts.PropertyDeclaration, output: ts.Decorator, args: string[]): void;
/** Visit HostBinding property decorators */
protected visitNgHostBinding(property: ts.PropertyDeclaration, decorator: ts.Decorator, args: string[]): void;
/** Visit ContentChild property decorators */
protected visitNgContentChild(property: ts.PropertyDeclaration, input: ts.Decorator, args: string[]): void;
/** Visit ContentChildren property decorators */
protected visitNgContentChildren(property: ts.PropertyDeclaration, input: ts.Decorator, args: string[]): void;
/** Visit ViewChild property decorators */
protected visitNgViewChild(property: ts.PropertyDeclaration, input: ts.Decorator, args: string[]): void;
/** Visit ViewChildren property decorators */
protected visitNgViewChildren(property: ts.PropertyDeclaration, input: ts.Decorator, args: string[]): void;
}
interface NgWalkerConfig {
cssVisitorCtrl?: CssAstVisitorCtrl;
expressionVisitorCtrl?: RecursiveAngularExpressionVisitorCtr;
templateVisitorCtrl?: TemplateAstVisitorCtr;
}Usage Examples:
Creating a custom rule with NgWalker:
import { NgWalker } from 'codelyzer';
export class CustomAngularRule extends Lint.Rules.AbstractRule {
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new CustomWalker(sourceFile, this.getOptions()));
}
}
class CustomWalker extends NgWalker {
protected visitNgComponent(metadata: ComponentMetadata): void {
// Custom component analysis logic
if (metadata.selector.startsWith('custom-')) {
// Validate custom component patterns
}
super.visitNgComponent(metadata);
}
}Reads and parses Angular decorator metadata from TypeScript AST nodes.
/**
* Reads Angular decorator metadata from TypeScript class declarations
* Extracts component, directive, pipe, and module information
*/
export class MetadataReader {
constructor(fileResolver?: FileResolver);
/** Read metadata from a class declaration */
read(declaration: ts.ClassDeclaration): DirectiveMetadata | ComponentMetadata | PipeMetadata | InjectableMetadata | ModuleMetadata | undefined;
}Type-safe representations of Angular decorator metadata.
/**
* Represents @Component decorator metadata
*/
export class ComponentMetadata extends DirectiveMetadata {
constructor(
readonly controller: ts.ClassDeclaration,
readonly decorator: ts.Decorator,
readonly selector?: string,
readonly animations?: (AnimationMetadata | undefined)[],
readonly styles?: (StyleMetadata | undefined)[],
readonly template?: TemplateMetadata
);
}
/**
* Represents @Directive decorator metadata
*/
export class DirectiveMetadata {
constructor(
readonly controller: ts.ClassDeclaration,
readonly decorator: ts.Decorator,
readonly selector?: string
);
}
/**
* Represents @Pipe decorator metadata
*/
export class PipeMetadata {
constructor(
readonly controller: ts.ClassDeclaration,
readonly decorator: ts.Decorator,
readonly name?: string,
readonly pure?: ts.BooleanLiteral
);
}
/**
* Represents @NgModule decorator metadata
*/
export class ModuleMetadata {
constructor(
readonly controller: ts.ClassDeclaration,
readonly decorator: ts.Decorator
);
}
/**
* Represents @Injectable decorator metadata
*/
export class InjectableMetadata {
constructor(
readonly controller: ts.ClassDeclaration,
readonly decorator: ts.Decorator,
readonly providedIn?: string | ts.Expression
);
}
/**
* Represents component styles metadata
*/
export interface StyleMetadata extends PropertyMetadata {
style: CodeWithSourceMap;
}
/**
* Represents component template metadata
*/
export interface TemplateMetadata extends PropertyMetadata {
template: CodeWithSourceMap;
}
/**
* Represents component animation metadata
*/
export interface AnimationMetadata extends PropertyMetadata {
animation: CodeWithSourceMap;
}
/**
* Base property metadata interface
*/
export interface PropertyMetadata {
node?: ts.Node;
url?: string;
}
/**
* Code with source map information
*/
export interface CodeWithSourceMap {
code: string;
map?: RawSourceMap;
source?: string;
}AST visitors for analyzing Angular templates and expressions.
Base visitor class for traversing Angular template AST nodes.
/**
* Base visitor for Angular template AST traversal
* Provides methods for visiting template nodes like elements, attributes, and expressions
*/
export class BasicTemplateAstVisitor {
/** Visit template elements */
visitElement(ast: ElementAst, context: any): any;
/** Visit template attributes */
visitAttr(ast: AttrAst, context: any): any;
/** Visit bound properties */
visitBoundText(ast: BoundTextAst, context: any): any;
/** Visit text nodes */
visitText(ast: TextAst, context: any): any;
/** Visit directives */
visitDirective(ast: DirectiveAst, context: any): any;
/** Visit events */
visitEvent(ast: BoundEventAst, context: any): any;
}
type TemplateAstVisitorCtr = new (...args: any[]) => BasicTemplateAstVisitor;Visitor for analyzing Angular expressions within templates.
/**
* Visitor for Angular template expressions
* Analyzes property bindings, event handlers, and template expressions
*/
export class RecursiveAngularExpressionVisitor {
/** Visit property read expressions */
visitPropertyRead(ast: PropertyRead, context: any): any;
/** Visit method call expressions */
visitMethodCall(ast: MethodCall, context: any): any;
/** Visit pipe expressions */
visitPipe(ast: BindingPipe, context: any): any;
/** Visit literal expressions */
visitLiteralPrimitive(ast: LiteralPrimitive, context: any): any;
}
type RecursiveAngularExpressionVisitorCtr = new (...args: any[]) => RecursiveAngularExpressionVisitor;Collects template reference variables and their usage.
/**
* Collects template reference variables (#ref) and their usage
* Useful for analyzing template variable scope and usage patterns
*/
export class ReferenceCollectorVisitor {
/** Get all collected references */
getReferences(): TemplateReference[];
}
interface TemplateReference {
name: string;
element: ElementAst;
directive?: DirectiveAst;
}AST visitors for analyzing component styles.
Base visitor class for traversing CSS AST nodes in component styles.
/**
* Base visitor for CSS AST traversal in Angular component styles
* Analyzes stylesheets, rules, selectors, and properties
*/
export class BasicCssAstVisitor {
/** Visit CSS stylesheet */
visitCssStyleSheet(ast: CssStyleSheetAst, context?: any): any;
/** Visit CSS rules */
visitCssRule(ast: CssRuleAst, context?: any): any;
/** Visit CSS selectors */
visitCssSelector(ast: CssSelectorAst, context?: any): any;
/** Visit CSS properties */
visitCssProperty(ast: CssPropertyAst, context?: any): any;
}
type CssAstVisitorCtrl = new (...args: any[]) => BasicCssAstVisitor;Type definitions for CSS Abstract Syntax Tree nodes.
/**
* CSS AST node types for component style analysis
*/
export interface CssAst {
visit(visitor: CssAstVisitor, context?: any): any;
}
export interface CssStyleSheetAst extends CssAst {
rules: CssRuleAst[];
}
export interface CssRuleAst extends CssAst {
selector: CssSelectorAst;
block: CssBlockAst;
}
export interface CssSelectorAst extends CssAst {
selectorParts: CssSelectorPartAst[];
}
export interface CssPropertyAst extends CssAst {
name: string;
value: CssPropertyValueAst;
}Utilities for resolving Angular template files and external resources.
Interface for resolving file paths in Angular projects.
/**
* Interface for resolving Angular template and style files
*/
export interface FileResolver {
resolve(url: string, base?: string): string;
}
/**
* Filesystem-based file resolver
*/
export class FsFileResolver implements FileResolver {
resolve(url: string, base?: string): string;
}
/**
* Mock file resolver for testing
*/
export class DummyFileResolver implements FileResolver {
resolve(url: string, base?: string): string;
}Configuration options for Angular analysis.
/**
* Configuration interface for Angular analysis
*/
export interface Config {
/** Predefined directive configuration */
predefinedDirectives: DirectiveConfig[];
/** Custom template parsing options */
templateOptions?: TemplateParsingOptions;
}
interface DirectiveConfig {
selector: string;
exportAs?: string;
inputs?: string[];
outputs?: string[];
}Helper functions for Angular framework operations.
/**
* Factory utilities for creating NgWalker instances
*/
export namespace ngWalkerFactoryUtils {
/** Create default metadata reader */
function defaultMetadataReader(): MetadataReader;
/** Create configured NgWalker */
function create(options: NgWalkerOptions): NgWalker;
}
/**
* Template parsing utilities
*/
export function parseTemplate(
template: string,
templateUrl?: string,
config?: Config
): TemplateAst[];
/**
* CSS parsing utilities
*/
export function parseCss(
css: string,
url?: string
): CssStyleSheetAst;import { NgWalker, ComponentMetadata } from 'codelyzer';
class MyCustomWalker extends NgWalker {
protected visitNgComponent(metadata: ComponentMetadata): void {
// Analyze component selector
if (!metadata.selector.startsWith('app-')) {
this.addFailureAtNode(
metadata.controller,
'Component selector must start with "app-"'
);
}
// Analyze component template
if (metadata.template && metadata.template.length > 1000) {
this.addFailureAtNode(
metadata.controller,
'Component template is too large'
);
}
super.visitNgComponent(metadata);
}
}import { BasicTemplateAstVisitor } from 'codelyzer';
class TemplateAnalyzer extends BasicTemplateAstVisitor {
visitElement(ast: ElementAst, context: any): any {
// Check for accessibility issues
if (ast.name === 'img' && !this.hasAttribute(ast, 'alt')) {
// Report missing alt attribute
}
return super.visitElement(ast, context);
}
private hasAttribute(element: ElementAst, name: string): boolean {
return element.attrs.some(attr => attr.name === name);
}
}Install with Tessl CLI
npx tessl i tessl/npm-codelyzer