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