ryo-executor 0.1.0

[experimental] Mutation execution engine for RYO - parallel execution, conflict detection, workspace management
Documentation
//! StructLiteralFieldConverter: Converts MutationSpec::AddStructLiteralField and RemoveStructLiteralField

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::{AddStructLiteralFieldMutation, RemoveStructLiteralFieldMutation};

/// Converter for AddStructLiteralField and RemoveStructLiteralField mutations
#[derive(Debug, Clone, Default)]
pub struct StructLiteralFieldConverter;

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

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

impl MutationConverter for StructLiteralFieldConverter {
    fn spec_kinds(&self) -> &'static [&'static str] {
        &["AddStructLiteralField", "RemoveStructLiteralField"]
    }

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

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_struct_literal_field_converter_spec_kinds() {
        let converter = StructLiteralFieldConverter::new();
        assert_eq!(
            converter.spec_kinds(),
            &["AddStructLiteralField", "RemoveStructLiteralField"]
        );
    }

    #[test]
    fn test_struct_literal_field_converter_can_handle() {
        let converter = StructLiteralFieldConverter::new();

        let spec = MutationSpec::AddStructLiteralField {
            target: crate::executor::spec::MutationTargetSymbol::ByKindAndName(
                crate::executor::ItemKind::Struct,
                "Config".to_string(),
            ),
            field_name: "timeout".to_string(),
            value: "None".to_string(),
        };
        assert!(converter.can_handle(&spec));
    }
}