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}