virtue_next/generate/gen_struct.rs
1use super::{
2 AttributeContainer, Field, FieldBuilder, Impl, ImplFor, Parent, Path, StreamBuilder,
3 StringOrIdent,
4};
5use crate::Result;
6use crate::parse::{Generic, Generics, Visibility};
7use crate::prelude::{Delimiter, Ident, Span, TokenStream};
8
9/// Builder to generate a struct.
10/// Defaults to a struct with named fields `struct <Name> { <field>: <ty>, ... }`
11pub struct GenStruct<'a, P: Parent> {
12 parent: &'a mut P,
13 name: Ident,
14 visibility: Visibility,
15 generics: Option<Generics>,
16 fields: Vec<Field>,
17 derives: Vec<Path>,
18 attributes: Vec<StreamBuilder>,
19 additional: Vec<StreamBuilder>,
20 struct_type: StructType,
21}
22
23impl<'a, P: Parent> GenStruct<'a, P> {
24 pub(crate) fn new(parent: &'a mut P, name: impl Into<String>) -> Self {
25 Self {
26 parent,
27 name: Ident::new(name.into().as_str(), Span::call_site()),
28 visibility: Visibility::Default,
29 generics: None,
30 fields: Vec::new(),
31 derives: Vec::new(),
32 attributes: Vec::new(),
33 additional: Vec::new(),
34 struct_type: StructType::Named,
35 }
36 }
37
38 /// Make the struct a zero-sized type (no fields)
39 ///
40 /// Any fields will be ignored
41 ///
42 /// ```
43 /// # use virtue::prelude::Generator;
44 /// # let mut generator = Generator::with_name("Fooz");
45 /// generator
46 /// .generate_struct("Foo")
47 /// .make_zst()
48 /// .add_field("bar", "u16")
49 /// .add_field("baz", "String");
50 /// # generator.assert_eq("struct Foo ;");
51 /// # Ok::<_, virtue::Error>(())
52 /// ```
53 ///
54 /// Generates:
55 /// ```
56 /// struct Foo;
57 /// ```
58 pub fn make_zst(&mut self) -> &mut Self {
59 self.struct_type = StructType::Zst;
60 self
61 }
62
63 /// Make the struct fields unnamed
64 ///
65 /// The names of any field will be ignored
66 ///
67 /// ```
68 /// # use virtue::prelude::Generator;
69 /// # let mut generator = Generator::with_name("Fooz");
70 /// generator
71 /// .generate_struct("Foo")
72 /// .make_tuple()
73 /// .add_field("bar", "u16")
74 /// .add_field("baz", "String");
75 /// # generator.assert_eq("struct Foo (u16 , String ,) ;");
76 /// # Ok::<_, virtue::Error>(())
77 /// ```
78 ///
79 /// Generates:
80 /// ```
81 /// struct Foo(u16, String);
82 /// ```
83 pub fn make_tuple(&mut self) -> &mut Self {
84 self.struct_type = StructType::Unnamed;
85 self
86 }
87
88 /// Make the struct `pub`. By default the struct will have no visibility modifier and will only be visible in the current scope.
89 pub fn make_pub(&mut self) -> &mut Self {
90 self.visibility = Visibility::Pub;
91 self
92 }
93
94 /// Inherit the generic parameters of the parent type.
95 ///
96 /// ```
97 /// # use virtue::prelude::Generator;
98 /// # let mut generator = Generator::with_name("Bar").with_lifetime("a");
99 /// // given a derive on struct Bar<'a>
100 /// generator
101 /// .generate_struct("Foo")
102 /// .inherit_generics()
103 /// .add_field("bar", "&'a str");
104 /// # generator.assert_eq("struct Foo < 'a > { bar : &'a str , }");
105 /// # Ok::<_, virtue::Error>(())
106 /// ```
107 ///
108 /// Generates:
109 /// ```ignore
110 /// // given a derive on struct Bar<'a>
111 /// struct Foo<'a> {
112 /// bar: &'a str
113 /// }
114 /// ```
115 pub fn inherit_generics(&mut self) -> &mut Self {
116 self.generics = self.parent.generics().cloned();
117 self
118 }
119
120 /// Append generic parameters to the type.
121 ///
122 /// ```
123 /// # use virtue::prelude::Generator;
124 /// # use virtue::parse::{Generic, Lifetime};
125 /// # use proc_macro2::{Ident, Span};
126 /// # let mut generator = Generator::with_name("Bar").with_lifetime("a");
127 /// generator
128 /// .generate_struct("Foo")
129 /// .with_generics([Lifetime { ident: Ident::new("a", Span::call_site()), constraint: vec![] }.into()])
130 /// .add_field("bar", "&'a str");
131 /// # generator.assert_eq("struct Foo < 'a > { bar : &'a str , }");
132 /// # Ok::<_, virtue::Error>(())
133 /// ```
134 ///
135 /// Generates:
136 /// ```ignore
137 /// struct Foo<'a> {
138 /// bar: &'a str
139 /// }
140 /// ```
141 pub fn with_generics(&mut self, generics: impl IntoIterator<Item = Generic>) -> &mut Self {
142 self.generics
143 .get_or_insert_with(|| Generics(Vec::new()))
144 .extend(generics);
145 self
146 }
147
148 /// Add a generic parameter to the type.
149 ///
150 /// ```
151 /// # use virtue::prelude::Generator;
152 /// # use virtue::parse::{Generic, Lifetime};
153 /// # use proc_macro2::{Ident, Span};
154 /// # let mut generator = Generator::with_name("Bar").with_lifetime("a");
155 /// generator
156 /// .generate_struct("Foo")
157 /// .with_generic(Lifetime { ident: Ident::new("a", Span::call_site()), constraint: vec![] }.into())
158 /// .add_field("bar", "&'a str");
159 /// # generator.assert_eq("struct Foo < 'a > { bar : &'a str , }");
160 /// # Ok::<_, virtue::Error>(())
161 /// ```
162 ///
163 /// Generates:
164 /// ```ignore
165 /// struct Foo<'a> {
166 /// bar: &'a str
167 /// }
168 /// ```
169 pub fn with_generic(&mut self, generic: Generic) -> &mut Self {
170 self.generics
171 .get_or_insert_with(|| Generics(Vec::new()))
172 .push(generic);
173 self
174 }
175
176 /// Add a derive macro to the struct.
177 ///
178 /// ```
179 /// # use virtue::prelude::Generator;
180 /// # use virtue::generate::Path;
181 /// # let mut generator = Generator::with_name("Bar");
182 /// generator
183 /// .generate_struct("Foo")
184 /// .with_derive("Clone")
185 /// .with_derive("Default")
186 /// .with_derive(Path::from_iter(vec!["serde", "Deserialize"]));
187 /// # generator.assert_eq("# [derive (Clone , Default , serde ::Deserialize)] struct Foo { }");
188 /// # Ok::<_, virtue::Error>(())
189 /// ```
190 ///
191 /// Generates:
192 /// ```ignore
193 /// #[derive(Clone, Default, serde::Deserialize)]
194 /// struct Foo { }
195 /// ```
196 pub fn with_derive(&mut self, derive: impl Into<Path>) -> &mut Self {
197 AttributeContainer::with_derive(self, derive)
198 }
199
200 /// Add derive macros to the struct.
201 ///
202 /// ```
203 /// # use virtue::prelude::Generator;
204 /// # use virtue::generate::Path;
205 /// # let mut generator = Generator::with_name("Bar");
206 /// generator
207 /// .generate_struct("Foo")
208 /// .with_derives([
209 /// "Clone".into(),
210 /// "Default".into(),
211 /// Path::from_iter(vec!["serde", "Deserialize"]),
212 /// ]);
213 /// # generator.assert_eq("# [derive (Clone , Default , serde ::Deserialize)] struct Foo { }");
214 /// # Ok::<_, virtue::Error>(())
215 /// ```
216 ///
217 /// Generates:
218 /// ```ignore
219 /// #[derive(Clone, Default, serde::Deserialize)]
220 /// struct Foo { }
221 /// ```
222 pub fn with_derives<T: Into<Path>>(
223 &mut self,
224 derives: impl IntoIterator<Item = T>,
225 ) -> &mut Self {
226 AttributeContainer::with_derives(self, derives)
227 }
228
229 /// Add an attribute to the struct. For `#[derive(...)]`, use [`with_derive`](Self::with_derive)
230 /// instead.
231 ///
232 /// ```
233 /// # use virtue::prelude::Generator;
234 /// # let mut generator = Generator::with_name("Bar");
235 /// generator
236 /// .generate_struct("Foo")
237 /// .with_attribute("serde", |b| {
238 /// b.push_parsed("(rename_all = \"camelCase\")")?;
239 /// Ok(())
240 /// })?;
241 /// # generator.assert_eq("# [serde (rename_all = \"camelCase\")] struct Foo { }");
242 /// # Ok::<_, virtue::Error>(())
243 /// ```
244 ///
245 /// Generates:
246 /// ```ignore
247 /// #[serde(rename_all = "camelCase")]
248 /// struct Foo { }
249 /// ```
250 pub fn with_attribute(
251 &mut self,
252 name: impl AsRef<str>,
253 value: impl FnOnce(&mut StreamBuilder) -> Result,
254 ) -> Result<&mut Self> {
255 AttributeContainer::with_attribute(self, name, value)
256 }
257
258 /// Add a parsed attribute to the struct. For `#[derive(...)]`, use [`with_derive`](Self::with_derive)
259 /// instead.
260 ///
261 /// ```
262 /// # use virtue::prelude::Generator;
263 /// # let mut generator = Generator::with_name("Bar");
264 /// generator
265 /// .generate_struct("Foo")
266 /// .with_parsed_attribute("serde(rename_all = \"camelCase\")")?;
267 /// # generator.assert_eq("# [serde (rename_all = \"camelCase\")] struct Foo { }");
268 /// # Ok::<_, virtue::Error>(())
269 /// ```
270 ///
271 /// Generates:
272 /// ```ignore
273 /// #[serde(rename_all = "camelCase")]
274 /// struct Foo { }
275 /// ```
276 pub fn with_parsed_attribute(&mut self, attribute: impl AsRef<str>) -> Result<&mut Self> {
277 AttributeContainer::with_parsed_attribute(self, attribute)
278 }
279
280 /// Add a token stream as an attribute to the struct. For `#[derive(...)]`, use
281 /// [`with_derive`](Self::with_derive) instead.
282 ///
283 /// ```
284 /// # use virtue::prelude::{Generator, TokenStream};
285 /// # use std::str::FromStr;
286 /// # let mut generator = Generator::with_name("Bar");
287 ///
288 /// let attribute = "serde(rename_all = \"camelCase\")".parse::<TokenStream>().unwrap();
289 /// generator
290 /// .generate_struct("Foo")
291 /// .with_attribute_stream(attribute);
292 /// # generator.assert_eq("# [serde (rename_all = \"camelCase\")] struct Foo { }");
293 /// # Ok::<_, virtue::Error>(())
294 /// ```
295 ///
296 /// Generates:
297 /// ```ignore
298 /// #[serde(rename_all = "camelCase")]
299 /// struct Foo { }
300 /// ```
301 pub fn with_attribute_stream(&mut self, attribute: impl Into<TokenStream>) -> &mut Self {
302 AttributeContainer::with_attribute_stream(self, attribute)
303 }
304
305 /// Add a field to the struct.
306 ///
307 /// Names are ignored when the Struct's fields are unnamed
308 ///
309 /// ```
310 /// # use virtue::prelude::Generator;
311 /// # let mut generator = Generator::with_name("Fooz");
312 /// generator
313 /// .generate_struct("Foo")
314 /// .add_field("bar", "u16")
315 /// .add_field("baz", "String");
316 /// # generator.assert_eq("struct Foo { bar : u16 , baz : String , }");
317 /// # Ok::<_, virtue::Error>(())
318 /// ```
319 ///
320 /// Generates:
321 /// ```
322 /// struct Foo {
323 /// bar: u16,
324 /// baz: String,
325 /// };
326 /// ```
327 pub fn add_field(
328 &mut self,
329 name: impl Into<String>,
330 ty: impl Into<String>,
331 ) -> FieldBuilder<'_, Self> {
332 let mut fields = FieldBuilder::from(&mut self.fields);
333 fields.add_field(name, ty);
334 fields
335 }
336
337 /// Add an `impl <name> for <struct>`
338 pub fn impl_for(&mut self, name: impl Into<StringOrIdent>) -> ImplFor<'_, Self> {
339 ImplFor::new(self, name.into(), None)
340 }
341
342 /// Generate an `impl <name>` implementation. See [`Impl`] for more information.
343 pub fn r#impl(&mut self) -> Impl<'_, Self> {
344 Impl::with_parent_name(self)
345 }
346
347 /// Generate an `impl <name>` implementation. See [`Impl`] for more information.
348 ///
349 /// Alias for [`impl`] which doesn't need a `r#` prefix.
350 ///
351 /// [`impl`]: #method.impl
352 pub fn generate_impl(&mut self) -> Impl<'_, Self> {
353 Impl::with_parent_name(self)
354 }
355}
356
357impl<P: Parent> AttributeContainer for GenStruct<'_, P> {
358 fn derives(&mut self) -> &mut Vec<Path> {
359 &mut self.derives
360 }
361
362 fn attributes(&mut self) -> &mut Vec<StreamBuilder> {
363 &mut self.attributes
364 }
365}
366
367impl<'a, P: Parent> Parent for GenStruct<'a, P> {
368 fn append(&mut self, builder: StreamBuilder) {
369 self.additional.push(builder);
370 }
371
372 fn name(&self) -> &Ident {
373 &self.name
374 }
375
376 fn generics(&self) -> Option<&Generics> {
377 self.generics.as_ref()
378 }
379
380 fn generic_constraints(&self) -> Option<&crate::parse::GenericConstraints> {
381 None
382 }
383}
384
385impl<'a, P: Parent> Drop for GenStruct<'a, P> {
386 fn drop(&mut self) {
387 use std::mem::take;
388 let mut builder = StreamBuilder::new();
389
390 self.build_derives(&mut builder)
391 .build_attributes(&mut builder);
392
393 if self.visibility == Visibility::Pub {
394 builder.ident_str("pub");
395 }
396 builder.ident_str("struct").ident(self.name.clone()).append(
397 self.generics()
398 .map(Generics::impl_generics)
399 .unwrap_or_default(),
400 );
401
402 match self.struct_type {
403 StructType::Named => builder
404 .group(Delimiter::Brace, |b| {
405 for field in self.fields.iter_mut() {
406 field.build_attributes(b);
407 if field.vis == Visibility::Pub {
408 b.ident_str("pub");
409 }
410 b.ident_str(&field.name)
411 .punct(':')
412 .push_parsed(&field.ty)?
413 .punct(',');
414 }
415 Ok(())
416 })
417 .expect("Could not build struct"),
418 StructType::Unnamed => builder
419 .group(Delimiter::Parenthesis, |b| {
420 for field in self.fields.iter_mut() {
421 field.build_attributes(b);
422 if field.vis == Visibility::Pub {
423 b.ident_str("pub");
424 }
425 b.push_parsed(&field.ty)?.punct(',');
426 }
427 Ok(())
428 })
429 .expect("Could not build struct")
430 .punct(';'),
431 StructType::Zst => builder.punct(';'),
432 };
433
434 for additional in take(&mut self.additional) {
435 builder.append(additional);
436 }
437 self.parent.append(builder);
438 }
439}
440
441enum StructType {
442 Named,
443 Unnamed,
444 Zst,
445}