use ryo_mutations::basic::{AddVariantMutation, RemoveVariantMutation};
use ryo_mutations::MutationResult;
use ryo_source::pure::{PureItem, PureVariant};
use crate::engine::{ASTMutationContext, ASTRegApply, ModificationType, MutationEvent};
impl ASTRegApply for AddVariantMutation {
fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
let target_id = self.enum_id;
let item = match ctx.ast_registry.get(target_id) {
Some(item) => item.clone(),
None => {
return MutationResult {
mutation_type: "AddVariant".to_string(),
changes: 0,
description: format!("AST not found for {:?}", target_id),
};
}
};
let new_item = match item {
PureItem::Enum(mut e) => {
if e.variants.iter().any(|v| v.name == self.variant_name) {
return MutationResult {
mutation_type: "AddVariant".to_string(),
changes: 0,
description: format!(
"Variant '{}' already exists in {:?}",
self.variant_name, target_id
),
};
}
e.variants.push(PureVariant {
attrs: Vec::new(),
name: self.variant_name.clone(),
fields: self.fields.clone(),
discriminant: None,
});
PureItem::Enum(e)
}
_ => {
return MutationResult {
mutation_type: "AddVariant".to_string(),
changes: 0,
description: format!("{:?} is not an enum", target_id),
};
}
};
ctx.set_ast(target_id, new_item);
ctx.emit(MutationEvent::SymbolModified {
id: target_id,
modification: ModificationType::VariantAdded(self.variant_name.clone()),
});
MutationResult {
mutation_type: "AddVariant".to_string(),
changes: 1,
description: format!("Added variant '{}' to {:?}", self.variant_name, target_id),
}
}
}
impl ASTRegApply for RemoveVariantMutation {
fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
let target_id = self.enum_id;
let item = match ctx.ast_registry.get(target_id) {
Some(item) => item.clone(),
None => {
return MutationResult {
mutation_type: "RemoveVariant".to_string(),
changes: 0,
description: format!("AST not found for {:?}", target_id),
};
}
};
let (new_item, removed) = match item {
PureItem::Enum(mut e) => {
let original_len = e.variants.len();
e.variants.retain(|v| v.name != self.variant_name);
let removed = e.variants.len() < original_len;
(PureItem::Enum(e), removed)
}
_ => {
return MutationResult {
mutation_type: "RemoveVariant".to_string(),
changes: 0,
description: format!("{:?} is not an enum", target_id),
};
}
};
if removed {
ctx.set_ast(target_id, new_item);
ctx.emit(MutationEvent::SymbolModified {
id: target_id,
modification: ModificationType::VariantRemoved(self.variant_name.clone()),
});
}
MutationResult {
mutation_type: "RemoveVariant".to_string(),
changes: if removed { 1 } else { 0 },
description: if removed {
format!(
"Removed variant '{}' from {:?}",
self.variant_name, target_id
)
} else {
format!(
"Variant '{}' not found in {:?}",
self.variant_name, target_id
)
},
}
}
}