1use crate::SymbolPath;
33use ryo_symbol::SymbolId;
34
35#[derive(Debug, Clone, PartialEq, Eq)]
39pub enum CascadeSpec {
40 AddDerive {
46 symbol_id: SymbolId,
48 derives: Vec<String>,
50 },
51
52 GenerateImpl {
56 target: SymbolPath,
58 trait_name: String,
60 call_new: bool,
62 },
63
64 ChangeVisibility {
68 symbol_id: SymbolId,
70 visibility: Visibility,
72 },
73
74 AddUse {
78 target_module: SymbolPath,
80 path: String,
82 },
83
84 AddMatchArm {
88 target: SymbolPath,
90 function_name: String,
92 enum_name: String,
94 pattern: String,
96 body: String,
98 },
99
100 RemoveMatchArm {
104 target: SymbolPath,
106 function_name: String,
108 enum_name: String,
110 pattern: String,
112 },
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
117pub enum Visibility {
118 Private,
120 Crate,
122 Super,
124 Public,
126}
127
128impl CascadeSpec {
129 pub fn add_derive(symbol_id: SymbolId, derives: Vec<String>) -> Self {
131 Self::AddDerive { symbol_id, derives }
132 }
133
134 pub fn generate_impl(
136 target: SymbolPath,
137 trait_name: impl Into<String>,
138 call_new: bool,
139 ) -> Self {
140 Self::GenerateImpl {
141 target,
142 trait_name: trait_name.into(),
143 call_new,
144 }
145 }
146
147 pub fn change_visibility(symbol_id: SymbolId, visibility: Visibility) -> Self {
149 Self::ChangeVisibility {
150 symbol_id,
151 visibility,
152 }
153 }
154
155 pub fn add_use(target_module: SymbolPath, path: impl Into<String>) -> Self {
157 Self::AddUse {
158 target_module,
159 path: path.into(),
160 }
161 }
162
163 pub fn add_match_arm(
165 target: SymbolPath,
166 function_name: impl Into<String>,
167 enum_name: impl Into<String>,
168 pattern: impl Into<String>,
169 body: impl Into<String>,
170 ) -> Self {
171 Self::AddMatchArm {
172 target,
173 function_name: function_name.into(),
174 enum_name: enum_name.into(),
175 pattern: pattern.into(),
176 body: body.into(),
177 }
178 }
179
180 pub fn remove_match_arm(
182 target: SymbolPath,
183 function_name: impl Into<String>,
184 enum_name: impl Into<String>,
185 pattern: impl Into<String>,
186 ) -> Self {
187 Self::RemoveMatchArm {
188 target,
189 function_name: function_name.into(),
190 enum_name: enum_name.into(),
191 pattern: pattern.into(),
192 }
193 }
194}
195
196#[cfg(test)]
197mod tests {
198 use super::*;
199 use ryo_symbol::{SymbolKind, SymbolRegistry};
200
201 fn dummy_symbol_id(name: &str) -> SymbolId {
203 let mut registry = SymbolRegistry::new();
204 let path = SymbolPath::parse(&format!("test_crate::test_{}", name)).unwrap();
205 registry.register(path, SymbolKind::Struct).unwrap()
206 }
207
208 #[test]
209 fn test_cascade_spec_add_derive() {
210 let symbol_id = dummy_symbol_id("config");
211 let spec = CascadeSpec::add_derive(symbol_id, vec!["Default".to_string()]);
212
213 match spec {
214 CascadeSpec::AddDerive {
215 symbol_id: sid,
216 derives,
217 } => {
218 assert_eq!(sid, symbol_id);
219 assert_eq!(derives, vec!["Default".to_string()]);
220 }
221 _ => panic!("Expected AddDerive"),
222 }
223 }
224
225 #[test]
226 fn test_cascade_spec_add_match_arm() {
227 let target_path = SymbolPath::parse("test_crate::handlers").unwrap();
228 let spec = CascadeSpec::add_match_arm(
229 target_path.clone(),
230 "process_status",
231 "Status",
232 "Status::Cancelled",
233 "todo!()",
234 );
235
236 match &spec {
237 CascadeSpec::AddMatchArm {
238 target,
239 function_name,
240 enum_name,
241 pattern,
242 body,
243 } => {
244 assert_eq!(target, &target_path);
245 assert_eq!(function_name, "process_status");
246 assert_eq!(enum_name, "Status");
247 assert_eq!(pattern, "Status::Cancelled");
248 assert_eq!(body, "todo!()");
249 }
250 _ => panic!("Expected AddMatchArm"),
251 }
252 }
253}