/** * @angular-modernizer/plugin-angular - Main Plugin * * The main entry point for the Angular-specific analysis plugin. * Provides analysis rules for Angular-specific best practices and performance optimizations. */ import type { Plugin, AnalysisRule, TransformRule, ValidationRule, IKernel } from '@angular-modernizer/plugin-system'; import { ConfigLoader } from '@angular-modernizer/core'; import type { RulesConfig } from '@angular-modernizer/core'; import { MissingOnPushRule } from './analysis-rules/angular-missing-onpush.rule.js'; import { PerformanceViolationRule } from './analysis-rules/angular-performance-violation.rule.js'; import { LifecycleHookRule } from './analysis-rules/angular-lifecycle-hook.rule.js'; import { TemplateComplexityRule } from './analysis-rules/angular-template-complexity.rule.js'; import { ImmutableInputViolationRule } from './analysis-rules/angular-immutable-input-violation.rule.js'; import { MissingTrackByRule } from './analysis-rules/angular-missing-trackby.rule.js'; import { ServiceWithoutInjectableRule } from './analysis-rules/angular-service-without-injectable.rule.js'; import { ComponentWithoutSelectorRule } from './analysis-rules/angular-component-without-selector.rule.js'; import { DirectiveWithoutSelectorRule } from './analysis-rules/angular-directive-without-selector.rule.js'; import { PipeWithoutNameRule } from './analysis-rules/angular-pipe-without-name.rule.js'; import { AsyncPipeMisuseRule } from './analysis-rules/angular-async-pipe-misuse.rule.js'; import { UnnecessaryChangeDetectionRule } from './analysis-rules/angular-unnecessary-change-detection.rule.js'; import { MissingReturnTypeRule } from './analysis-rules/angular-missing-return-type.rule.js'; import { TooManyInputsRule } from './analysis-rules/angular-too-many-inputs.rule.js'; import { RxJSOptimizationRule } from './analysis-rules/rxjs-optimization.rule.js'; import { BundleSizeOptimizationRule } from './analysis-rules/bundle-size-optimization.rule.js'; import { ConstructorToInjectRule } from './transform-rules/constructor-to-inject.rule.js'; import { InterfaceExtractionRule } from './transform-rules/interface-extraction.rule.js'; import { DependencyInjectionMigrationRule } from './transform-rules/dependency-injection-migration.rule.js'; import { FormModernizationRule } from './transform-rules/form-modernization.rule.js'; import { FacadePatternRule } from './transform-rules/facade-pattern.rule.js'; import { ConstructorInjectionTransformRule } from './transform-rules/constructor-injection-transform.rule.js'; import { ComponentInputsInterfaceExtractionRule } from './transform-rules/component-inputs-interface-extraction.rule.js'; import { ServiceInjectionCleanupRule } from './transform-rules/service-injection-cleanup.rule.js'; import { ContainerPresentationalRule } from './transform-rules/container-presentational.rule.js'; import { CoreSharedModulesRule } from './transform-rules/core-shared-modules.rule.js'; import { DataHandlingStrategyRule } from './analysis-rules/data-handling-strategy.rule.js'; import { InheritanceToCompositionRule } from './transform-rules/inheritance-to-composition.rule.js'; import { ServiceBagTransformRule } from './transform-rules/service-bag-transform.rule.js'; import { TypeSafetyAnalysisRule } from './analysis-rules/type-safety.analysis.rule.js'; import { TypeSafetyTransformRule } from './transform-rules/type-safety.transform.rule.js'; import { AnyToInterfaceAnalysisRule } from './analysis-rules/any-to-interface.analysis.rule.js'; import { AnyToInterfaceTransformRule } from './transform-rules/any-to-interface.transform.rule.js'; import { UntypedDynamicComponentRule } from './analysis-rules/untyped-dynamic-component.analysis.rule.js'; import { InterfaceDuplicationAnalysisRule } from './analysis-rules/interface-duplication-analysis.rule.js'; import { DtoObjectLiteralTransformRule } from './transform-rules/dto-object-literal.transform.rule.js'; import { ComponentWrapperInstantiationRule } from './analysis-rules/component-wrapper-instantiation.rule.js'; import { DtoDirectInstantiationRule } from './analysis-rules/dto-direct-instantiation.rule.js'; import { MagicStringSelectorRule } from './analysis-rules/magic-string-selector.rule.js'; import { StaticClassAnalysisRule } from './analysis-rules/static-class-analysis.rule.js'; import { StaticClassTransformRule } from './transform-rules/static-class-transform.rule.js'; import { StaticExtractTransformRule } from './transform-rules/static-extract-transform.rule.js'; import { InterfaceDuplicationTransformRule } from './transform-rules/interface-duplication-transform.rule.js'; import { PromiseObservableAnalysisRule } from './analysis-rules/promise-observable.analysis.rule.js'; import { PresentationalComponentViolationRule } from './analysis-rules/presentational-component-violation.rule.js'; import { PromiseServiceTransformRule } from './transform-rules/promise-service-transform.rule.js'; import { PromiseComponentTransformRule } from './transform-rules/promise-component-transform.rule.js'; import { PromiseCleanupTransformRule } from './transform-rules/promise-cleanup-transform.rule.js'; import { SequentialAwaitTransformRule } from './transform-rules/sequential-await-transform.rule.js'; import { MissingOutputTransformRule } from './transform-rules/missing-output-transform.rule.js'; import { SubscriptionTransformRule } from './transform-rules/subscription-transform.rule.js'; import { LibraryExtractionTransformRule } from './transform-rules/library-extraction.transform.rule.js'; import { ServiceMutableStateRule } from './analysis-rules/service-mutable-state.rule.js'; /** * Angular-Specific Analysis Plugin * * @remarks * This plugin provides analysis rules for Angular-specific best practices, * performance optimizations, and framework-specific violations. * * ## Current Rules * * - {@link MissingOnPushRule}: Detects Angular components missing OnPush change detection * - {@link PerformanceViolationRule}: Detects memory leaks and performance issues * - {@link LifecycleHookRule}: Detects improper lifecycle hook usage and missing cleanup * - {@link TemplateComplexityRule}: Detects complex operations in templates causing side effects * - {@link ImmutableInputViolationRule}: Detects mutation of `` properties breaking OnPush * - {@link MissingTrackByRule}: Detects ngFor directives without trackBy functions * - {@link ServiceWithoutInjectableRule}: Detects services without `` decorator * - {@link ComponentWithoutSelectorRule}: Detects components without selector property * - {@link DirectiveWithoutSelectorRule}: Detects directives without selector property * - {@link PipeWithoutNameRule}: Detects pipes without name property * - {@link AsyncPipeMisuseRule}: Detects incorrect usage of async pipe * - {@link UnnecessaryChangeDetectionRule}: Detects components using Default change detection unnecessarily * - {@link MissingReturnTypeRule}: Detects methods missing return type annotations * - {@link TooManyInputsRule}: Detects components with too many `` properties * - {@link RxJSOptimizationRule}: Detects inefficient RxJS operator usage and optimization opportunities * - {@link BundleSizeOptimizationRule}: Detects bundle size optimization opportunities for faster initial load times * - {@link DataHandlingStrategyRule}: Detects inefficient data processing strategies and suggests server-side alternatives * - {@link TypeSafetyAnalysisRule}: Detects explicit any types, untyped parameters, missing return types, and untyped properties * - {@link AnyToInterfaceAnalysisRule}: Detects `any`-typed parameters and class properties that can be replaced with generated interfaces * - {@link UntypedDynamicComponentRule}: Detects implicit contracts via untyped `ComponentRef.instance` member access * - {@link ComponentWrapperInstantiationRule}: Direct `new X()` instantiation of wrapper/adapter classes that should be injected via DI * - {@link DtoDirectInstantiationRule}: Direct `new X()` instantiation of DTO/Response/Result classes * - {@link MagicStringSelectorRule}: Magic string selector arguments passed to dynamic component loading methods * * ## Future Rules (Planned) * * @see {@link MissingOnPushRule} for the OnPush change detection rule */ export class AngularPlugin implements Plugin { /** * Unique plugin identifier. */ public readonly name = '@angular-modernizer/plugin-angular'; private ruleConfigs: RulesConfig | undefined; /** * Plugin version (from package.json). */ public readonly version = '0.1.0'; /** * Plugin description. */ public readonly description = 'Provides Angular-specific analysis for best practices and performance'; /** * Plugin author. */ public readonly author = 'Angular Modernization Platform'; /** * Initialize the plugin. * * @param kernel - The Kernel instance for accessing infrastructure */ async initialize(kernel: IKernel): Promise { const projectRoot = kernel.getProjectRoot(); const loader = new ConfigLoader(); try { const config = loader.load(projectRoot); this.ruleConfigs = config.rules; } catch { // Config load failure is non-fatal — rule defaults remain in effect } } /** * Get all analysis rules provided by this plugin. * * @returns Array of analysis rules for Angular-specific violations */ getAnalysisRules(): AnalysisRule[] { const rules = [ new MissingOnPushRule(), new PerformanceViolationRule(), new LifecycleHookRule(), new TemplateComplexityRule(), new ImmutableInputViolationRule(), new MissingTrackByRule(), new ServiceWithoutInjectableRule(), new ComponentWithoutSelectorRule(), new DirectiveWithoutSelectorRule(), new PipeWithoutNameRule(), new AsyncPipeMisuseRule(), new UnnecessaryChangeDetectionRule(), new MissingReturnTypeRule(), new TooManyInputsRule(), new RxJSOptimizationRule(), new BundleSizeOptimizationRule(), new DataHandlingStrategyRule(), new TypeSafetyAnalysisRule(), new AnyToInterfaceAnalysisRule(), new UntypedDynamicComponentRule(), new InterfaceDuplicationAnalysisRule(), new ComponentWrapperInstantiationRule( this.ruleConfigs?.['angular:component-wrapper-instantiation'], ), new DtoDirectInstantiationRule( this.ruleConfigs?.['angular:dto-direct-instantiation'], ), new MagicStringSelectorRule( this.ruleConfigs?.['angular:magic-string-selector'] ? { targetMethodPatterns: this.ruleConfigs['angular:magic-string-selector'] .targetMethodPatterns, } : undefined, ), new StaticClassAnalysisRule(), new PromiseObservableAnalysisRule(), new PresentationalComponentViolationRule( this.ruleConfigs?.['angular:presentational-component-violation'], ), new ServiceMutableStateRule(), ]; console.info( `Angular Plugin: Returning ${rules.length} analysis rules:`, rules.map((r) => r.id), ); return rules; } /** * Get all transformation rules provided by this plugin. * * @returns Array of transformation rules for Angular-specific conversions */ getTransformRules(): TransformRule[] { return [ new ConstructorToInjectRule(), new InterfaceExtractionRule(), new DependencyInjectionMigrationRule(), new FormModernizationRule(), new FacadePatternRule(), new ConstructorInjectionTransformRule(), new ComponentInputsInterfaceExtractionRule(), new ServiceInjectionCleanupRule(), new ContainerPresentationalRule(), new CoreSharedModulesRule(), new InheritanceToCompositionRule(), new ServiceBagTransformRule(), new TypeSafetyTransformRule(), new AnyToInterfaceTransformRule(), new DtoObjectLiteralTransformRule(), new StaticClassTransformRule(), new StaticExtractTransformRule(), new InterfaceDuplicationTransformRule(), new PromiseServiceTransformRule(), new PromiseComponentTransformRule(), new PromiseCleanupTransformRule(), new SequentialAwaitTransformRule(), new MissingOutputTransformRule(), new SubscriptionTransformRule(), new LibraryExtractionTransformRule(), ]; } /** * Get all validation rules provided by this plugin. * * @returns Empty array (no validation rules yet) */ getValidationRules(): ValidationRule[] { // Future: Add validation rules to verify Angular fixes return []; } }