codegen/
module.rs

1use std::fmt::{self, Write};
2
3use crate::docs::Docs;
4use crate::formatter::Formatter;
5use crate::function::Function;
6use crate::scope::Scope;
7
8use crate::r#enum::Enum;
9use crate::r#impl::Impl;
10use crate::r#struct::Struct;
11use crate::r#trait::Trait;
12
13/// Defines a module.
14#[derive(Debug, Clone)]
15pub struct Module {
16    /// Module name
17    pub name: String,
18
19    /// Visibility
20    vis: Option<String>,
21
22    /// Module documentation
23    docs: Option<Docs>,
24
25    /// Contents of the module
26    scope: Scope,
27
28    /// Module attributes, e.g., `#[allow(unused_imports)]`.
29    attributes: Vec<String>,
30}
31
32impl Module {
33    /// Return a new, blank module
34    pub fn new(name: &str) -> Self {
35        Module {
36            name: name.to_string(),
37            vis: None,
38            docs: None,
39            scope: Scope::new(),
40            attributes: Vec::new(),
41        }
42    }
43
44    /// Returns a mutable reference to the module's scope.
45    pub fn scope(&mut self) -> &mut Scope {
46        &mut self.scope
47    }
48
49    /// Set the module visibility.
50    pub fn vis(&mut self, vis: &str) -> &mut Self {
51        self.vis = Some(vis.to_string());
52        self
53    }
54
55    /// Import a type into the module's scope.
56    ///
57    /// This results in a new `use` statement bein added to the beginning of the
58    /// module.
59    pub fn import(&mut self, path: &str, ty: &str) -> &mut Self {
60        self.scope.import(path, ty);
61        self
62    }
63
64    /// Add an attribute to the module.
65    pub fn attr(&mut self, attribute: impl Into<String>) -> &mut Self {
66        self.attributes.push(attribute.into());
67        self
68    }
69
70    /// Push a new module definition, returning a mutable reference to it.
71    ///
72    /// # Panics
73    ///
74    /// Since a module's name must uniquely identify it within the scope in
75    /// which it is defined, pushing a module whose name is already defined
76    /// in this scope will cause this function to panic.
77    ///
78    /// In many cases, the [`get_or_new_module`] function is preferrable, as it
79    /// will return the existing definition instead.
80    ///
81    /// [`get_or_new_module`]: #method.get_or_new_module
82    pub fn new_module(&mut self, name: &str) -> &mut Module {
83        self.scope.new_module(name)
84    }
85
86    /// Returns a reference to a module if it is exists in this scope.
87    pub fn get_module<Q: ?Sized>(&self, name: &Q) -> Option<&Module>
88    where
89        String: PartialEq<Q>,
90    {
91        self.scope.get_module(name)
92    }
93
94    /// Returns a mutable reference to a module if it is exists in this scope.
95    pub fn get_module_mut<Q: ?Sized>(&mut self, name: &Q) -> Option<&mut Module>
96    where
97        String: PartialEq<Q>,
98    {
99        self.scope.get_module_mut(name)
100    }
101
102    /// Returns a mutable reference to a module, creating it if it does
103    /// not exist.
104    pub fn get_or_new_module(&mut self, name: &str) -> &mut Module {
105        self.scope.get_or_new_module(name)
106    }
107
108    /// Push a module definition.
109    ///
110    /// # Panics
111    ///
112    /// Since a module's name must uniquely identify it within the scope in
113    /// which it is defined, pushing a module whose name is already defined
114    /// in this scope will cause this function to panic.
115    ///
116    /// In many cases, the [`get_or_new_module`] function is preferrable, as it will
117    /// return the existing definition instead.
118    ///
119    /// [`get_or_new_module`]: #method.get_or_new_module
120    pub fn push_module(&mut self, item: Module) -> &mut Self {
121        self.scope.push_module(item);
122        self
123    }
124
125    /// Push a new struct definition, returning a mutable reference to it.
126    pub fn new_struct(&mut self, name: &str) -> &mut Struct {
127        self.scope.new_struct(name)
128    }
129
130    /// Push a structure definition
131    pub fn push_struct(&mut self, item: Struct) -> &mut Self {
132        self.scope.push_struct(item);
133        self
134    }
135
136    /// Push a new function definition, returning a mutable reference to it.
137    pub fn new_fn(&mut self, name: &str) -> &mut Function {
138        self.scope.new_fn(name)
139    }
140
141    /// Push a function definition
142    pub fn push_fn(&mut self, item: Function) -> &mut Self {
143        self.scope.push_fn(item);
144        self
145    }
146
147    /// Push a new enum definition, returning a mutable reference to it.
148    pub fn new_enum(&mut self, name: &str) -> &mut Enum {
149        self.scope.new_enum(name)
150    }
151
152    /// Push an enum definition
153    pub fn push_enum(&mut self, item: Enum) -> &mut Self {
154        self.scope.push_enum(item);
155        self
156    }
157
158    /// Push a new `impl` block, returning a mutable reference to it.
159    pub fn new_impl(&mut self, target: &str) -> &mut Impl {
160        self.scope.new_impl(target)
161    }
162
163    /// Push an `impl` block.
164    pub fn push_impl(&mut self, item: Impl) -> &mut Self {
165        self.scope.push_impl(item);
166        self
167    }
168
169    /// Push a new trait
170    pub fn new_trait(&mut self, name: impl Into<String>) -> &mut Trait {
171        self.scope.new_trait(name)
172    }
173
174    /// Push a trait definition
175    pub fn push_trait(&mut self, item: Trait) -> &mut Self {
176        self.scope.push_trait(item);
177        self
178    }
179
180    /// Formats the module using the given formatter.
181    pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
182        for attr in &self.attributes {
183            writeln!(fmt, "#[{}] ", attr)?;
184        }
185
186        if let Some(ref vis) = self.vis {
187            write!(fmt, "{} ", vis)?;
188        }
189
190        write!(fmt, "mod {}", self.name)?;
191        fmt.block(|fmt| self.scope.fmt(fmt))
192    }
193}