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(¶meter.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}