Skip to main content

ryo_executor/engine/impls/
field.rs

1//! ASTRegApply implementation for field mutations
2
3use ryo_mutations::basic::{AddFieldMutation, RemoveFieldMutation};
4use ryo_mutations::MutationResult;
5use ryo_source::pure::{PureField, PureFields, PureItem, PureType, PureVis};
6
7use crate::engine::{ASTMutationContext, ASTRegApply, ModificationType};
8
9impl ASTRegApply for AddFieldMutation {
10    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
11        let target_id = self.struct_id;
12
13        // Get the AST
14        let ast = match ctx.get_ast_mut(target_id) {
15            Some(ast) => ast,
16            None => {
17                return MutationResult {
18                    mutation_type: "AddField".to_string(),
19                    changes: 0,
20                    description: format!("AST not found for {:?}", target_id),
21                };
22            }
23        };
24
25        // Modify the struct
26        if let PureItem::Struct(s) = ast {
27            // Check if field already exists
28            if let PureFields::Named(fields) = &s.fields {
29                if fields.iter().any(|f| f.name == self.field_name) {
30                    return MutationResult {
31                        mutation_type: "AddField".to_string(),
32                        changes: 0,
33                        description: format!("Field '{}' already exists", self.field_name),
34                    };
35                }
36            }
37
38            // Create new field
39            let new_field = PureField {
40                attrs: Vec::new(),
41                vis: if self.is_pub {
42                    PureVis::Public
43                } else {
44                    PureVis::Private
45                },
46                name: self.field_name.clone(),
47                ty: PureType::Path(self.field_type.clone()),
48            };
49
50            // Add the field
51            match &mut s.fields {
52                PureFields::Named(fields) => {
53                    fields.push(new_field);
54                }
55                PureFields::Unit => {
56                    s.fields = PureFields::Named(vec![new_field]);
57                }
58                PureFields::Tuple(_) => {
59                    return MutationResult {
60                        mutation_type: "AddField".to_string(),
61                        changes: 0,
62                        description: "Cannot add named field to tuple struct".to_string(),
63                    };
64                }
65            }
66
67            ctx.emit_modified(
68                target_id,
69                ModificationType::FieldAdded(self.field_name.clone()),
70            );
71
72            MutationResult {
73                mutation_type: "AddField".to_string(),
74                changes: 1,
75                description: format!("Added field '{}'", self.field_name),
76            }
77        } else {
78            MutationResult {
79                mutation_type: "AddField".to_string(),
80                changes: 0,
81                description: format!("{:?} is not a struct", target_id),
82            }
83        }
84    }
85}
86
87impl ASTRegApply for RemoveFieldMutation {
88    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
89        let target_id = self.struct_id;
90
91        // Get the AST
92        let ast = match ctx.get_ast_mut(target_id) {
93            Some(ast) => ast,
94            None => {
95                return MutationResult {
96                    mutation_type: "RemoveField".to_string(),
97                    changes: 0,
98                    description: format!("AST not found for {:?}", target_id),
99                };
100            }
101        };
102
103        // Modify the struct
104        if let PureItem::Struct(s) = ast {
105            if let PureFields::Named(fields) = &mut s.fields {
106                let original_len = fields.len();
107                fields.retain(|f| f.name != self.field_name);
108
109                if fields.len() < original_len {
110                    ctx.emit_modified(
111                        target_id,
112                        ModificationType::FieldRemoved(self.field_name.clone()),
113                    );
114
115                    return MutationResult {
116                        mutation_type: "RemoveField".to_string(),
117                        changes: 1,
118                        description: format!("Removed field '{}'", self.field_name),
119                    };
120                }
121            }
122
123            MutationResult {
124                mutation_type: "RemoveField".to_string(),
125                changes: 0,
126                description: format!("Field '{}' not found", self.field_name),
127            }
128        } else {
129            MutationResult {
130                mutation_type: "RemoveField".to_string(),
131                changes: 0,
132                description: format!("{:?} is not a struct", target_id),
133            }
134        }
135    }
136}