use ryo_mutations::basic::{AddEnumMutation, RemoveEnumMutation};
use ryo_mutations::MutationResult;
use ryo_source::pure::{
PureAttrMeta, PureAttribute, PureEnum, PureGenerics, PureItem, PureVariant, PureVis,
};
use ryo_symbol::SymbolKind;
use crate::engine::{ASTMutationContext, ASTRegApply};
impl ASTRegApply for AddEnumMutation {
fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
let module_id = self.parent;
if ctx.symbol_registry.kind(module_id) != Some(SymbolKind::Mod) {
return MutationResult {
mutation_type: "AddEnum".to_string(),
changes: 0,
description: format!("Target symbol {:?} is not a module", module_id),
};
}
let parent_path = match ctx.symbol_registry.path(module_id) {
Some(p) => p,
None => {
return MutationResult {
mutation_type: "AddEnum".to_string(),
changes: 0,
description: format!("Module {:?} not found in registry", module_id),
};
}
};
let exists = ctx
.symbol_registry
.iter()
.filter(|(id, _)| ctx.symbol_registry.kind(*id) == Some(SymbolKind::Enum))
.any(|(_, path)| {
path.parent().as_ref() == Some(parent_path) && path.name() == self.name
});
if exists {
return MutationResult {
mutation_type: "AddEnum".to_string(),
changes: 0,
description: format!("Enum '{}' already exists in module", self.name),
};
}
let attrs = if !self.derives.is_empty() {
vec![PureAttribute {
path: "derive".to_string(),
meta: PureAttrMeta::List(self.derives.join(", ")),
is_inner: false,
}]
} else {
vec![]
};
let variants: Vec<PureVariant> = self
.variants
.iter()
.map(|(name, fields)| PureVariant {
attrs: vec![],
name: name.clone(),
fields: fields.clone(),
discriminant: None,
})
.collect();
let enum_item = PureEnum {
attrs,
vis: if self.is_pub {
PureVis::Public
} else {
PureVis::Private
},
name: self.name.clone(),
generics: PureGenerics::default(),
variants,
};
let enum_path = match parent_path.child(&self.name) {
Ok(p) => p,
Err(_) => {
return MutationResult {
mutation_type: "AddEnum".to_string(),
changes: 0,
description: format!("Failed to create path for enum '{}'", self.name),
};
}
};
match ctx.symbol_registry.register(enum_path, SymbolKind::Enum) {
Ok(enum_id) => {
ctx.ast_registry.set(enum_id, PureItem::Enum(enum_item));
MutationResult {
mutation_type: "AddEnum".to_string(),
changes: 1,
description: format!("Added enum '{}' to module {:?}", self.name, module_id),
}
}
Err(e) => MutationResult {
mutation_type: "AddEnum".to_string(),
changes: 0,
description: format!("Failed to register enum '{}': {:?}", self.name, e),
},
}
}
}
impl ASTRegApply for RemoveEnumMutation {
fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
let enum_id = self.symbol_id;
if ctx.symbol_registry.kind(enum_id) != Some(SymbolKind::Enum) {
return MutationResult {
mutation_type: "RemoveEnum".to_string(),
changes: 0,
description: format!("Symbol {:?} is not an enum", enum_id),
};
}
ctx.ast_registry.remove(enum_id);
MutationResult {
mutation_type: "RemoveEnum".to_string(),
changes: 1,
description: format!("Removed enum {:?}", enum_id),
}
}
}