ryo_executor/executor/registry/converters/
move_.rs1use crate::engine::ASTRegApply;
15use crate::executor::registry::converter::{ConvertError, MutationConverter};
16use crate::executor::registry::converters::ResolveTargetSymbol;
17use crate::executor::spec::MutationSpec;
18use ryo_analysis::AnalysisContext;
19use ryo_mutations::MoveItemMutation;
20
21pub struct MoveConverter;
23
24impl MoveConverter {
25 pub fn new() -> Self {
26 Self
27 }
28}
29
30impl Default for MoveConverter {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl ResolveTargetSymbol for MoveConverter {}
38
39impl MutationConverter for MoveConverter {
40 fn spec_kinds(&self) -> &'static [&'static str] {
41 &["MoveItem"]
42 }
43
44 fn convert_v2(
45 &self,
46 spec: &MutationSpec,
47 ctx: &AnalysisContext,
48 ) -> Result<Vec<Box<dyn ASTRegApply>>, ConvertError> {
49 match spec {
50 MutationSpec::MoveItem {
51 source: source_symbol,
52 target: target_symbol,
53 item_name,
54 item_kind,
55 add_use,
56 } => {
57 let source_id = self.resolve_target_symbol(source_symbol, ctx)?;
59 let target_id = self.resolve_target_symbol(target_symbol, ctx)?;
60
61 let source_path = ctx
62 .registry
63 .resolve(source_id)
64 .ok_or_else(|| {
65 ConvertError::TargetNotFound(format!(
66 "Source module {:?} not found",
67 source_id
68 ))
69 })?
70 .clone();
71
72 let target_path = ctx
73 .registry
74 .resolve(target_id)
75 .ok_or_else(|| {
76 ConvertError::TargetNotFound(format!(
77 "Target module {:?} not found",
78 target_id
79 ))
80 })?
81 .clone();
82
83 let mutation = MoveItemMutation::new(
84 source_path,
85 target_path,
86 item_name.clone(),
87 *item_kind,
88 *add_use,
89 );
90 Ok(vec![Box::new(mutation)])
91 }
92 _ => Err(ConvertError::TypeMismatch {
93 expected: "MoveItem",
94 actual: spec.kind_name().to_string(),
95 }),
96 }
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use crate::executor::spec::MutationSpec;
104 use ryo_source::ItemKind;
105 use ryo_symbol::{SymbolKind, SymbolPath, SymbolRegistry};
106
107 #[test]
108 fn test_move_converter_spec_kinds() {
109 let converter = MoveConverter::new();
110 assert_eq!(converter.spec_kinds(), &["MoveItem"]);
111 }
112
113 #[test]
114 fn test_move_converter_can_handle() {
115 let converter = MoveConverter::new();
116
117 let move_spec = MutationSpec::MoveItem {
118 source: crate::executor::spec::MutationTargetSymbol::ByPath(Box::new(
119 SymbolPath::parse("test_crate").unwrap(),
120 )),
121 target: crate::executor::spec::MutationTargetSymbol::ByPath(Box::new(
122 SymbolPath::parse("test_crate::core").unwrap(),
123 )),
124 item_name: "Task".into(),
125 item_kind: ItemKind::Struct,
126 add_use: true,
127 };
128 assert!(converter.can_handle(&move_spec));
129
130 let mut registry = SymbolRegistry::new();
132 let path = SymbolPath::parse("test_crate::old").unwrap();
133 let symbol_id = registry.register(path, SymbolKind::Function).unwrap();
134
135 let other_spec = MutationSpec::Rename {
136 target: crate::executor::spec::MutationTargetSymbol::ById(symbol_id),
137 to: "new".into(),
138 scope: crate::executor::spec::Scope::Project,
139 };
140 assert!(!converter.can_handle(&other_spec));
141 }
142}