ryo_executor/executor/registry/converters/
duplicate.rs1use 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::AddPureItemsMutation;
9use ryo_source::pure::PureItem;
10use ryo_symbol::SymbolKind;
11
12#[derive(Debug, Clone, Default)]
14pub struct DuplicateConverter;
15
16impl DuplicateConverter {
17 pub fn new() -> Self {
18 Self
19 }
20}
21
22impl ResolveTargetSymbol for DuplicateConverter {}
24
25impl MutationConverter for DuplicateConverter {
26 fn spec_kinds(&self) -> &'static [&'static str] {
27 &[
28 "DuplicateFunction",
29 "DuplicateStruct",
30 "DuplicateEnum",
31 "DuplicateModTree",
32 ]
33 }
34
35 fn convert_v2(
36 &self,
37 spec: &MutationSpec,
38 ctx: &AnalysisContext,
39 ) -> Result<Vec<Box<dyn ASTRegApply>>, ConvertError> {
40 match spec {
41 MutationSpec::DuplicateFunction {
42 target: target_symbol,
43 to,
44 } => {
45 let symbol_id = self.resolve_target_symbol(target_symbol, ctx)?;
47
48 let source_ast = ctx
50 .ast_registry
51 .get(symbol_id)
52 .ok_or(ConvertError::SymbolNotFound(symbol_id))?;
53
54 let mut new_fn = match source_ast {
55 PureItem::Fn(f) => f.clone(),
56 _ => {
57 return Err(ConvertError::Apply(format!(
58 "Symbol {:?} is not a function",
59 symbol_id
60 )))
61 }
62 };
63
64 new_fn.name = to.clone();
66
67 let source_path = ctx
69 .registry
70 .path(symbol_id)
71 .ok_or(ConvertError::SymbolNotFound(symbol_id))?;
72 let parent_path = source_path.parent().ok_or_else(|| {
73 ConvertError::Apply("Source function has no parent module".to_string())
74 })?;
75 let parent_id = ctx.registry.lookup(&parent_path).ok_or_else(|| {
76 ConvertError::Apply(format!("Parent module '{}' not found", parent_path))
77 })?;
78
79 Ok(vec![Box::new(AddPureItemsMutation::new(
80 parent_id,
81 vec![PureItem::Fn(new_fn)],
82 ))])
83 }
84 MutationSpec::DuplicateStruct {
85 target: target_symbol,
86 to,
87 include_impls,
88 } => {
89 let symbol_id = self.resolve_target_symbol(target_symbol, ctx)?;
91
92 let source_ast = ctx
94 .ast_registry
95 .get(symbol_id)
96 .ok_or(ConvertError::SymbolNotFound(symbol_id))?;
97
98 let (mut new_struct, source_name) = match source_ast {
99 PureItem::Struct(s) => (s.clone(), s.name.clone()),
100 _ => {
101 return Err(ConvertError::Apply(format!(
102 "Symbol {:?} is not a struct",
103 symbol_id
104 )))
105 }
106 };
107
108 new_struct.name = to.clone();
110
111 let mut items = vec![PureItem::Struct(new_struct)];
112
113 if *include_impls {
115 for (impl_id, _) in ctx.registry.iter() {
116 if ctx.registry.kind(impl_id) == Some(SymbolKind::Impl) {
117 if let Some(PureItem::Impl(imp)) = ctx.ast_registry.get(impl_id) {
118 if imp.self_ty == source_name {
119 let mut new_impl = imp.clone();
120 new_impl.self_ty = to.clone();
121 items.push(PureItem::Impl(new_impl));
122 }
123 }
124 }
125 }
126 }
127
128 let source_path = ctx
130 .registry
131 .path(symbol_id)
132 .ok_or(ConvertError::SymbolNotFound(symbol_id))?;
133 let parent_path = source_path.parent().ok_or_else(|| {
134 ConvertError::Apply("Source struct has no parent module".to_string())
135 })?;
136 let parent_id = ctx.registry.lookup(&parent_path).ok_or_else(|| {
137 ConvertError::Apply(format!("Parent module '{}' not found", parent_path))
138 })?;
139
140 Ok(vec![Box::new(AddPureItemsMutation::new(parent_id, items))])
141 }
142 MutationSpec::DuplicateEnum {
143 target: target_symbol,
144 to,
145 include_impls,
146 } => {
147 let symbol_id = self.resolve_target_symbol(target_symbol, ctx)?;
149
150 let source_ast = ctx
152 .ast_registry
153 .get(symbol_id)
154 .ok_or(ConvertError::SymbolNotFound(symbol_id))?;
155
156 let (mut new_enum, source_name) = match source_ast {
157 PureItem::Enum(e) => (e.clone(), e.name.clone()),
158 _ => {
159 return Err(ConvertError::Apply(format!(
160 "Symbol {:?} is not an enum",
161 symbol_id
162 )))
163 }
164 };
165
166 new_enum.name = to.clone();
168
169 let mut items = vec![PureItem::Enum(new_enum)];
170
171 if *include_impls {
173 for (impl_id, _) in ctx.registry.iter() {
174 if ctx.registry.kind(impl_id) == Some(SymbolKind::Impl) {
175 if let Some(PureItem::Impl(imp)) = ctx.ast_registry.get(impl_id) {
176 if imp.self_ty == source_name {
177 let mut new_impl = imp.clone();
178 new_impl.self_ty = to.clone();
179 items.push(PureItem::Impl(new_impl));
180 }
181 }
182 }
183 }
184 }
185
186 let source_path = ctx
188 .registry
189 .path(symbol_id)
190 .ok_or(ConvertError::SymbolNotFound(symbol_id))?;
191 let parent_path = source_path.parent().ok_or_else(|| {
192 ConvertError::Apply("Source enum has no parent module".to_string())
193 })?;
194 let parent_id = ctx.registry.lookup(&parent_path).ok_or_else(|| {
195 ConvertError::Apply(format!("Parent module '{}' not found", parent_path))
196 })?;
197
198 Ok(vec![Box::new(AddPureItemsMutation::new(parent_id, items))])
199 }
200 MutationSpec::DuplicateModTree {
201 target: target_symbol,
202 to,
203 } => {
204 let symbol_id = self.resolve_target_symbol(target_symbol, ctx)?;
206
207 let source_ast = ctx
209 .ast_registry
210 .get(symbol_id)
211 .ok_or(ConvertError::SymbolNotFound(symbol_id))?;
212
213 let mut new_mod = match source_ast {
214 PureItem::Mod(m) => m.clone(),
215 _ => {
216 return Err(ConvertError::Apply(format!(
217 "Symbol {:?} is not a module",
218 symbol_id
219 )))
220 }
221 };
222
223 new_mod.name = to.clone();
225
226 let source_path = ctx
228 .registry
229 .path(symbol_id)
230 .ok_or(ConvertError::SymbolNotFound(symbol_id))?;
231 let parent_path = source_path.parent().ok_or_else(|| {
232 ConvertError::Apply("Source module has no parent module".to_string())
233 })?;
234 let parent_id = ctx.registry.lookup(&parent_path).ok_or_else(|| {
235 ConvertError::Apply(format!("Parent module '{}' not found", parent_path))
236 })?;
237
238 Ok(vec![Box::new(AddPureItemsMutation::new(
239 parent_id,
240 vec![PureItem::Mod(new_mod)],
241 ))])
242 }
243 _ => Err(ConvertError::TypeMismatch {
244 expected: "Duplicate*",
245 actual: spec.kind_name().to_string(),
246 }),
247 }
248 }
249}