/** * @angular-modernizer/plugin-angular - Static Extract Transform Rule * * Extracts public static methods from stateful classes to module-level * exported functions placed immediately above the class declaration. * * @example * // Before * export class OrderService { * private orders: Order[] = []; * static validate(id: string): boolean { return id.length > 0; } * addOrder(order: Order): void { this.orders.push(order); } * } * * // After * export function validate(id: string): boolean { return id.length > 0; } * * export class OrderService { * private orders: Order[] = []; * addOrder(order: Order): void { this.orders.push(order); } * } */ import type { TransformRule, TransformContext, TransformResult, } from '@angular-modernizer/plugin-system'; import type { PublicApi } from '@angular-modernizer/api'; import { StaticExtractTransformOrchestrator } from '../orchestrators/static-extract-transform.orchestrator.js'; export class StaticExtractTransformRule implements TransformRule { public readonly id = 'angular:extract-static-from-stateful'; public readonly name = 'Extract Static Methods from Stateful Class'; public readonly description = 'Extracts public static methods from classes with instance state to module-level functions'; public readonly category = 'refactoring'; public readonly tags = [ 'angular', 'refactoring', 'static', 'tree-shaking', 'architecture', ]; private readonly orchestrator = new StaticExtractTransformOrchestrator(); async transform( context: TransformContext, ): Promise { const { sourceFile, filePath } = context; if (filePath.endsWith('.d.ts')) { return { ruleId: this.id, modified: false, message: 'Skipped declaration file', filePath, }; } const initialText = sourceFile.getFullText(); const stats = this.orchestrator.run(context); const modified = sourceFile.getFullText() !== initialText; return { ruleId: this.id, modified, message: modified ? `Extracted ${stats.extractedCount} static method(s) to module level; ${stats.inFileRefsUpdated} in-file + ${stats.crossFileCallersUpdated} cross-file reference(s) updated` : 'No eligible static-in-stateful-class patterns found', filePath, changeCount: stats.extractedCount, }; } }