php_codegen/
property.rs

1use crate::attribute::AttributeGroup;
2use crate::body::Body;
3use crate::comment::Document;
4use crate::data_type::DataType;
5use crate::literal::Value;
6use crate::modifiers::Modifier;
7use crate::modifiers::VisibilityModifier;
8use crate::Generator;
9use crate::Indentation;
10
11#[derive(Debug)]
12pub struct PropertySetHookParameter {
13    pub data_type: Option<DataType>,
14    pub name: String,
15}
16
17#[derive(Debug)]
18pub enum PropertyHook {
19    Get(bool, Body),
20    Set(Option<PropertySetHookParameter>, Body),
21}
22
23#[derive(Debug)]
24pub struct Property {
25    pub documentation: Option<Document>,
26    pub attributes: Vec<AttributeGroup>,
27    pub visibility: Option<VisibilityModifier>,
28    pub modifiers: Vec<Modifier>,
29    pub data_type: Option<DataType>,
30    pub name: String,
31    pub default: Option<Value>,
32    pub hooks: Vec<PropertyHook>,
33}
34
35impl PropertySetHookParameter {
36    pub fn new<T: ToString>(name: T) -> Self {
37        Self {
38            name: name.to_string(),
39            data_type: None,
40        }
41    }
42
43    pub fn typed(mut self, data_type: DataType) -> Self {
44        self.data_type = Some(data_type);
45
46        self
47    }
48}
49
50impl Property {
51    pub fn new<T: ToString>(name: T) -> Self {
52        Self {
53            name: name.to_string(),
54            data_type: None,
55            default: None,
56            modifiers: vec![],
57            attributes: vec![],
58            visibility: None,
59            documentation: None,
60            hooks: vec![],
61        }
62    }
63
64    pub fn document(mut self, documentation: Document) -> Self {
65        self.documentation = Some(documentation);
66
67        self
68    }
69
70    pub fn attributes(mut self, attributes: AttributeGroup) -> Self {
71        self.attributes.push(attributes);
72
73        self
74    }
75
76    pub fn typed(mut self, data_type: DataType) -> Self {
77        self.data_type = Some(data_type);
78
79        self
80    }
81
82    pub fn default<T: Into<Value>>(mut self, default: T) -> Self {
83        self.default = Some(default.into());
84
85        self
86    }
87
88    pub fn modifier(mut self, modifier: Modifier) -> Self {
89        self.modifiers.push(modifier);
90
91        self
92    }
93
94    pub fn public(mut self) -> Self {
95        self.visibility = Some(VisibilityModifier::Public);
96
97        self
98    }
99
100    pub fn protected(mut self) -> Self {
101        self.visibility = Some(VisibilityModifier::Protected);
102
103        self
104    }
105
106    pub fn private(mut self) -> Self {
107        self.visibility = Some(VisibilityModifier::Private);
108
109        self
110    }
111
112    pub fn visibility(mut self, visibility: VisibilityModifier) -> Self {
113        self.visibility = Some(visibility);
114
115        self
116    }
117
118    pub fn hook(mut self, hook: PropertyHook) -> Self {
119        self.hooks.push(hook);
120
121        self
122    }
123}
124
125impl Generator for PropertySetHookParameter {
126    fn generate(&self, indentation: Indentation, level: usize) -> String {
127        let mut code = String::new();
128
129        if let Some(data_type) = &self.data_type {
130            code.push_str(&format!("{} ", data_type.generate(indentation, level)));
131        }
132
133        code.push_str(&self.name);
134
135        code
136    }
137}
138
139impl Generator for PropertyHook {
140    fn generate(&self, indentation: Indentation, level: usize) -> String {
141        match self {
142            PropertyHook::Get(by_reference, body) => {
143                let mut code = String::new();
144
145                code.push_str(&indentation.value(level + 1));
146                if *by_reference {
147                    code.push_str("&get");
148                } else {
149                    code.push_str("get");
150                }
151
152                code.push_str(&body.generate(indentation, level + 1));
153
154                code
155            }
156            PropertyHook::Set(parameter, body) => {
157                let mut code = String::new();
158
159                code.push_str(&indentation.value(level + 1));
160                code.push_str("set");
161
162                if let Some(parameter) = parameter {
163                    code.push_str(" (");
164                    code.push_str(&parameter.generate(indentation, level + 1));
165                    code.push(')');
166                }
167
168                code.push_str(&body.generate(indentation, level + 1));
169
170                code
171            }
172        }
173    }
174}
175
176impl Generator for Vec<PropertyHook> {
177    fn generate(&self, indentation: Indentation, level: usize) -> String {
178        if self.is_empty() {
179            return String::from(";");
180        }
181
182        let hooks = self
183            .iter()
184            .map(|hook| hook.generate(indentation, level))
185            .collect::<Vec<String>>()
186            .join("");
187
188        format!(" {{\n{}{}}}", hooks, indentation.value(level))
189    }
190}
191
192impl Generator for Property {
193    fn generate(&self, indentation: Indentation, level: usize) -> String {
194        let mut code = indentation.value(level);
195
196        if let Some(document) = &self.documentation {
197            code.push_str(&document.generate(indentation, level));
198        }
199
200        if !self.attributes.is_empty() {
201            code.push_str(
202                &self
203                    .attributes
204                    .iter()
205                    .map(|attributes| attributes.generate(indentation, level))
206                    .collect::<Vec<String>>()
207                    .join("\n"),
208            );
209
210            code.push('\n');
211        }
212
213        if let Some(visibility) = &self.visibility {
214            code.push_str(&format!("{} ", visibility.generate(indentation, level)));
215        }
216
217        for modifier in &self.modifiers {
218            code.push_str(&format!("{} ", modifier.generate(indentation, level)));
219        }
220
221        if let Some(data_type) = &self.data_type {
222            code.push_str(&format!("{} ", data_type.generate(indentation, level)));
223        }
224
225        code.push_str(&format!("${}", &self.name));
226
227        if let Some(default) = &self.default {
228            code.push_str(&format!(" = {}", default.generate(indentation, level)));
229        }
230
231        code.push_str(&self.hooks.generate(indentation, level));
232
233        code
234    }
235}
236
237impl Generator for Vec<Property> {
238    fn generate(&self, indentation: Indentation, level: usize) -> String {
239        let mut code = String::new();
240        if self.is_empty() {
241            return code;
242        }
243
244        for property in self.iter() {
245            code.push_str(property.generate(indentation, level).as_str());
246            code.push('\n');
247        }
248
249        code
250    }
251}