ryo-executor 0.1.0

[experimental] Mutation execution engine for RYO - parallel execution, conflict detection, workspace management
Documentation
//! RenameConverter: Converts MutationSpec::Rename to RenameMutation

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::RenameMutation;

/// Converter for Rename mutations
#[derive(Debug, Clone, Default)]
pub struct RenameConverter;

impl RenameConverter {
    pub fn new() -> Self {
        Self
    }
}

// RenameConverter uses the default implementation of ResolveTargetSymbol
impl ResolveTargetSymbol for RenameConverter {}

impl MutationConverter for RenameConverter {
    fn spec_kinds(&self) -> &'static [&'static str] {
        &["Rename"]
    }

    fn convert_v2(
        &self,
        spec: &MutationSpec,
        ctx: &AnalysisContext,
    ) -> Result<Vec<Box<dyn ASTRegApply>>, ConvertError> {
        match spec {
            MutationSpec::Rename {
                target: target_symbol,
                to,
                ..
            } => {
                // Resolve target_symbol to SymbolId
                let symbol_id = self.resolve_target_symbol(target_symbol, ctx)?;
                let mutation = RenameMutation::new(symbol_id, to);
                Ok(vec![Box::new(mutation)])
            }
            _ => Err(ConvertError::TypeMismatch {
                expected: "Rename",
                actual: spec.kind_name().to_string(),
            }),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::executor::spec::Scope;
    use ryo_symbol::{SymbolKind, SymbolPath, SymbolRegistry};

    #[test]
    fn test_rename_converter_spec_kinds() {
        let converter = RenameConverter::new();
        assert_eq!(converter.spec_kinds(), &["Rename"]);
    }

    #[test]
    fn test_rename_converter_can_handle() {
        let converter = RenameConverter::new();

        let mut registry = SymbolRegistry::new();
        let path = SymbolPath::parse("test_crate::old").unwrap();
        let symbol_id = registry.register(path, SymbolKind::Function).unwrap();

        let rename_spec = MutationSpec::Rename {
            target: crate::executor::spec::MutationTargetSymbol::ById(symbol_id),
            to: "new".into(),
            scope: Scope::Project,
        };
        assert!(converter.can_handle(&rename_spec));

        let add_field_spec = MutationSpec::AddField {
            target: crate::executor::spec::MutationTargetSymbol::ById(symbol_id),
            field_name: "bar".into(),
            field_type: "i32".into(),
            visibility: crate::executor::spec::Visibility::Private,
        };
        assert!(!converter.can_handle(&add_field_spec));
    }
}