Skip to main content

virtue_next/generate/
generate_mod.rs

1use super::{GenEnum, GenStruct, Impl, Parent, StreamBuilder};
2use crate::{
3    Result,
4    parse::Visibility,
5    prelude::{Delimiter, Ident, Span},
6};
7
8/// Builder for generating a module with its contents.
9pub struct GenerateMod<'a, P: Parent> {
10    parent: &'a mut P,
11    name: Ident,
12    uses: Vec<StreamBuilder>,
13    vis: Visibility,
14    content: StreamBuilder,
15}
16
17impl<'a, P: Parent> GenerateMod<'a, P> {
18    pub(crate) fn new(parent: &'a mut P, name: impl Into<String>) -> Self {
19        Self {
20            parent,
21            name: Ident::new(name.into().as_str(), Span::call_site()),
22            uses: Vec::new(),
23            vis: Visibility::Default,
24            content: StreamBuilder::new(),
25        }
26    }
27
28    /// Add a `use ...;` to the current mod
29    ///
30    /// `generator.impl_mod("foo").add_use("bar")` will generate:
31    ///
32    /// ```ignore
33    /// mod foo {
34    ///     use bar;
35    /// }
36    /// ```
37    ///
38    /// This is especially useful with `.add_use("super::*");`, which will pull all parent imports into scope
39    pub fn add_use(&mut self, r#use: impl AsRef<str>) -> Result {
40        let mut builder = StreamBuilder::new();
41        builder.ident_str("use").push_parsed(r#use)?.punct(';');
42        self.uses.push(builder);
43        Ok(())
44    }
45
46    /// Generate a struct with the given name. See [`GenStruct`] for more info.
47    pub fn generate_struct(&mut self, name: impl Into<String>) -> GenStruct<'_, Self> {
48        GenStruct::new(self, name)
49    }
50
51    /// Generate an enum with the given name. See [`GenEnum`] for more info.
52    pub fn generate_enum(&mut self, name: impl Into<String>) -> GenEnum<'_, Self> {
53        GenEnum::new(self, name)
54    }
55
56    /// Generate an `impl <name>` implementation. See [`Impl`] for more information.
57    pub fn r#impl(&mut self, name: impl Into<String>) -> Impl<'_, Self> {
58        Impl::new(self, name)
59    }
60
61    /// Generate an `impl <name>` implementation. See [`Impl`] for more information.
62    ///
63    /// Alias for [`impl`] which doesn't need a `r#` prefix.
64    ///
65    /// [`impl`]: #method.impl
66    pub fn generate_impl(&mut self, name: impl Into<String>) -> Impl<'_, Self> {
67        Impl::new(self, name)
68    }
69}
70
71impl<'a, P: Parent> Drop for GenerateMod<'a, P> {
72    fn drop(&mut self) {
73        let mut builder = StreamBuilder::new();
74        if self.vis == Visibility::Pub {
75            builder.ident_str("pub");
76        }
77        builder
78            .ident_str("mod")
79            .ident(self.name.clone())
80            .group(Delimiter::Brace, |group| {
81                for r#use in std::mem::take(&mut self.uses) {
82                    group.append(r#use);
83                }
84                group.append(std::mem::take(&mut self.content));
85                Ok(())
86            })
87            .unwrap();
88
89        self.parent.append(builder);
90    }
91}
92
93impl<P: Parent> Parent for GenerateMod<'_, P> {
94    fn append(&mut self, builder: StreamBuilder) {
95        self.content.append(builder);
96    }
97
98    fn name(&self) -> &crate::prelude::Ident {
99        &self.name
100    }
101
102    fn generics(&self) -> Option<&crate::parse::Generics> {
103        None
104    }
105
106    fn generic_constraints(&self) -> Option<&crate::parse::GenericConstraints> {
107        None
108    }
109}