Skip to main content

ryo_mutations/basic/
match_arm.rs

1//! Match arm mutations: AddMatchArmMutation, RemoveMatchArmMutation, ReplaceMatchArmMutation
2//!
3//! Adds, removes, or replaces match arms in existing match expressions.
4
5use ryo_symbol::SymbolId;
6
7use crate::Mutation;
8
9/// Add a match arm to an existing match expression in a function
10#[derive(Debug, Clone)]
11pub struct AddMatchArmMutation {
12    /// Target function SymbolId
13    pub function_id: SymbolId,
14    /// Enum name to identify the target match expression
15    pub enum_name: String,
16    /// Pattern string (e.g., "Status::Cancelled")
17    pub pattern: String,
18    /// Body string (e.g., "todo!()")
19    pub body: String,
20}
21
22impl AddMatchArmMutation {
23    pub fn new(
24        function_id: SymbolId,
25        enum_name: impl Into<String>,
26        pattern: impl Into<String>,
27        body: impl Into<String>,
28    ) -> Self {
29        Self {
30            function_id,
31            enum_name: enum_name.into(),
32            pattern: pattern.into(),
33            body: body.into(),
34        }
35    }
36}
37
38impl Mutation for AddMatchArmMutation {
39    fn describe(&self) -> String {
40        format!(
41            "Add match arm '{}' => {} in function {}",
42            self.pattern, self.body, self.function_id
43        )
44    }
45
46    fn mutation_type(&self) -> &'static str {
47        "AddMatchArm"
48    }
49
50    fn box_clone(&self) -> Box<dyn Mutation> {
51        Box::new(self.clone())
52    }
53}
54
55/// Remove a match arm from an existing match expression in a function
56#[derive(Debug, Clone)]
57pub struct RemoveMatchArmMutation {
58    /// Target function SymbolId
59    pub function_id: SymbolId,
60    /// Enum name to identify the target match expression
61    pub enum_name: String,
62    /// Pattern string to remove (e.g., "Status::Completed")
63    pub pattern: String,
64}
65
66impl RemoveMatchArmMutation {
67    pub fn new(
68        function_id: SymbolId,
69        enum_name: impl Into<String>,
70        pattern: impl Into<String>,
71    ) -> Self {
72        Self {
73            function_id,
74            enum_name: enum_name.into(),
75            pattern: pattern.into(),
76        }
77    }
78}
79
80impl Mutation for RemoveMatchArmMutation {
81    fn describe(&self) -> String {
82        format!(
83            "Remove match arm '{}' in function {}",
84            self.pattern, self.function_id
85        )
86    }
87
88    fn mutation_type(&self) -> &'static str {
89        "RemoveMatchArm"
90    }
91
92    fn box_clone(&self) -> Box<dyn Mutation> {
93        Box::new(self.clone())
94    }
95}
96
97/// Replace a match arm (pattern + body) in an existing match expression
98///
99/// This mutation allows replacing both the pattern and body of a match arm
100/// atomically, solving the issue where ReplaceExpr only modifies the body
101/// but leaves the pattern unchanged.
102#[derive(Debug, Clone)]
103pub struct ReplaceMatchArmMutation {
104    /// Target function SymbolId
105    pub function_id: SymbolId,
106    /// Enum name to identify the target match expression
107    pub enum_name: String,
108    /// Pattern to match for replacement (e.g., "PathSegment::Slice { start: _, end: _ }")
109    pub old_pattern: String,
110    /// New pattern string (e.g., "PathSegment::Slice { start, end }")
111    pub new_pattern: String,
112    /// New body string (e.g., "{ /* implementation */ }")
113    pub new_body: String,
114}
115
116impl ReplaceMatchArmMutation {
117    pub fn new(
118        function_id: SymbolId,
119        enum_name: impl Into<String>,
120        old_pattern: impl Into<String>,
121        new_pattern: impl Into<String>,
122        new_body: impl Into<String>,
123    ) -> Self {
124        Self {
125            function_id,
126            enum_name: enum_name.into(),
127            old_pattern: old_pattern.into(),
128            new_pattern: new_pattern.into(),
129            new_body: new_body.into(),
130        }
131    }
132}
133
134impl Mutation for ReplaceMatchArmMutation {
135    fn describe(&self) -> String {
136        format!(
137            "Replace match arm '{}' with '{}' in function {}",
138            self.old_pattern, self.new_pattern, self.function_id
139        )
140    }
141
142    fn mutation_type(&self) -> &'static str {
143        "ReplaceMatchArm"
144    }
145
146    fn box_clone(&self) -> Box<dyn Mutation> {
147        Box::new(self.clone())
148    }
149}