ryo_executor/engine/impls/
use_stmt.rs1use ryo_mutations::basic::{AddUseMutation, RemoveUseMutation};
4use ryo_mutations::MutationResult;
5use ryo_source::pure::{PureItem, PureUse, PureUseTree, PureVis};
6use ryo_symbol::SymbolKind;
7
8use crate::engine::{ASTMutationContext, ASTRegApply};
9
10impl ASTRegApply for AddUseMutation {
11 fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
12 let module_id = ctx
14 .symbol_registry
15 .iter()
16 .filter(|(id, _)| ctx.symbol_registry.kind(*id) == Some(SymbolKind::Mod))
17 .find(|(_, path)| path.to_string() == "crate")
18 .map(|(id, _)| id);
19
20 let module_id = match module_id {
21 Some(id) => id,
22 None => {
23 return MutationResult {
24 mutation_type: "AddUse".to_string(),
25 changes: 0,
26 description: "Crate root module not found".to_string(),
27 };
28 }
29 };
30
31 let exists = ctx
33 .symbol_registry
34 .iter()
35 .filter(|(id, _)| ctx.symbol_registry.kind(*id) == Some(SymbolKind::Use))
36 .any(|(_, path)| path.name() == self.path);
37
38 if exists {
39 return MutationResult {
40 mutation_type: "AddUse".to_string(),
41 changes: 0,
42 description: format!("Use statement '{}' already exists", self.path),
43 };
44 }
45
46 let tree = parse_path_to_tree(&self.path);
48
49 let use_item = PureUse {
51 vis: PureVis::Private,
52 tree,
53 };
54
55 let use_path = ctx
57 .symbol_registry
58 .path(module_id)
59 .and_then(|p| p.child(&self.path).ok());
60
61 if let Some(path) = use_path {
62 if let Ok(use_id) = ctx.symbol_registry.register(path, SymbolKind::Use) {
63 ctx.ast_registry.set(use_id, PureItem::Use(use_item));
64
65 return MutationResult {
66 mutation_type: "AddUse".to_string(),
67 changes: 1,
68 description: format!("Added use statement '{}'", self.path),
69 };
70 }
71 }
72
73 MutationResult {
74 mutation_type: "AddUse".to_string(),
75 changes: 0,
76 description: format!("Failed to register use statement '{}'", self.path),
77 }
78 }
79}
80
81impl ASTRegApply for RemoveUseMutation {
82 fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
83 let use_id = ctx
84 .symbol_registry
85 .iter()
86 .filter(|(id, _)| ctx.symbol_registry.kind(*id) == Some(SymbolKind::Use))
87 .find(|(_, path)| {
88 if self.path.contains("::") {
89 path.to_string() == self.path || path.name() == self.path
90 } else {
91 path.name() == self.path
92 }
93 })
94 .map(|(id, _)| id);
95
96 let use_id = match use_id {
97 Some(id) => id,
98 None => {
99 return MutationResult {
100 mutation_type: "RemoveUse".to_string(),
101 changes: 0,
102 description: format!("Use statement '{}' not found", self.path),
103 };
104 }
105 };
106
107 ctx.ast_registry.remove(use_id);
108
109 MutationResult {
110 mutation_type: "RemoveUse".to_string(),
111 changes: 1,
112 description: format!("Removed use statement '{}'", self.path),
113 }
114 }
115}
116
117fn parse_path_to_tree(path: &str) -> PureUseTree {
119 let parts: Vec<&str> = path.split("::").collect();
120 if parts.is_empty() {
121 return PureUseTree::Name(path.to_string());
122 }
123
124 let mut tree = PureUseTree::Name(
126 parts
127 .last()
128 .expect("is_empty() guard above guarantees a last element")
129 .to_string(),
130 );
131 for part in parts.iter().rev().skip(1) {
132 tree = PureUseTree::Path {
133 path: part.to_string(),
134 tree: Box::new(tree),
135 };
136 }
137 tree
138}