ryo_executor/executor/registry/converters/
enum_.rs1use crate::engine::ASTRegApply;
4use crate::executor::registry::converters::ResolveTargetSymbol;
5use crate::executor::registry::{ConvertError, MutationConverter};
6use crate::executor::spec::{MutationSpec, VariantKind};
7use ryo_analysis::AnalysisContext;
8use ryo_mutations::{AddVariantMutation, RemoveVariantMutation};
9
10#[derive(Debug, Clone, Default)]
12pub struct EnumConverter;
13
14impl EnumConverter {
15 pub fn new() -> Self {
16 Self
17 }
18}
19
20impl ResolveTargetSymbol for EnumConverter {}
22
23impl MutationConverter for EnumConverter {
24 fn spec_kinds(&self) -> &'static [&'static str] {
25 &["AddVariant", "RemoveVariant"]
26 }
27
28 fn convert_v2(
29 &self,
30 spec: &MutationSpec,
31 ctx: &AnalysisContext,
32 ) -> Result<Vec<Box<dyn ASTRegApply>>, ConvertError> {
33 use ryo_source::pure::{PureField, PureFields, PureTupleField, PureType, PureVis};
34
35 match spec {
36 MutationSpec::AddVariant {
37 target: target_symbol,
38 variant_name,
39 variant_kind,
40 } => {
41 let symbol_id = self.resolve_target_symbol(target_symbol, ctx)?;
43
44 let fields = match variant_kind {
45 VariantKind::Unit => PureFields::Unit,
46 VariantKind::Tuple { types } => PureFields::Tuple(
47 types
48 .iter()
49 .map(|t| PureTupleField {
50 attrs: Vec::new(),
51 vis: PureVis::Private,
52 ty: PureType::Path(t.clone()),
53 })
54 .collect(),
55 ),
56 VariantKind::Struct { fields } => {
57 let pure_fields: Vec<PureField> = fields
58 .iter()
59 .map(|(n, t)| PureField {
60 attrs: Vec::new(),
61 vis: PureVis::Private,
62 name: n.clone(),
63 ty: PureType::Path(t.clone()),
64 })
65 .collect();
66 PureFields::Named(pure_fields)
67 }
68 };
69 let mutation = AddVariantMutation::new(symbol_id, variant_name, fields);
70 Ok(vec![Box::new(mutation)])
71 }
72 MutationSpec::RemoveVariant {
73 target: target_symbol,
74 variant_name,
75 } => {
76 let symbol_id = self.resolve_target_symbol(target_symbol, ctx)?;
78 let mutation = RemoveVariantMutation::new(symbol_id, variant_name);
79 Ok(vec![Box::new(mutation)])
80 }
81 _ => Err(ConvertError::TypeMismatch {
82 expected: "AddVariant or RemoveVariant",
83 actual: spec.kind_name().to_string(),
84 }),
85 }
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use crate::executor::spec::MutationTargetSymbol;
93 use ryo_symbol::{SymbolKind, SymbolPath, SymbolRegistry};
94
95 fn create_test_symbol_id() -> ryo_symbol::SymbolId {
96 let mut registry = SymbolRegistry::new();
97 let path = SymbolPath::parse("test_crate::Status").unwrap();
98 registry.register(path, SymbolKind::Enum).unwrap()
99 }
100
101 #[test]
102 fn test_enum_converter_spec_kinds() {
103 let converter = EnumConverter::new();
104 assert_eq!(converter.spec_kinds(), &["AddVariant", "RemoveVariant"]);
105 }
106
107 #[test]
108 fn test_enum_converter_can_handle_add_variant() {
109 let converter = EnumConverter::new();
110 let id = create_test_symbol_id();
111
112 let spec = MutationSpec::AddVariant {
113 target: MutationTargetSymbol::ById(id),
114 variant_name: "Pending".into(),
115 variant_kind: VariantKind::Unit,
116 };
117 assert!(converter.can_handle(&spec));
118 }
119
120 #[test]
121 fn test_enum_converter_can_handle_remove_variant() {
122 let converter = EnumConverter::new();
123 let id = create_test_symbol_id();
124
125 let spec = MutationSpec::RemoveVariant {
126 target: MutationTargetSymbol::ById(id),
127 variant_name: "Pending".into(),
128 };
129 assert!(converter.can_handle(&spec));
130 }
131}