ryo_executor/executor/registry/converters/
field.rs1use crate::engine::ASTRegApply;
6use crate::executor::registry::converters::ResolveTargetSymbol;
7use crate::executor::registry::{ConvertError, MutationConverter};
8use crate::executor::spec::{MutationSpec, Visibility};
9use ryo_analysis::AnalysisContext;
10use ryo_mutations::{AddFieldMutation, RemoveFieldMutation};
11
12#[derive(Debug, Clone, Default)]
14pub struct FieldConverter;
15
16impl FieldConverter {
17 pub fn new() -> Self {
18 Self
19 }
20}
21
22impl ResolveTargetSymbol for FieldConverter {}
24
25impl MutationConverter for FieldConverter {
26 fn spec_kinds(&self) -> &'static [&'static str] {
27 &["AddField", "RemoveField"]
28 }
29
30 fn convert_v2(
31 &self,
32 spec: &MutationSpec,
33 ctx: &AnalysisContext,
34 ) -> Result<Vec<Box<dyn ASTRegApply>>, ConvertError> {
35 match spec {
36 MutationSpec::AddField {
37 target,
38 field_name,
39 field_type,
40 visibility,
41 } => {
42 let symbol_id = self.resolve_target_symbol(target, ctx)?;
44
45 let mut mutation = AddFieldMutation::new(symbol_id, field_name, field_type);
46 if *visibility == Visibility::Pub {
47 mutation = mutation.public();
48 }
49 Ok(vec![Box::new(mutation)])
50 }
51 MutationSpec::RemoveField { target, field_name } => {
52 let symbol_id = self.resolve_target_symbol(target, ctx)?;
54
55 let mutation = RemoveFieldMutation::new(symbol_id, field_name);
56 Ok(vec![Box::new(mutation)])
57 }
58 _ => Err(ConvertError::TypeMismatch {
59 expected: "AddField or RemoveField",
60 actual: spec.kind_name().to_string(),
61 }),
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_field_converter_spec_kinds() {
72 let converter = FieldConverter::new();
73 assert_eq!(converter.spec_kinds(), &["AddField", "RemoveField"]);
74 }
75
76 #[test]
77 fn test_field_converter_can_handle_add() {
78 use crate::executor::spec::MutationTargetSymbol;
79 use ryo_symbol::{SymbolKind, SymbolPath, SymbolRegistry};
80
81 let converter = FieldConverter::new();
82 let mut registry = SymbolRegistry::new();
83 let path = SymbolPath::parse("test_crate::Config").unwrap();
84 let symbol_id = registry.register(path, SymbolKind::Struct).unwrap();
85
86 let spec = MutationSpec::AddField {
87 target: MutationTargetSymbol::by_id(symbol_id),
88 field_name: "timeout".into(),
89 field_type: "u64".into(),
90 visibility: Visibility::Pub,
91 };
92 assert!(converter.can_handle(&spec));
93 }
94
95 #[test]
96 fn test_field_converter_can_handle_remove() {
97 use crate::executor::spec::MutationTargetSymbol;
98 use ryo_symbol::{SymbolKind, SymbolPath, SymbolRegistry};
99
100 let converter = FieldConverter::new();
101 let mut registry = SymbolRegistry::new();
102 let path = SymbolPath::parse("test_crate::Config").unwrap();
103 let symbol_id = registry.register(path, SymbolKind::Struct).unwrap();
104
105 let spec = MutationSpec::RemoveField {
106 target: MutationTargetSymbol::by_id(symbol_id),
107 field_name: "timeout".into(),
108 };
109 assert!(converter.can_handle(&spec));
110 }
111}