use ryo_mutations::basic::{AddFieldMutation, RemoveFieldMutation};
use ryo_mutations::MutationResult;
use ryo_source::pure::{PureField, PureFields, PureItem, PureType, PureVis};
use crate::engine::{ASTMutationContext, ASTRegApply, ModificationType};
impl ASTRegApply for AddFieldMutation {
fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
let target_id = self.struct_id;
let ast = match ctx.get_ast_mut(target_id) {
Some(ast) => ast,
None => {
return MutationResult {
mutation_type: "AddField".to_string(),
changes: 0,
description: format!("AST not found for {:?}", target_id),
};
}
};
if let PureItem::Struct(s) = ast {
if let PureFields::Named(fields) = &s.fields {
if fields.iter().any(|f| f.name == self.field_name) {
return MutationResult {
mutation_type: "AddField".to_string(),
changes: 0,
description: format!("Field '{}' already exists", self.field_name),
};
}
}
let new_field = PureField {
attrs: Vec::new(),
vis: if self.is_pub {
PureVis::Public
} else {
PureVis::Private
},
name: self.field_name.clone(),
ty: PureType::Path(self.field_type.clone()),
};
match &mut s.fields {
PureFields::Named(fields) => {
fields.push(new_field);
}
PureFields::Unit => {
s.fields = PureFields::Named(vec![new_field]);
}
PureFields::Tuple(_) => {
return MutationResult {
mutation_type: "AddField".to_string(),
changes: 0,
description: "Cannot add named field to tuple struct".to_string(),
};
}
}
ctx.emit_modified(
target_id,
ModificationType::FieldAdded(self.field_name.clone()),
);
MutationResult {
mutation_type: "AddField".to_string(),
changes: 1,
description: format!("Added field '{}'", self.field_name),
}
} else {
MutationResult {
mutation_type: "AddField".to_string(),
changes: 0,
description: format!("{:?} is not a struct", target_id),
}
}
}
}
impl ASTRegApply for RemoveFieldMutation {
fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
let target_id = self.struct_id;
let ast = match ctx.get_ast_mut(target_id) {
Some(ast) => ast,
None => {
return MutationResult {
mutation_type: "RemoveField".to_string(),
changes: 0,
description: format!("AST not found for {:?}", target_id),
};
}
};
if let PureItem::Struct(s) = ast {
if let PureFields::Named(fields) = &mut s.fields {
let original_len = fields.len();
fields.retain(|f| f.name != self.field_name);
if fields.len() < original_len {
ctx.emit_modified(
target_id,
ModificationType::FieldRemoved(self.field_name.clone()),
);
return MutationResult {
mutation_type: "RemoveField".to_string(),
changes: 1,
description: format!("Removed field '{}'", self.field_name),
};
}
}
MutationResult {
mutation_type: "RemoveField".to_string(),
changes: 0,
description: format!("Field '{}' not found", self.field_name),
}
} else {
MutationResult {
mutation_type: "RemoveField".to_string(),
changes: 0,
description: format!("{:?} is not a struct", target_id),
}
}
}
}