Skip to main content

ryo_mutations/basic/
method.rs

1//! Method mutations: AddMethodMutation, RemoveMethodMutation
2
3use ryo_symbol::SymbolId;
4
5use crate::Mutation;
6
7/// Add a method to a struct or enum
8///
9/// New design: Methods are registered directly on the type (e.g., `Struct::method`).
10/// Impl blocks are file-level constructs, not internal entities.
11#[derive(Debug, Clone)]
12pub struct AddMethodMutation {
13    /// SymbolId for the type (Struct or Enum)
14    pub type_id: SymbolId,
15    pub name: String,
16    pub params: Vec<(String, String)>,
17    pub return_type: Option<String>,
18    pub body: String,
19    pub is_pub: bool,
20    pub takes_self: Option<(bool, bool)>, // Some((is_ref, is_mut)) or None
21}
22
23impl AddMethodMutation {
24    pub fn new(type_id: SymbolId, name: impl Into<String>) -> Self {
25        Self {
26            type_id,
27            name: name.into(),
28            params: Vec::new(),
29            return_type: None,
30            body: "todo!()".to_string(),
31            is_pub: false,
32            takes_self: None,
33        }
34    }
35
36    pub fn with_self(mut self) -> Self {
37        self.takes_self = Some((true, false)); // &self
38        self
39    }
40
41    pub fn with_mut_self(mut self) -> Self {
42        self.takes_self = Some((true, true)); // &mut self
43        self
44    }
45
46    pub fn with_owned_self(mut self) -> Self {
47        self.takes_self = Some((false, false)); // self
48        self
49    }
50
51    pub fn with_params(mut self, params: Vec<(String, String)>) -> Self {
52        self.params = params;
53        self
54    }
55
56    pub fn with_return_type(mut self, ty: impl Into<String>) -> Self {
57        self.return_type = Some(ty.into());
58        self
59    }
60
61    pub fn with_body(mut self, body: impl Into<String>) -> Self {
62        self.body = body.into();
63        self
64    }
65
66    pub fn public(mut self) -> Self {
67        self.is_pub = true;
68        self
69    }
70}
71
72impl Mutation for AddMethodMutation {
73    fn describe(&self) -> String {
74        let vis = if self.is_pub { "pub " } else { "" };
75        let self_param = match self.takes_self {
76            Some((true, true)) => "&mut self",
77            Some((true, false)) => "&self",
78            Some((false, _)) => "self",
79            None => "",
80        };
81        let ret = self
82            .return_type
83            .as_ref()
84            .map(|t| format!(" -> {}", t))
85            .unwrap_or_default();
86        format!(
87            "Add {}fn {}({}){}  to type {}",
88            vis, self.name, self_param, ret, self.type_id
89        )
90    }
91
92    fn mutation_type(&self) -> &'static str {
93        "AddMethod"
94    }
95
96    fn box_clone(&self) -> Box<dyn Mutation> {
97        Box::new(self.clone())
98    }
99}
100
101/// Remove a method from a struct or enum
102///
103/// New design: Methods are registered directly on the type (e.g., `Struct::method`).
104#[derive(Debug, Clone)]
105pub struct RemoveMethodMutation {
106    /// SymbolId for the method itself (Type::method)
107    pub method_id: SymbolId,
108}
109
110impl RemoveMethodMutation {
111    pub fn new(method_id: SymbolId) -> Self {
112        Self { method_id }
113    }
114}
115
116impl Mutation for RemoveMethodMutation {
117    fn describe(&self) -> String {
118        format!("Remove method {}", self.method_id)
119    }
120
121    fn mutation_type(&self) -> &'static str {
122        "RemoveMethod"
123    }
124
125    fn box_clone(&self) -> Box<dyn Mutation> {
126        Box::new(self.clone())
127    }
128}