1use std::fmt::{self, Write};
2
3use indexmap::IndexMap;
4
5use crate::docs::Docs;
6use crate::formatter::Formatter;
7use crate::function::Function;
8use crate::import::Import;
9use crate::item::Item;
10use crate::module::Module;
11
12use crate::r#enum::Enum;
13use crate::r#impl::Impl;
14use crate::r#struct::Struct;
15use crate::r#trait::Trait;
16
17#[derive(Debug, Clone)]
21pub struct Scope {
22 docs: Option<Docs>,
24
25 imports: IndexMap<String, IndexMap<String, Import>>,
27
28 items: Vec<Item>,
30}
31
32impl Scope {
33 pub fn new() -> Self {
35 Self {
36 docs: None,
37 imports: IndexMap::new(),
38 items: vec![],
39 }
40 }
41
42 pub fn import(&mut self, path: &str, ty: &str) -> &mut Import {
47 let ty = ty.split("::").next().unwrap_or(ty);
50 self.imports
51 .entry(path.to_string())
52 .or_insert(IndexMap::new())
53 .entry(ty.to_string())
54 .or_insert_with(|| Import::new(path, ty))
55 }
56
57 pub fn new_module(&mut self, name: &str) -> &mut Module {
70 self.push_module(Module::new(name));
71
72 match self.items.last_mut().unwrap() {
73 Item::Module(v) => v,
74 _ => unreachable!(),
75 }
76 }
77
78 pub fn get_module_mut<Q: ?Sized>(&mut self, name: &Q) -> Option<&mut Module>
80 where
81 String: PartialEq<Q>,
82 {
83 self.items
84 .iter_mut()
85 .filter_map(|item| match item {
86 Item::Module(ref mut module) if module.name == *name => Some(module),
87 _ => None,
88 })
89 .next()
90 }
91
92 pub fn get_module<Q: ?Sized>(&self, name: &Q) -> Option<&Module>
94 where
95 String: PartialEq<Q>,
96 {
97 self.items
98 .iter()
99 .filter_map(|item| match item {
100 Item::Module(module) if module.name == *name => Some(module),
101 _ => None,
102 })
103 .next()
104 }
105
106 pub fn get_or_new_module(&mut self, name: &str) -> &mut Module {
109 if self.get_module(name).is_some() {
110 self.get_module_mut(name).unwrap()
111 } else {
112 self.new_module(name)
113 }
114 }
115
116 pub fn push_module(&mut self, item: Module) -> &mut Self {
129 assert!(self.get_module(&item.name).is_none());
130 self.items.push(Item::Module(item));
131 self
132 }
133
134 pub fn new_struct(&mut self, name: &str) -> &mut Struct {
136 self.push_struct(Struct::new(name));
137
138 match self.items.last_mut().unwrap() {
139 Item::Struct(v) => v,
140 _ => unreachable!(),
141 }
142 }
143
144 pub fn push_struct(&mut self, item: Struct) -> &mut Self {
146 self.items.push(Item::Struct(item));
147 self
148 }
149
150 pub fn new_fn(&mut self, name: &str) -> &mut Function {
152 self.push_fn(Function::new(name));
153
154 match *self.items.last_mut().unwrap() {
155 Item::Function(ref mut v) => v,
156 _ => unreachable!(),
157 }
158 }
159
160 pub fn push_fn(&mut self, item: Function) -> &mut Self {
162 self.items.push(Item::Function(item));
163 self
164 }
165
166 pub fn new_trait(&mut self, name: &str) -> &mut Trait {
168 self.push_trait(Trait::new(name));
169
170 match *self.items.last_mut().unwrap() {
171 Item::Trait(ref mut v) => v,
172 _ => unreachable!(),
173 }
174 }
175
176 pub fn push_trait(&mut self, item: Trait) -> &mut Self {
178 self.items.push(Item::Trait(item));
179 self
180 }
181
182 pub fn new_enum(&mut self, name: &str) -> &mut Enum {
184 self.push_enum(Enum::new(name));
185
186 match *self.items.last_mut().unwrap() {
187 Item::Enum(ref mut v) => v,
188 _ => unreachable!(),
189 }
190 }
191
192 pub fn push_enum(&mut self, item: Enum) -> &mut Self {
194 self.items.push(Item::Enum(item));
195 self
196 }
197
198 pub fn new_impl(&mut self, target: &str) -> &mut Impl {
200 self.push_impl(Impl::new(target));
201
202 match *self.items.last_mut().unwrap() {
203 Item::Impl(ref mut v) => v,
204 _ => unreachable!(),
205 }
206 }
207
208 pub fn push_impl(&mut self, item: Impl) -> &mut Self {
210 self.items.push(Item::Impl(item));
211 self
212 }
213
214 pub fn raw(&mut self, val: &str) -> &mut Self {
218 self.items.push(Item::Raw(val.to_string()));
219 self
220 }
221
222 pub fn to_string(&self) -> String {
224 let mut ret = String::new();
225
226 self.fmt(&mut Formatter::new(&mut ret)).unwrap();
227
228 if ret.as_bytes().last() == Some(&b'\n') {
230 ret.pop();
231 }
232
233 ret
234 }
235
236 pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
238 self.fmt_imports(fmt)?;
239
240 if !self.imports.is_empty() {
241 writeln!(fmt)?;
242 }
243
244 for (i, item) in self.items.iter().enumerate() {
245 if i != 0 {
246 writeln!(fmt)?;
247 }
248
249 match &item {
250 Item::Module(v) => v.fmt(fmt)?,
251 Item::Struct(v) => v.fmt(fmt)?,
252 Item::Function(v) => v.fmt(false, fmt)?,
253 Item::Trait(v) => v.fmt(fmt)?,
254 Item::Enum(v) => v.fmt(fmt)?,
255 Item::Impl(v) => v.fmt(fmt)?,
256 Item::Raw(v) => {
257 writeln!(fmt, "{}", v)?;
258 }
259 }
260 }
261
262 Ok(())
263 }
264
265 fn fmt_imports(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
266 let mut visibilities = vec![];
268
269 for (_, imports) in &self.imports {
270 for (_, import) in imports {
271 if !visibilities.contains(&import.vis) {
272 visibilities.push(import.vis.clone());
273 }
274 }
275 }
276
277 let mut tys = vec![];
278
279 for vis in &visibilities {
281 for (path, imports) in &self.imports {
282 tys.clear();
283
284 for (ty, import) in imports {
285 if *vis == import.vis {
286 tys.push(ty);
287 }
288 }
289
290 if !tys.is_empty() {
291 if let Some(vis) = &vis {
292 write!(fmt, "{} ", vis)?;
293 }
294
295 write!(fmt, "use {}::", path)?;
296
297 if tys.len() > 1 {
298 write!(fmt, "{{")?;
299
300 for (i, ty) in tys.iter().enumerate() {
301 if i != 0 {
302 write!(fmt, ", ")?;
303 }
304 write!(fmt, "{}", ty)?;
305 }
306
307 writeln!(fmt, "}};")?;
308 } else if tys.len() == 1 {
309 writeln!(fmt, "{};", tys[0])?;
310 }
311 }
312 }
313 }
314
315 Ok(())
316 }
317}