1use serde::{Deserialize, Serialize};
6use std::path::PathBuf;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
10#[serde(rename_all = "lowercase")]
11pub enum EditMode {
12 Surgical,
15 Reformat,
18}
19
20impl Default for EditMode {
21 fn default() -> Self {
22 EditMode::Surgical
23 }
24}
25
26impl std::fmt::Display for EditMode {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 match self {
29 EditMode::Surgical => write!(f, "surgical"),
30 EditMode::Reformat => write!(f, "reformat"),
31 }
32 }
33}
34
35impl std::str::FromStr for EditMode {
36 type Err = String;
37
38 fn from_str(s: &str) -> Result<Self, Self::Err> {
39 match s.to_lowercase().as_str() {
40 "surgical" => Ok(EditMode::Surgical),
41 "reformat" => Ok(EditMode::Reformat),
42 _ => Err(format!("Invalid edit mode: {}. Valid values are 'surgical' or 'reformat'", s)),
43 }
44 }
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(tag = "type")]
49pub enum Operation {
50 AddStructField(AddStructFieldOp),
51 UpdateStructField(UpdateStructFieldOp),
52 RemoveStructField(RemoveStructFieldOp),
53 AddStructLiteralField(AddStructLiteralFieldOp),
54 AddEnumVariant(AddEnumVariantOp),
55 UpdateEnumVariant(UpdateEnumVariantOp),
56 RemoveEnumVariant(RemoveEnumVariantOp),
57 AddMatchArm(AddMatchArmOp),
58 UpdateMatchArm(UpdateMatchArmOp),
59 RemoveMatchArm(RemoveMatchArmOp),
60 AddImplMethod(AddImplMethodOp),
61 AddUseStatement(AddUseStatementOp),
62 AddDerive(AddDeriveOp),
63 Transform(TransformOp),
64 RenameEnumVariant(RenameEnumVariantOp),
65 RenameFunction(RenameFunctionOp),
66 AddDocComment(AddDocCommentOp),
67 UpdateDocComment(UpdateDocCommentOp),
68 RemoveDocComment(RemoveDocCommentOp),
69 SetStructLiteralBase(SetStructLiteralBaseOp),
70 AddCallArg(AddCallArgOp),
71 UpdateCallArg(UpdateCallArgOp),
72 RemoveCallArg(RemoveCallArgOp),
73}
74
75impl Operation {
76 pub fn kind_name(&self) -> &'static str {
79 match self {
80 Operation::AddStructField(_) => "AddStructField",
81 Operation::UpdateStructField(_) => "UpdateStructField",
82 Operation::RemoveStructField(_) => "RemoveStructField",
83 Operation::AddStructLiteralField(_) => "AddStructLiteralField",
84 Operation::AddEnumVariant(_) => "AddEnumVariant",
85 Operation::UpdateEnumVariant(_) => "UpdateEnumVariant",
86 Operation::RemoveEnumVariant(_) => "RemoveEnumVariant",
87 Operation::RenameEnumVariant(_) => "RenameEnumVariant",
88 Operation::AddMatchArm(_) => "AddMatchArm",
89 Operation::UpdateMatchArm(_) => "UpdateMatchArm",
90 Operation::RemoveMatchArm(_) => "RemoveMatchArm",
91 Operation::AddImplMethod(_) => "AddImplMethod",
92 Operation::AddUseStatement(_) => "AddUseStatement",
93 Operation::AddDerive(_) => "AddDerive",
94 Operation::Transform(_) => "Transform",
95 Operation::RenameFunction(_) => "RenameFunction",
96 Operation::AddDocComment(_) => "AddDocComment",
97 Operation::UpdateDocComment(_) => "UpdateDocComment",
98 Operation::RemoveDocComment(_) => "RemoveDocComment",
99 Operation::SetStructLiteralBase(_) => "SetStructLiteralBase",
100 Operation::AddCallArg(_) => "AddCallArg",
101 Operation::UpdateCallArg(_) => "UpdateCallArg",
102 Operation::RemoveCallArg(_) => "RemoveCallArg",
103 }
104 }
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct AddStructFieldOp {
109 pub struct_name: String,
110 pub field_def: String, pub position: InsertPosition,
112 #[serde(default)]
113 pub literal_default: Option<String>, #[serde(default)]
115 pub where_filter: Option<String>, }
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct UpdateStructFieldOp {
120 pub struct_name: String,
121 pub field_def: String, #[serde(default)]
123 pub where_filter: Option<String>, }
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct RemoveStructFieldOp {
128 pub struct_name: String,
129 pub field_name: String, #[serde(default)]
131 pub literal_only: bool, #[serde(default)]
133 pub where_filter: Option<String>, }
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct AddStructLiteralFieldOp {
138 pub struct_name: String,
139 pub field_def: String, pub position: InsertPosition,
141 #[serde(default)]
142 pub struct_path: Option<String>, }
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct SetStructLiteralBaseOp {
149 pub struct_name: String,
150 pub base_expr: String,
153 #[serde(default)]
154 pub struct_path: Option<String>, }
156
157#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct AddEnumVariantOp {
159 pub enum_name: String,
160 pub variant_def: String, pub position: InsertPosition,
162 #[serde(default)]
163 pub where_filter: Option<String>, }
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct UpdateEnumVariantOp {
168 pub enum_name: String,
169 pub variant_def: String, #[serde(default)]
171 pub where_filter: Option<String>, }
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct RemoveEnumVariantOp {
176 pub enum_name: String,
177 pub variant_name: String, #[serde(default)]
179 pub where_filter: Option<String>, }
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct AddMatchArmOp {
184 pub pattern: String, pub body: String, pub function_name: Option<String>, #[serde(default)]
188 pub auto_detect: bool, pub enum_name: Option<String>, }
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct UpdateMatchArmOp {
194 pub pattern: String, pub new_body: String, pub function_name: Option<String>, }
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct RemoveMatchArmOp {
201 pub pattern: String, pub function_name: Option<String>, }
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct AddImplMethodOp {
207 pub target: String, pub method_def: String, pub position: InsertPosition,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct AddUseStatementOp {
214 pub use_path: String, pub position: InsertPosition,
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
219pub struct AddDeriveOp {
220 pub target_name: String, pub target_type: String, pub derives: Vec<String>, #[serde(default)]
224 pub where_filter: Option<String>, }
226
227#[derive(Debug, Clone, Serialize, Deserialize)]
228pub enum InsertPosition {
229 First,
230 Last,
231 After(String), Before(String), }
234
235#[derive(Debug, Serialize, Deserialize)]
236pub struct BatchSpec {
237 pub base_path: PathBuf,
238 pub operations: Vec<Operation>,
239}
240
241#[derive(Debug, Serialize, Deserialize, Clone)]
242pub struct NodeLocation {
243 pub line: usize,
244 pub column: usize,
245 pub end_line: usize,
246 pub end_column: usize,
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize)]
251pub struct BackupNode {
252 pub node_type: String, pub identifier: String, pub original_content: String, pub location: NodeLocation,
256}
257
258#[derive(Debug)]
260pub struct ModificationResult {
261 pub changed: bool,
262 pub modified_nodes: Vec<BackupNode>,
263 pub unmatched_qualified_paths: Option<std::collections::HashMap<String, usize>>,
266}
267
268#[derive(Debug, Serialize, Deserialize)]
270pub struct InspectResult {
271 pub file_path: String,
272 pub node_type: String, pub identifier: String, pub location: NodeLocation,
275 pub snippet: String, #[serde(skip_serializing_if = "Option::is_none")]
277 pub preceding_comment: Option<String>, }
279
280#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct TransformOp {
283 pub node_type: String, pub name_filter: Option<String>, pub content_filter: Option<String>, pub action: TransformAction, }
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
291#[serde(tag = "type")]
292pub enum TransformAction {
293 Comment, Remove, Replace { with: String }, }
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct RenameEnumVariantOp {
301 pub enum_name: String, pub old_variant: String, pub new_variant: String, #[serde(default)]
305 pub enum_path: Option<String>, #[serde(default)]
307 pub edit_mode: EditMode, }
309
310#[derive(Debug, Clone, Serialize, Deserialize)]
312pub struct RenameFunctionOp {
313 pub old_name: String, pub new_name: String, #[serde(default)]
316 pub function_path: Option<String>, #[serde(default)]
318 pub edit_mode: EditMode, }
320
321#[derive(Debug, Clone, Serialize, Deserialize)]
323pub struct AddDocCommentOp {
324 pub target_type: String, pub name: String, pub doc_comment: String, #[serde(default)]
328 pub style: DocCommentStyle, }
330
331#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct UpdateDocCommentOp {
334 pub target_type: String, pub name: String, pub doc_comment: String, }
338
339#[derive(Debug, Clone, Serialize, Deserialize)]
341pub struct RemoveDocCommentOp {
342 pub target_type: String, pub name: String, }
345
346#[derive(Debug, Clone, Serialize, Deserialize)]
348#[serde(rename_all = "lowercase")]
349pub enum DocCommentStyle {
350 Line, Block, }
353
354impl Default for DocCommentStyle {
355 fn default() -> Self {
356 DocCommentStyle::Line
357 }
358}
359
360impl std::str::FromStr for DocCommentStyle {
361 type Err = String;
362
363 fn from_str(s: &str) -> Result<Self, Self::Err> {
364 match s.to_lowercase().as_str() {
365 "line" => Ok(DocCommentStyle::Line),
366 "block" => Ok(DocCommentStyle::Block),
367 _ => Err(format!("Invalid doc comment style: {}. Valid values are 'line' or 'block'", s)),
368 }
369 }
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
374pub struct FieldLocation {
375 pub file_path: String,
376 pub line: usize,
377 pub context: FieldContext,
378}
379
380#[derive(Debug, Clone, Serialize, Deserialize)]
382pub enum ArgPosition {
383 First,
385 Last,
387 Index(usize),
389}
390
391impl Default for ArgPosition {
392 fn default() -> Self {
393 ArgPosition::Last
394 }
395}
396
397impl std::fmt::Display for ArgPosition {
398 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
399 match self {
400 ArgPosition::First => write!(f, "first"),
401 ArgPosition::Last => write!(f, "last"),
402 ArgPosition::Index(i) => write!(f, "index:{}", i),
403 }
404 }
405}
406
407impl std::str::FromStr for ArgPosition {
408 type Err = String;
409
410 fn from_str(s: &str) -> Result<Self, Self::Err> {
411 match s.to_lowercase().as_str() {
412 "first" => Ok(ArgPosition::First),
413 "last" => Ok(ArgPosition::Last),
414 s if s.starts_with("index:") => {
415 let idx = s[6..].parse::<usize>()
416 .map_err(|_| format!("Invalid index in position: {}", s))?;
417 Ok(ArgPosition::Index(idx))
418 }
419 s => {
420 if let Ok(idx) = s.parse::<usize>() {
422 Ok(ArgPosition::Index(idx))
423 } else {
424 Err(format!("Invalid arg position: {}. Valid values are 'first', 'last', or 'index:N'", s))
425 }
426 }
427 }
428 }
429}
430
431#[derive(Debug, Clone, Serialize, Deserialize)]
433pub struct AddCallArgOp {
434 pub call_name: String,
436 pub arg_expr: String,
438 #[serde(default)]
440 pub position: ArgPosition,
441 #[serde(default)]
443 pub call_type: Option<String>,
444 #[serde(default)]
446 pub content_filter: Option<String>,
447}
448
449#[derive(Debug, Clone, Serialize, Deserialize)]
451pub struct UpdateCallArgOp {
452 pub call_name: String,
454 pub arg_index: usize,
456 pub new_expr: String,
458 #[serde(default)]
460 pub call_type: Option<String>,
461 #[serde(default)]
463 pub content_filter: Option<String>,
464}
465
466#[derive(Debug, Clone, Serialize, Deserialize)]
468pub struct RemoveCallArgOp {
469 pub call_name: String,
471 pub arg_index: usize,
473 #[serde(default)]
475 pub call_type: Option<String>,
476 #[serde(default)]
478 pub content_filter: Option<String>,
479}
480
481#[derive(Debug, Clone, Serialize, Deserialize)]
483#[serde(tag = "type")]
484pub enum FieldContext {
485 StructDefinition {
486 struct_name: String,
487 field_type: String,
488 },
489 EnumVariantDefinition {
490 enum_name: String,
491 variant_name: String,
492 field_type: String,
493 },
494 StructLiteral {
495 struct_name: String,
496 },
497}