rust_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)]
15#[allow(dead_code)]
16pub struct Module {
17    /// The module's name.
18    pub name: String,
19    /// The module's visibility.
20    vis: Option<String>,
21    /// Module documentation.
22    docs: Option<Docs>,
23    /// Contents of the module.
24    scope: Scope,
25}
26
27impl Module {
28    /// Return a new, blank module.
29    /// 
30    /// # Arguments
31    /// 
32    /// * `name` - The name of the module.
33    /// 
34    /// # Examples
35    /// 
36    /// ```
37    /// use rust_codegen::Module;
38    /// 
39    /// let foo_module = Module::new("Foo");
40    /// ```
41    pub fn new(name: &str) -> Self {
42        Module {
43            name: name.to_string(),
44            vis: None,
45            docs: None,
46            scope: Scope::new(),
47        }
48    }
49
50    /// Returns a mutable reference to the module's scope.
51    /// 
52    /// # Examples
53    /// 
54    /// ```
55    /// use rust_codegen::Module;
56    /// 
57    /// let mut foo_module = Module::new("Foo");
58    /// println!("{:?}", foo_module.scope());
59    /// ```
60    pub fn scope(&mut self) -> &mut Scope {
61        &mut self.scope
62    }
63
64    /// Set the module visibility.
65    /// 
66    /// # Arguments
67    /// 
68    /// * `vis` - The visibility of the module.
69    /// 
70    /// # Examples
71    /// 
72    /// ```
73    /// use rust_codegen::Module;
74    /// 
75    /// let mut foo_module = Module::new("Foo");
76    /// foo_module.vis("pub");
77    /// ```
78    pub fn vis(&mut self, vis: &str) -> &mut Self {
79        self.vis = Some(vis.to_string());
80        self
81    }
82
83    /// Import a type into the module's scope.
84    ///
85    /// This results in a new `use` statement bein added to the beginning of 
86    /// the module.
87    /// 
88    /// # Arguments
89    /// 
90    /// * `path` - The path to the type to import.
91    /// * `ty` - The type to import.
92    /// 
93    /// # Examples
94    /// 
95    /// ```
96    /// use rust_codegen::Module;
97    /// 
98    /// let mut foo_module = Module::new("Foo");
99    /// foo_module.import("rust_codegen", "Module");
100    /// ```
101    pub fn import(&mut self, path: &str, ty: &str) -> &mut Self {
102        self.scope.import(path, ty);
103        self
104    }
105
106    /// Push a new module definition, returning a mutable reference to it.
107    ///
108    /// # Panics
109    ///
110    /// Since a module's name must uniquely identify it within the scope in
111    /// which it is defined, pushing a module whose name is already defined
112    /// in this scope will cause this function to panic.
113    ///
114    /// In many cases, the [`get_or_new_module`] function is preferrable, as it
115    /// will return the existing definition instead.
116    ///
117    /// [`get_or_new_module`]: #method.get_or_new_module
118    /// 
119    /// # Arguments
120    /// 
121    /// * `name` - The name of the module.
122    /// 
123    /// # Examples
124    /// 
125    /// ```
126    /// use rust_codegen::Module;
127    /// 
128    /// let mut foo_module = Module::new("Foo");
129    /// foo_module.new_module("Bar");
130    /// ```
131    pub fn new_module(&mut self, name: &str) -> &mut Module {
132        self.scope.new_module(name)
133    }
134
135    /// Returns a reference to a module if it is exists in this scope.
136    /// 
137    /// # Arguments
138    /// 
139    /// * `name` - The name of the module to get.
140    /// 
141    /// # Examples
142    /// 
143    /// ```
144    /// use rust_codegen::Module;
145    /// 
146    /// let mut foo_module = Module::new("Foo");
147    /// foo_module.new_module("Bar");
148    /// 
149    /// foo_module.get_module("Bar");
150    /// ```
151    pub fn get_module<Q: ?Sized>(&self, name: &Q) -> Option<&Module>
152    where
153        String: PartialEq<Q>,
154    {
155        self.scope.get_module(name)
156    }
157
158    /// Returns a mutable reference to a module if it is exists in this scope.
159    /// 
160    /// # Arguments
161    /// 
162    /// * `name` - The name of the module to get.
163    /// 
164    /// # Examples
165    /// 
166    /// ```
167    /// use rust_codegen::Module;
168    /// 
169    /// let mut foo_module = Module::new("Foo");
170    /// foo_module.new_module("Bar");
171    /// 
172    /// foo_module.get_module("Bar");
173    /// ```
174    pub fn get_module_mut<Q: ?Sized>(&mut self, name: &Q) -> Option<&mut Module>
175    where
176        String: PartialEq<Q>,
177    {
178        self.scope.get_module_mut(name)
179    }
180
181    /// Returns a mutable reference to a module, creating it if it does
182    /// not exist.
183    /// 
184    /// # Arguments
185    /// 
186    /// * `name` - The name of the module to get or create if it doesn't exist.
187    /// 
188    /// # Examples
189    /// 
190    /// ```
191    /// use rust_codegen::Module;
192    /// 
193    /// let mut foo_module = Module::new("Foo");
194    /// foo_module.get_or_new_module("Bar");
195    /// ```
196    pub fn get_or_new_module(&mut self, name: &str) -> &mut Module {
197        self.scope.get_or_new_module(name)
198    }
199
200    /// Push a module definition.
201    ///
202    /// # Panics
203    ///
204    /// Since a module's name must uniquely identify it within the scope in
205    /// which it is defined, pushing a module whose name is already defined
206    /// in this scope will cause this function to panic.
207    ///
208    /// In many cases, the [`get_or_new_module`] function is preferrable, as it will
209    /// return the existing definition instead.
210    ///
211    /// [`get_or_new_module`]: #method.get_or_new_module
212    /// 
213    /// # Arguments
214    /// 
215    /// * `item` - The module to push.
216    /// 
217    /// # Examples
218    /// 
219    /// ```
220    /// use rust_codegen::Module;
221    /// 
222    /// let mut foo_module = Module::new("Foo");
223    /// let mut bar_module = Module::new("Bar");
224    /// 
225    /// foo_module.push_module(bar_module);
226    /// ```
227    pub fn push_module(&mut self, item: Module) -> &mut Self {
228        self.scope.push_module(item);
229        self
230    }
231
232    /// Push a new struct definition, returning a mutable reference to it.
233    /// 
234    /// # Arguments
235    /// 
236    /// * `name` - The name of the struct to push.
237    /// 
238    /// # Examples
239    /// 
240    /// ```
241    /// use rust_codegen::Module;
242    /// 
243    /// let mut foo_module = Module::new("Foo");
244    /// foo_module.new_struct("Bar");
245    /// ```
246    pub fn new_struct(&mut self, name: &str) -> &mut Struct {
247        self.scope.new_struct(name)
248    }
249
250    /// Push a structure definition.
251    /// 
252    /// # Arguments
253    /// 
254    /// * `item` - The struct definition to push.
255    /// 
256    /// # Examples
257    /// 
258    /// ```
259    /// use rust_codegen::{Module,Struct};
260    /// 
261    /// let mut foo_module = Module::new("Foo");
262    /// let mut bar_struct = Struct::new("Bar");
263    /// 
264    /// foo_module.push_struct(bar_struct);
265    /// ```
266    pub fn push_struct(&mut self, item: Struct) -> &mut Self {
267        self.scope.push_struct(item);
268        self
269    }
270
271    /// Push a new function definition, returning a mutable reference to it.
272    /// 
273    /// # Arguments
274    /// 
275    /// * `name` - The name of the function to push.
276    /// 
277    /// # Examples
278    /// 
279    /// ```
280    /// use rust_codegen::Module;
281    /// 
282    /// let mut foo_module = Module::new("Foo");
283    /// foo_module.new_fn("bar_fn");
284    /// ```
285    pub fn new_fn(&mut self, name: &str) -> &mut Function {
286        self.scope.new_fn(name)
287    }
288
289    /// Push a function definition.
290    /// 
291    /// # Arguments
292    /// 
293    /// * `item` - The function definition to push.
294    /// 
295    /// # Examples
296    /// 
297    /// ```
298    /// use rust_codegen::{Function,Module};
299    /// 
300    /// let mut foo_module = Module::new("Foo");
301    /// let mut bar_fn = Function::new("bar_fn");
302    /// 
303    /// foo_module.push_fn(bar_fn);
304    /// ```
305    pub fn push_fn(&mut self, item: Function) -> &mut Self {
306        self.scope.push_fn(item);
307        self
308    }
309
310    /// Push a new enum definition, returning a mutable reference to it.
311    /// 
312    /// # Arguments
313    /// 
314    /// * `name` - The name of the enum.
315    /// 
316    /// # Examples
317    /// 
318    /// ```
319    /// use rust_codegen::Module;
320    /// 
321    /// let mut foo_module = Module::new("Foo");
322    /// foo_module.new_enum("Bar");
323    /// ```
324    pub fn new_enum(&mut self, name: &str) -> &mut Enum {
325        self.scope.new_enum(name)
326    }
327
328    /// Push an enum definition.
329    /// 
330    /// # Arguments
331    /// 
332    /// * `item` - The enum definition to push.
333    /// 
334    /// # Examples
335    /// 
336    /// ```
337    /// use rust_codegen::{Enum,Module};
338    /// 
339    /// let mut foo_module = Module::new("Foo");
340    /// let mut bar_enum = Enum::new("Bar");
341    /// 
342    /// foo_module.push_enum(bar_enum);
343    /// ```
344    pub fn push_enum(&mut self, item: Enum) -> &mut Self {
345        self.scope.push_enum(item);
346        self
347    }
348
349    /// Push a new `impl` block, returning a mutable reference to it.
350    /// 
351    /// # Arguments
352    /// 
353    /// * `target` - The impl block to push.
354    /// 
355    /// # Examples
356    /// 
357    /// ```
358    /// use rust_codegen::Module;
359    /// 
360    /// let mut foo_module = Module::new("Foo");
361    /// foo_module.new_impl("Bar");
362    /// ```
363    pub fn new_impl(&mut self, target: &str) -> &mut Impl {
364        self.scope.new_impl(target)
365    }
366
367    /// Push an `impl` block.
368    /// 
369    /// # Arguments
370    /// 
371    /// * `item` - The impl definition to push.
372    /// 
373    /// # Examples
374    /// 
375    /// ```
376    /// use rust_codegen::{Impl,Module};
377    /// 
378    /// let mut foo_module = Module::new("Foo");
379    /// let mut bar_impl = Impl::new("Bar");
380    /// 
381    /// foo_module.push_impl(bar_impl);
382    /// ```
383    pub fn push_impl(&mut self, item: Impl) -> &mut Self {
384        self.scope.push_impl(item);
385        self
386    }
387
388    /// Push a trait definition.
389    /// 
390    /// # Arguments
391    /// 
392    /// * `item` - The trait to push.
393    /// 
394    /// # Examples
395    /// 
396    /// ```
397    /// use rust_codegen::{Module,Trait};
398    /// 
399    /// let mut foo_module = Module::new("Foo");
400    /// let mut bar_trait = Trait::new("Bar");
401    /// 
402    /// foo_module.push_trait(bar_trait);
403    /// ```
404    pub fn push_trait(&mut self, item: Trait) -> &mut Self {
405        self.scope.push_trait(item);
406        self
407    }
408
409    /// Formats the module using the given formatter.
410    /// 
411    /// # Arguments
412    /// 
413    /// * `fmt` - The formatter to use.
414    /// 
415    /// # Examples
416    /// 
417    /// ```
418    /// use rust_codegen::*;
419    /// 
420    /// let mut dest = String::new();
421    /// let mut fmt = Formatter::new(&mut dest);
422    /// 
423    /// let mut foo_module = Module::new("Foo");
424    /// foo_module.fmt(&mut fmt);
425    /// ```
426    pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
427        if let Some(ref vis) = self.vis {
428            write!(fmt, "{} ", vis)?;
429        }
430
431        write!(fmt, "mod {}", self.name)?;
432        fmt.block(|fmt| self.scope.fmt(fmt))
433    }
434}