codegen_rs/
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
29impl Module {
30    /// Return a new, blank module
31    pub fn new(name: &str) -> Self {
32        Self {
33            name: name.to_string(),
34            vis: None,
35            docs: None,
36            scope: Scope::new(),
37        }
38    }
39
40    /// Returns a mutable reference to the module's scope.
41    pub fn scope(&mut self) -> &mut Scope {
42        &mut self.scope
43    }
44
45    /// Set the module visibility.
46    pub fn vis(&mut self, vis: &str) -> &mut Self {
47        self.vis = Some(vis.to_string());
48        self
49    }
50
51    /// Import a type into the module's scope.
52    ///
53    /// This results in a new `use` statement bein added to the beginning of the
54    /// module.
55    pub fn import(&mut self, path: &str, ty: &str) -> &mut Self {
56        self.scope.import(path, ty);
57        self
58    }
59
60    /// Push a new module definition, returning a mutable reference to it.
61    ///
62    /// # Panics
63    ///
64    /// Since a module's name must uniquely identify it within the scope in
65    /// which it is defined, pushing a module whose name is already defined
66    /// in this scope will cause this function to panic.
67    ///
68    /// In many cases, the [`get_or_new_module`] function is preferrable, as it
69    /// will return the existing definition instead.
70    ///
71    /// [`get_or_new_module`]: #method.get_or_new_module
72    pub fn new_module(&mut self, name: &str) -> &mut Self {
73        self.scope.new_module(name)
74    }
75
76    /// Returns a reference to a module if it is exists in this scope.
77    pub fn get_module<Q: ?Sized>(&self, name: &Q) -> Option<&Self>
78    where
79        String: PartialEq<Q>,
80    {
81        self.scope.get_module(name)
82    }
83
84    /// Returns a mutable reference to a module if it is exists in this scope.
85    pub fn get_module_mut<Q: ?Sized>(&mut self, name: &Q) -> Option<&mut Self>
86    where
87        String: PartialEq<Q>,
88    {
89        self.scope.get_module_mut(name)
90    }
91
92    /// Returns a mutable reference to a module, creating it if it does
93    /// not exist.
94    pub fn get_or_new_module(&mut self, name: &str) -> &mut Self {
95        self.scope.get_or_new_module(name)
96    }
97
98    /// Push a module definition.
99    ///
100    /// # Panics
101    ///
102    /// Since a module's name must uniquely identify it within the scope in
103    /// which it is defined, pushing a module whose name is already defined
104    /// in this scope will cause this function to panic.
105    ///
106    /// In many cases, the [`get_or_new_module`] function is preferrable, as it will
107    /// return the existing definition instead.
108    ///
109    /// [`get_or_new_module`]: #method.get_or_new_module
110    pub fn push_module(&mut self, item: Self) -> &mut Self {
111        self.scope.push_module(item);
112        self
113    }
114
115    /// Push a new struct definition, returning a mutable reference to it.
116    pub fn new_struct(&mut self, name: &str) -> &mut Struct {
117        self.scope.new_struct(name)
118    }
119
120    /// Push a structure definition
121    pub fn push_struct(&mut self, item: Struct) -> &mut Self {
122        self.scope.push_struct(item);
123        self
124    }
125
126    /// Push a new function definition, returning a mutable reference to it.
127    pub fn new_fn(&mut self, name: &str) -> &mut Function {
128        self.scope.new_fn(name)
129    }
130
131    /// Push a function definition
132    pub fn push_fn(&mut self, item: Function) -> &mut Self {
133        self.scope.push_fn(item);
134        self
135    }
136
137    /// Push a new enum definition, returning a mutable reference to it.
138    pub fn new_enum(&mut self, name: &str) -> &mut Enum {
139        self.scope.new_enum(name)
140    }
141
142    /// Push an enum definition
143    pub fn push_enum(&mut self, item: Enum) -> &mut Self {
144        self.scope.push_enum(item);
145        self
146    }
147
148    /// Push a new `impl` block, returning a mutable reference to it.
149    pub fn new_impl(&mut self, target: &str) -> &mut Impl {
150        self.scope.new_impl(target)
151    }
152
153    /// Push an `impl` block.
154    pub fn push_impl(&mut self, item: Impl) -> &mut Self {
155        self.scope.push_impl(item);
156        self
157    }
158
159    /// Push a trait definition
160    pub fn push_trait(&mut self, item: Trait) -> &mut Self {
161        self.scope.push_trait(item);
162        self
163    }
164
165    /// Formats the module using the given formatter.
166    pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
167        if let Some(ref vis) = self.vis {
168            write!(fmt, "{} ", vis)?;
169        }
170
171        write!(fmt, "mod {}", self.name)?;
172        fmt.block(|fmt| self.scope.fmt(fmt))
173    }
174}