use ryo_mutations::basic::{AddImplMutation, RemoveImplMutation};
use ryo_mutations::MutationResult;
use ryo_source::pure::{PureGenerics, PureImpl, PureItem};
use ryo_symbol::SymbolKind;
use crate::engine::{ASTMutationContext, ASTRegApply};
impl ASTRegApply for AddImplMutation {
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: "AddImpl".to_string(),
changes: 0,
description: format!("Target symbol {} is not a module", module_id),
};
}
let impl_item = PureImpl {
attrs: vec![],
generics: PureGenerics::default(),
is_unsafe: false,
trait_: self.trait_name.clone(),
self_ty: self.target.clone(),
items: vec![],
};
let impl_name = if let Some(trait_name) = &self.trait_name {
format!("<impl {} for {}>", trait_name, self.target)
} else {
format!("<impl {}>", self.target)
};
let parent_path = match ctx.symbol_registry.path(module_id) {
Some(p) => p,
None => {
return MutationResult {
mutation_type: "AddImpl".to_string(),
changes: 0,
description: format!("Module {} not found in registry", module_id),
};
}
};
let impl_path = match parent_path.child(&impl_name) {
Ok(p) => p,
Err(_) => {
return MutationResult {
mutation_type: "AddImpl".to_string(),
changes: 0,
description: format!("Failed to create path for impl '{}'", impl_name),
};
}
};
match ctx.symbol_registry.register(impl_path, SymbolKind::Impl) {
Ok(impl_id) => {
ctx.ast_registry
.set(impl_id, PureItem::Impl(impl_item.clone()));
let mut items = ctx
.ast_registry
.get_module_items(module_id)
.cloned()
.unwrap_or_default();
items.push(PureItem::Impl(impl_item));
ctx.ast_registry.set_module_items(module_id, items);
MutationResult {
mutation_type: "AddImpl".to_string(),
changes: 1,
description: format!("Added impl {} to module {}", impl_name, module_id),
}
}
Err(e) => MutationResult {
mutation_type: "AddImpl".to_string(),
changes: 0,
description: format!("Failed to register impl '{}': {:?}", impl_name, e),
},
}
}
}
impl ASTRegApply for RemoveImplMutation {
fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
let impl_id = self.symbol_id;
if ctx.symbol_registry.kind(impl_id) != Some(SymbolKind::Impl) {
return MutationResult {
mutation_type: "RemoveImpl".to_string(),
changes: 0,
description: format!("Symbol {} is not an impl block", impl_id),
};
}
ctx.ast_registry.remove(impl_id);
MutationResult {
mutation_type: "RemoveImpl".to_string(),
changes: 1,
description: format!("Removed impl block {}", impl_id),
}
}
}