Skip to main content

ryo_executor/executor/registry/converters/
struct_literal_field.rs

1//! StructLiteralFieldConverter: Converts MutationSpec::AddStructLiteralField and RemoveStructLiteralField
2
3use crate::engine::ASTRegApply;
4use crate::executor::registry::converters::ResolveTargetSymbol;
5use crate::executor::registry::{ConvertError, MutationConverter};
6use crate::executor::spec::MutationSpec;
7use ryo_analysis::AnalysisContext;
8use ryo_mutations::{AddStructLiteralFieldMutation, RemoveStructLiteralFieldMutation};
9
10/// Converter for AddStructLiteralField and RemoveStructLiteralField mutations
11#[derive(Debug, Clone, Default)]
12pub struct StructLiteralFieldConverter;
13
14impl StructLiteralFieldConverter {
15    pub fn new() -> Self {
16        Self
17    }
18}
19
20// StructLiteralFieldConverter uses the default implementation of ResolveTargetSymbol
21impl ResolveTargetSymbol for StructLiteralFieldConverter {}
22
23impl MutationConverter for StructLiteralFieldConverter {
24    fn spec_kinds(&self) -> &'static [&'static str] {
25        &["AddStructLiteralField", "RemoveStructLiteralField"]
26    }
27
28    fn convert_v2(
29        &self,
30        spec: &MutationSpec,
31        ctx: &AnalysisContext,
32    ) -> Result<Vec<Box<dyn ASTRegApply>>, ConvertError> {
33        match spec {
34            MutationSpec::AddStructLiteralField {
35                target: target_symbol,
36                field_name,
37                value,
38            } => {
39                // Resolve target_symbol to SymbolId
40                let symbol_id = self.resolve_target_symbol(target_symbol, ctx)?;
41                let mutation = AddStructLiteralFieldMutation::new(
42                    symbol_id,
43                    field_name.clone(),
44                    value.clone(),
45                );
46                Ok(vec![Box::new(mutation)])
47            }
48            MutationSpec::RemoveStructLiteralField {
49                target: target_symbol,
50                field_name,
51            } => {
52                // Resolve target_symbol to SymbolId
53                let symbol_id = self.resolve_target_symbol(target_symbol, ctx)?;
54                let mutation = RemoveStructLiteralFieldMutation::new(symbol_id, field_name.clone());
55                Ok(vec![Box::new(mutation)])
56            }
57            _ => Err(ConvertError::TypeMismatch {
58                expected: "AddStructLiteralField or RemoveStructLiteralField",
59                actual: spec.kind_name().to_string(),
60            }),
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn test_struct_literal_field_converter_spec_kinds() {
71        let converter = StructLiteralFieldConverter::new();
72        assert_eq!(
73            converter.spec_kinds(),
74            &["AddStructLiteralField", "RemoveStructLiteralField"]
75        );
76    }
77
78    #[test]
79    fn test_struct_literal_field_converter_can_handle() {
80        let converter = StructLiteralFieldConverter::new();
81
82        let spec = MutationSpec::AddStructLiteralField {
83            target: crate::executor::spec::MutationTargetSymbol::ByKindAndName(
84                crate::executor::ItemKind::Struct,
85                "Config".to_string(),
86            ),
87            field_name: "timeout".to_string(),
88            value: "None".to_string(),
89        };
90        assert!(converter.can_handle(&spec));
91    }
92}