/** * @angular-modernizer/plugin-angular - Static Class to Functions Transform Rule * * Transforms static-only classes into module-level function/const exports. * * @example * // Before * export class StringHelper { * static isEmpty(s: string): boolean { return s.length === 0; } * } * * // After * export function isEmpty(s: string): boolean { return s.length === 0; } */ import type { TransformRule, TransformContext, TransformResult, } from '@angular-modernizer/plugin-system'; import type { PublicApi } from '@angular-modernizer/api'; import { StaticClassTransformOrchestrator } from '../orchestrators/static-class-transform.orchestrator.js'; export class StaticClassTransformRule implements TransformRule { public readonly id = 'angular:static-class-to-functions'; public readonly name = 'Static Class to Functions Transform'; public readonly description = 'Transforms static-only classes into module-level functions and const exports'; public readonly category = 'refactoring'; public readonly tags = [ 'angular', 'refactoring', 'functional', 'tree-shaking', 'static', ]; private readonly orchestrator = new StaticClassTransformOrchestrator(); 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 ? `Transformed ${stats.classesTransformed} static class(es) → ${stats.functionsCreated} function(s), ${stats.constantsCreated} constant(s); ${stats.inFileRefsUpdated} in-file + ${stats.crossFileCallersUpdated} cross-file reference(s) updated` : 'No static-only classes found', filePath, changeCount: stats.classesTransformed, }; } }