ryo_executor/engine/ast_reg_apply.rs
1//! ASTRegApply trait - Apply mutations to ASTRegistry
2//!
3//! This trait extends Mutation with registry-based execution capability.
4//! Defined in ryo-executor to avoid circular dependency between
5//! ryo-mutations and ryo-analysis.
6//!
7//! # Design
8//!
9//! ```text
10//! ryo-mutations ryo-analysis ryo-executor
11//! ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
12//! │ Mutation │ │ ASTRegistry │ │ ASTRegApply │
13//! │ (base trait) │ │ SymbolReg │ │ (ext trait) │
14//! └──────────────┘ └──────────────┘ └──────────────┘
15//! ↑ ↑ │
16//! └─────────────────────┴──────────────────────┘
17//! ASTRegApply: Mutation
18//! ```
19//!
20//! # Quality Policy for V2 Implementations
21//!
22//! When implementing `ASTRegApply` for mutations:
23//!
24//! ## DO:
25//! - Design the implementation to work naturally with ASTRegistry/SymbolRegistry
26//! - Add comprehensive snapshot tests that verify exact output
27//! - Consider if the ASTMutationContext API needs extension for new capabilities
28//!
29//! ## DON'T:
30//! - Create hacky workarounds just to make tests pass
31//! - Use temporary allocations or intermediate representations (defeats V2 purpose)
32//! - Copy V1 patterns that don't fit the registry-based model
33//!
34//! ## When V2 Cannot Handle a Mutation Cleanly:
35//!
36//! If a mutation cannot be implemented cleanly with the current V2 API:
37//!
38//! 1. **Do NOT** hack the implementation or tests to force it to work
39//! 2. **Do** evaluate if ASTMutationContext needs new methods
40//! 3. **Do** consider if ASTRegistry/SymbolRegistry need enhancements
41//! 4. **Do** document the design gap and propose a proper solution
42//!
43//! The goal is a clean, maintainable architecture - not 100% feature coverage
44//! through workarounds.
45//!
46//! # Usage
47//!
48//! ```ignore
49//! use ryo_executor::engine::ASTRegApply;
50//!
51//! impl ASTRegApply for AddFieldMutation {
52//! fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
53//! // Get target struct from registry
54//! let id = ctx.lookup(&self.target_path)?;
55//! let ast = ctx.get_ast_mut(id)?;
56//!
57//! // Modify AST
58//! if let PureItem::Struct(s) = ast {
59//! s.fields.push(new_field);
60//! }
61//!
62//! ctx.emit_modified(id, ModificationType::FieldAdded(name));
63//! MutationResult { ... }
64//! }
65//! }
66//! ```
67
68use ryo_mutations::{Mutation, MutationResult};
69
70use super::ast_mutation_engine::ASTMutationContext;
71
72/// Trait for mutations that can be applied to ASTRegistry
73///
74/// Extends the base `Mutation` trait with registry-based execution.
75/// This is the primary execution path for the new AST-centric architecture.
76///
77/// # Implementing
78///
79/// Mutations that want to support registry-based execution should:
80/// 1. Implement this trait
81/// 2. Use `ctx.lookup()` to find target symbols
82/// 3. Use `ctx.get_ast_mut()` to modify AST
83/// 4. Use `ctx.emit_*()` to record changes
84///
85/// # Fallback
86///
87/// If a mutation doesn't implement this trait, ASTMutationEngine
88/// will return no changes. The legacy `apply(&mut PureFile)` path
89/// remains available for backward compatibility.
90pub trait ASTRegApply: Mutation {
91 /// Apply this mutation to the ASTRegistry
92 ///
93 /// # Arguments
94 ///
95 /// * `ctx` - Mutable context providing access to registries and event emission
96 ///
97 /// # Returns
98 ///
99 /// MutationResult indicating the number of changes made
100 fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult;
101}