use std::path::PathBuf;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[derive(Default)]
pub enum EditMode {
#[default]
Surgical,
Reformat,
}
impl std::fmt::Display for EditMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Surgical => write!(f, "surgical"),
Self::Reformat => write!(f, "reformat"),
}
}
}
impl std::str::FromStr for EditMode {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"surgical" => Ok(Self::Surgical),
"reformat" => Ok(Self::Reformat),
_ => Err(format!(
"Invalid edit mode: {}. Valid values are 'surgical' or 'reformat'",
s
)),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Operation {
AddStructField(AddStructFieldOp),
UpdateStructField(UpdateStructFieldOp),
RemoveStructField(RemoveStructFieldOp),
AddStructLiteralField(AddStructLiteralFieldOp),
AddEnumVariant(AddEnumVariantOp),
UpdateEnumVariant(UpdateEnumVariantOp),
RemoveEnumVariant(RemoveEnumVariantOp),
AddMatchArm(AddMatchArmOp),
UpdateMatchArm(UpdateMatchArmOp),
RemoveMatchArm(RemoveMatchArmOp),
AddImplMethod(AddImplMethodOp),
AddUseStatement(AddUseStatementOp),
AddDerive(AddDeriveOp),
Transform(TransformOp),
RenameEnumVariant(RenameEnumVariantOp),
RenameFunction(RenameFunctionOp),
AddDocComment(AddDocCommentOp),
UpdateDocComment(UpdateDocCommentOp),
RemoveDocComment(RemoveDocCommentOp),
SetStructLiteralBase(SetStructLiteralBaseOp),
AddCallArg(AddCallArgOp),
UpdateCallArg(UpdateCallArgOp),
RemoveCallArg(RemoveCallArgOp),
}
impl Operation {
pub const fn kind_name(&self) -> &'static str {
match self {
Self::AddStructField(_) => "AddStructField",
Self::UpdateStructField(_) => "UpdateStructField",
Self::RemoveStructField(_) => "RemoveStructField",
Self::AddStructLiteralField(_) => "AddStructLiteralField",
Self::AddEnumVariant(_) => "AddEnumVariant",
Self::UpdateEnumVariant(_) => "UpdateEnumVariant",
Self::RemoveEnumVariant(_) => "RemoveEnumVariant",
Self::RenameEnumVariant(_) => "RenameEnumVariant",
Self::AddMatchArm(_) => "AddMatchArm",
Self::UpdateMatchArm(_) => "UpdateMatchArm",
Self::RemoveMatchArm(_) => "RemoveMatchArm",
Self::AddImplMethod(_) => "AddImplMethod",
Self::AddUseStatement(_) => "AddUseStatement",
Self::AddDerive(_) => "AddDerive",
Self::Transform(_) => "Transform",
Self::RenameFunction(_) => "RenameFunction",
Self::AddDocComment(_) => "AddDocComment",
Self::UpdateDocComment(_) => "UpdateDocComment",
Self::RemoveDocComment(_) => "RemoveDocComment",
Self::SetStructLiteralBase(_) => "SetStructLiteralBase",
Self::AddCallArg(_) => "AddCallArg",
Self::UpdateCallArg(_) => "UpdateCallArg",
Self::RemoveCallArg(_) => "RemoveCallArg",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddStructFieldOp {
pub struct_name: String,
pub field_def: String,
pub position: InsertPosition,
#[serde(default)]
pub literal_default: Option<String>,
#[serde(default)]
pub where_filter: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateStructFieldOp {
pub struct_name: String,
pub field_def: String, #[serde(default)]
pub where_filter: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoveStructFieldOp {
pub struct_name: String,
pub field_name: String, #[serde(default)]
pub literal_only: bool, #[serde(default)]
pub where_filter: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddStructLiteralFieldOp {
pub struct_name: String,
pub field_def: String, pub position: InsertPosition,
#[serde(default)]
pub struct_path: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SetStructLiteralBaseOp {
pub struct_name: String,
pub base_expr: String,
#[serde(default)]
pub struct_path: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddEnumVariantOp {
pub enum_name: String,
pub variant_def: String, pub position: InsertPosition,
#[serde(default)]
pub where_filter: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateEnumVariantOp {
pub enum_name: String,
pub variant_def: String,
#[serde(default)]
pub where_filter: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoveEnumVariantOp {
pub enum_name: String,
pub variant_name: String, #[serde(default)]
pub where_filter: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddMatchArmOp {
pub pattern: String, pub body: String, pub function_name: Option<String>, #[serde(default)]
pub auto_detect: bool, pub enum_name: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateMatchArmOp {
pub pattern: String, pub new_body: String, pub function_name: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoveMatchArmOp {
pub pattern: String, pub function_name: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddImplMethodOp {
pub target: String, pub method_def: String, pub position: InsertPosition,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddUseStatementOp {
pub use_path: String, pub position: InsertPosition,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddDeriveOp {
pub target_name: String, pub target_type: String, pub derives: Vec<String>, #[serde(default)]
pub where_filter: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum InsertPosition {
First,
Last,
After(String), Before(String), }
#[derive(Debug, Serialize, Deserialize)]
pub struct BatchSpec {
pub base_path: PathBuf,
pub operations: Vec<Operation>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct NodeLocation {
pub line: usize,
pub column: usize,
pub end_line: usize,
pub end_column: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BackupNode {
pub node_type: String, pub identifier: String, pub original_content: String, pub location: NodeLocation,
}
#[derive(Debug)]
pub struct ModificationResult {
pub changed: bool,
pub modified_nodes: Vec<BackupNode>,
pub unmatched_qualified_paths: Option<std::collections::HashMap<String, usize>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct InspectResult {
pub file_path: String,
pub node_type: String, pub identifier: String, pub location: NodeLocation,
pub snippet: String, #[serde(skip_serializing_if = "Option::is_none")]
pub preceding_comment: Option<String>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransformOp {
pub node_type: String, pub name_filter: Option<String>, pub content_filter: Option<String>, pub action: TransformAction, }
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum TransformAction {
Comment, Remove, Replace { with: String }, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RenameEnumVariantOp {
pub enum_name: String, pub old_variant: String, pub new_variant: String, #[serde(default)]
pub enum_path: Option<String>,
#[serde(default)]
pub edit_mode: EditMode, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RenameFunctionOp {
pub old_name: String, pub new_name: String, #[serde(default)]
pub function_path: Option<String>, #[serde(default)]
pub edit_mode: EditMode, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddDocCommentOp {
pub target_type: String, pub name: String, pub doc_comment: String, #[serde(default)]
pub style: DocCommentStyle, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateDocCommentOp {
pub target_type: String, pub name: String, pub doc_comment: String, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoveDocCommentOp {
pub target_type: String, pub name: String, }
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[derive(Default)]
pub enum DocCommentStyle {
#[default]
Line, Block, }
impl std::str::FromStr for DocCommentStyle {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"line" => Ok(Self::Line),
"block" => Ok(Self::Block),
_ => Err(format!(
"Invalid doc comment style: {}. Valid values are 'line' or 'block'",
s
)),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldLocation {
pub file_path: String,
pub line: usize,
pub context: FieldContext,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub enum ArgPosition {
First,
#[default]
Last,
Index(usize),
}
impl std::fmt::Display for ArgPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::First => write!(f, "first"),
Self::Last => write!(f, "last"),
Self::Index(i) => write!(f, "index:{}", i),
}
}
}
impl std::str::FromStr for ArgPosition {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"first" => Ok(Self::First),
"last" => Ok(Self::Last),
s if s.starts_with("index:") => {
let idx = s[6..]
.parse::<usize>()
.map_err(|_| format!("Invalid index in position: {}", s))?;
Ok(Self::Index(idx))
}
s => {
s.parse::<usize>().map_or_else(
|_| {
Err(format!(
"Invalid arg position: {}. Valid values are 'first', 'last', or 'index:N'",
s
))
},
|idx| Ok(Self::Index(idx)),
)
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddCallArgOp {
pub call_name: String,
pub arg_expr: String,
#[serde(default)]
pub position: ArgPosition,
#[serde(default)]
pub call_type: Option<String>,
#[serde(default)]
pub content_filter: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateCallArgOp {
pub call_name: String,
pub arg_index: usize,
pub new_expr: String,
#[serde(default)]
pub call_type: Option<String>,
#[serde(default)]
pub content_filter: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoveCallArgOp {
pub call_name: String,
pub arg_index: usize,
#[serde(default)]
pub call_type: Option<String>,
#[serde(default)]
pub content_filter: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum FieldContext {
StructDefinition {
struct_name: String,
field_type: String,
},
EnumVariantDefinition {
enum_name: String,
variant_name: String,
field_type: String,
},
StructLiteral {
struct_name: String,
},
}