use crate::engine::ASTRegApply;
use crate::executor::registry::converters::ResolveTargetSymbol;
use crate::executor::registry::{ConvertError, MutationConverter};
use crate::executor::spec::MutationSpec;
use ryo_analysis::AnalysisContext;
use ryo_mutations::{AddMatchArmMutation, RemoveMatchArmMutation, ReplaceMatchArmMutation};
#[derive(Debug, Clone, Default)]
pub struct MatchArmConverter;
impl MatchArmConverter {
pub fn new() -> Self {
Self
}
}
impl ResolveTargetSymbol for MatchArmConverter {}
impl MutationConverter for MatchArmConverter {
fn spec_kinds(&self) -> &'static [&'static str] {
&["AddMatchArm", "RemoveMatchArm", "ReplaceMatchArm"]
}
fn convert_v2(
&self,
spec: &MutationSpec,
ctx: &AnalysisContext,
) -> Result<Vec<Box<dyn ASTRegApply>>, ConvertError> {
match spec {
MutationSpec::AddMatchArm {
target,
enum_name,
pattern,
body,
} => {
let fn_id = self.resolve_target_symbol(target, ctx)?;
let mutation = AddMatchArmMutation::new(
fn_id,
enum_name.clone(),
pattern.clone(),
body.clone(),
);
Ok(vec![Box::new(mutation)])
}
MutationSpec::RemoveMatchArm {
target,
enum_name,
pattern,
} => {
let fn_id = self.resolve_target_symbol(target, ctx)?;
let mutation =
RemoveMatchArmMutation::new(fn_id, enum_name.clone(), pattern.clone());
Ok(vec![Box::new(mutation)])
}
MutationSpec::ReplaceMatchArm {
target,
enum_name,
old_pattern,
new_pattern,
new_body,
} => {
let fn_id = self.resolve_target_symbol(target, ctx)?;
let mutation = ReplaceMatchArmMutation::new(
fn_id,
enum_name.clone(),
old_pattern.clone(),
new_pattern.clone(),
new_body.clone(),
);
Ok(vec![Box::new(mutation)])
}
_ => Err(ConvertError::TypeMismatch {
expected: "AddMatchArm, RemoveMatchArm, or ReplaceMatchArm",
actual: spec.kind_name().to_string(),
}),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::executor::spec::MutationTargetSymbol;
use ryo_analysis::SymbolPath;
#[test]
fn test_match_arm_converter_spec_kinds() {
let converter = MatchArmConverter::new();
assert_eq!(
converter.spec_kinds(),
&["AddMatchArm", "RemoveMatchArm", "ReplaceMatchArm"]
);
}
#[test]
fn test_match_arm_converter_can_handle() {
let converter = MatchArmConverter::new();
let spec = MutationSpec::AddMatchArm {
target: MutationTargetSymbol::ByPath(Box::new(
SymbolPath::parse("test_crate::handlers::process_status").unwrap(),
)),
enum_name: "Status".to_string(),
pattern: "Status::Cancelled".to_string(),
body: "todo!()".to_string(),
};
assert!(converter.can_handle(&spec));
}
}