1mod crate_directive;
32mod directive_options;
33mod enum_directive;
34mod executable_directive;
35mod function_directive;
36mod impl_directive;
37mod macro_directive;
38mod module_directive;
39mod struct_directive;
40mod trait_directive;
41mod type_directive;
42mod use_directive;
43mod variable_directive;
44
45use syn::{Attribute, Expr, ForeignItem, ImplItem, Item, Lit, TraitItem, Visibility};
46
47pub use crate::directives::crate_directive::CrateDirective;
49pub(crate) use crate::directives::directive_options::DirectiveVisibility;
50pub use crate::directives::enum_directive::EnumDirective;
51pub use crate::directives::executable_directive::ExecutableDirective;
52pub use crate::directives::function_directive::FunctionDirective;
53pub use crate::directives::impl_directive::ImplDirective;
54pub use crate::directives::macro_directive::MacroDirective;
55pub use crate::directives::module_directive::ModuleDirective;
56pub use crate::directives::struct_directive::StructDirective;
57pub use crate::directives::trait_directive::TraitDirective;
58pub use crate::directives::type_directive::TypeDirective;
59pub use crate::directives::use_directive::UseDirective;
60pub use crate::directives::variable_directive::VariableDirective;
61use crate::formats::{MdDirective, RstDirective};
62use crate::utils::SourceCodeFile;
63
64#[derive(Clone, Debug)]
66pub(crate) enum Directive {
67 Crate(CrateDirective),
68 Enum(EnumDirective),
69 Executable(ExecutableDirective),
70 Function(FunctionDirective),
71 Impl(ImplDirective),
72 Macro(MacroDirective),
73 Module(ModuleDirective),
74 Struct(StructDirective),
75 Trait(TraitDirective),
76 Type(TypeDirective),
77 Use(UseDirective),
78 Variable(VariableDirective),
79}
80
81impl Directive {
82 fn name(&self) -> &str {
83 match self {
84 Directive::Crate(c) => &c.name,
85 Directive::Enum(e) => &e.name,
86 Directive::Executable(e) => &e.0.name,
87 Directive::Function(f) => &f.name,
88 Directive::Impl(i) => &i.name,
89 Directive::Macro(m) => &m.name,
90 Directive::Module(m) => &m.name,
91 Directive::Struct(s) => &s.name,
92 Directive::Trait(t) => &t.name,
93 Directive::Type(t) => &t.name,
94 Directive::Use(_) => {
95 unreachable!("name is used for sorting, which is not done for UseDirective")
96 }
97 Directive::Variable(v) => &v.name,
98 }
99 }
100
101 fn change_parent(&mut self, new_parent: &str) {
103 match self {
104 Directive::Crate(_) => {
105 unreachable!("Crate directive shouldn't have parent")
106 }
107 Directive::Enum(e) => e.change_parent(new_parent),
108 Directive::Executable(_) => {
109 unreachable!("Executable directive shouldn't have parent")
110 }
111 Directive::Function(f) => f.change_parent(new_parent),
112 Directive::Impl(i) => i.change_parent(new_parent),
113 Directive::Macro(m) => m.change_parent(new_parent),
114 Directive::Module(m) => m.change_parent(new_parent),
115 Directive::Struct(s) => s.change_parent(new_parent),
116 Directive::Trait(t) => t.change_parent(new_parent),
117 Directive::Type(t) => t.change_parent(new_parent),
118 Directive::Use(_) => {}
119 Directive::Variable(v) => v.change_parent(new_parent),
120 }
121 }
122
123 fn directive_visibility(&self) -> &DirectiveVisibility {
125 match self {
126 Directive::Crate(_) => &DirectiveVisibility::Pub,
127 Directive::Enum(e) => e.directive_visibility(),
128 Directive::Executable(_) => &DirectiveVisibility::Pub,
129 Directive::Function(f) => f.directive_visibility(),
130 Directive::Impl(i) => i.directive_visibility(),
131 Directive::Macro(m) => m.directive_visibility(),
132 Directive::Module(m) => m.directive_visibility(),
133 Directive::Struct(s) => s.directive_visibility(),
134 Directive::Trait(t) => t.directive_visibility(),
135 Directive::Type(t) => t.directive_visibility(),
136 Directive::Use(u) => u.directive_visibility(),
137 Directive::Variable(v) => v.directive_visibility(),
138 }
139 }
140
141 fn add_content<I: IntoIterator<Item = String>>(&mut self, content: I) {
145 match self {
146 Directive::Crate(d) => {
147 d.content.push(String::new());
148 d.content.extend(content);
149 d.content.push(String::new())
150 }
151 Directive::Enum(d) => {
152 d.content.push(String::new());
153 d.content.extend(content);
154 d.content.push(String::new())
155 }
156 Directive::Executable(d) => {
157 d.0.content.push(String::new());
158 d.0.content.extend(content);
159 d.0.content.push(String::new())
160 }
161 Directive::Function(d) => {
162 d.content.push(String::new());
163 d.content.extend(content);
164 d.content.push(String::new())
165 }
166 Directive::Impl(d) => {
167 d.content.push(String::new());
168 d.content.extend(content);
169 d.content.push(String::new())
170 }
171 Directive::Macro(d) => {
172 d.content.push(String::new());
173 d.content.extend(content);
174 d.content.push(String::new())
175 }
176 Directive::Module(d) => {
177 d.content.push(String::new());
178 d.content.extend(content);
179 d.content.push(String::new())
180 }
181 Directive::Struct(d) => {
182 d.content.push(String::new());
183 d.content.extend(content);
184 d.content.push(String::new())
185 }
186 Directive::Trait(d) => {
187 d.content.push(String::new());
188 d.content.extend(content);
189 d.content.push(String::new())
190 }
191 Directive::Type(d) => {
192 d.content.push(String::new());
193 d.content.extend(content);
194 d.content.push(String::new())
195 }
196 Directive::Use(d) => {
197 d.content.push(String::new());
198 d.content.extend(content);
199 d.content.push(String::new())
200 }
201 Directive::Variable(d) => {
202 d.content.push(String::new());
203 d.content.extend(content);
204 d.content.push(String::new())
205 }
206 }
207 }
208
209 fn from_item(
218 parent_path: &str,
219 item: &Item,
220 inherited_visibility: &Option<&Visibility>,
221 ) -> Option<Directive> {
222 match item {
223 Item::Const(c) => Some(VariableDirective::from_const(parent_path, c)),
224 Item::Enum(e) => Some(EnumDirective::from_item(parent_path, e)),
225 Item::ExternCrate(_) => None,
226 Item::Fn(f) => Some(FunctionDirective::from_item(parent_path, f)),
227 Item::ForeignMod(_) => panic!("ForeignMod items cannot be converted to a single item"),
228 Item::Impl(i) => Some(Directive::Impl(ImplDirective::from_item(
229 parent_path,
230 i,
231 inherited_visibility,
232 ))),
233 Item::Macro(m) => MacroDirective::from_item(parent_path, m),
234 Item::Mod(_) => panic!("Module directives must be created with a source code file"),
235 Item::Static(s) => Some(VariableDirective::from_static(parent_path, s)),
236 Item::Struct(s) => Some(StructDirective::from_item(parent_path, s)),
237 Item::Trait(t) => Some(TraitDirective::from_item(parent_path, t)),
238 Item::TraitAlias(t) => Some(TraitDirective::from_alias(parent_path, t)),
239 Item::Type(t) => Some(TypeDirective::from_item(parent_path, t)),
240 Item::Union(u) => Some(StructDirective::from_union(parent_path, u)),
241 Item::Use(u) => Some(UseDirective::from_item_as_directive(parent_path, u)),
242 Item::Verbatim(_) => None,
243 i => panic!("Unexpected item: {:?}", i),
244 }
245 }
246
247 fn from_impl_item(
256 parent_path: &str,
257 item: &ImplItem,
258 inherited_visibility: &Option<&Visibility>,
259 ) -> Option<Directive> {
260 match item {
261 ImplItem::Const(c) => Some(VariableDirective::from_impl_const(
262 parent_path,
263 c,
264 inherited_visibility,
265 )),
266 ImplItem::Fn(f) => Some(FunctionDirective::from_impl_item(
267 parent_path,
268 f,
269 inherited_visibility,
270 )),
271 ImplItem::Type(t) => Some(TypeDirective::from_impl_item(
272 parent_path,
273 t,
274 inherited_visibility,
275 )),
276 ImplItem::Macro(_) | ImplItem::Verbatim(_) => None,
277 i => panic!("Unexpected impl item: {:?}", i),
278 }
279 }
280
281 fn from_impl_items<'a, T: Iterator<Item = &'a ImplItem>>(
291 parent_path: &str,
292 items: T,
293 inherited_visibility: &Option<&Visibility>,
294 ) -> Vec<Directive> {
295 items
296 .filter_map(|i| Self::from_impl_item(parent_path, i, inherited_visibility))
297 .collect()
298 }
299
300 fn from_trait_item(
309 parent_path: &str,
310 item: &TraitItem,
311 inherited_visibility: &Option<&Visibility>,
312 ) -> Option<Directive> {
313 match item {
314 TraitItem::Const(c) => Some(VariableDirective::from_trait_const(
315 parent_path,
316 c,
317 inherited_visibility,
318 )),
319 TraitItem::Fn(f) => Some(FunctionDirective::from_trait_item(
320 parent_path,
321 f,
322 inherited_visibility,
323 )),
324 TraitItem::Type(t) => Some(TypeDirective::from_trait_item(
325 parent_path,
326 t,
327 inherited_visibility,
328 )),
329 TraitItem::Macro(_) | TraitItem::Verbatim(_) => None,
330 i => panic!("Unexpected trait item: {:?}", i),
331 }
332 }
333
334 fn from_trait_items<'a, T: Iterator<Item = &'a TraitItem>>(
344 parent_path: &str,
345 items: T,
346 inherited_visibility: &Option<&Visibility>,
347 ) -> Vec<Directive> {
348 items
349 .filter_map(|i| Self::from_trait_item(parent_path, i, inherited_visibility))
350 .collect()
351 }
352
353 fn from_extern_item(parent_path: &str, item: &ForeignItem) -> Option<Directive> {
362 match item {
363 ForeignItem::Fn(f) => Some(FunctionDirective::from_extern(parent_path, f)),
364 ForeignItem::Static(s) => Some(VariableDirective::from_extern_static(parent_path, s)),
365 ForeignItem::Type(t) => Some(TypeDirective::from_extern(parent_path, t)),
366 _ => None,
367 }
368 }
369
370 fn from_extern_items<'a, T: Iterator<Item = &'a ForeignItem>>(
380 parent_path: &str,
381 items: T,
382 ) -> Vec<Directive> {
383 items
384 .filter_map(|i| Self::from_extern_item(parent_path, i))
385 .collect()
386 }
387}
388
389impl RstDirective for Directive {
390 fn get_rst_text(self, level: usize, max_visibility: &DirectiveVisibility) -> Vec<String> {
391 match self {
392 Directive::Crate(c) => c.get_rst_text(level, max_visibility),
393 Directive::Enum(e) => e.get_rst_text(level, max_visibility),
394 Directive::Executable(e) => e.get_rst_text(level, max_visibility),
395 Directive::Function(f) => f.get_rst_text(level, max_visibility),
396 Directive::Impl(i) => i.get_rst_text(level, max_visibility),
397 Directive::Macro(m) => m.get_rst_text(level, max_visibility),
398 Directive::Module(m) => m.get_rst_text(level, max_visibility),
399 Directive::Struct(s) => s.get_rst_text(level, max_visibility),
400 Directive::Trait(t) => t.get_rst_text(level, max_visibility),
401 Directive::Type(t) => t.get_rst_text(level, max_visibility),
402 Directive::Use(u) => u.get_rst_text(level, max_visibility),
403 Directive::Variable(v) => v.get_rst_text(level, max_visibility),
404 }
405 }
406}
407
408impl MdDirective for Directive {
409 fn get_md_text(self, fence_size: usize, max_visibility: &DirectiveVisibility) -> Vec<String> {
410 match self {
411 Directive::Crate(c) => c.get_md_text(fence_size, max_visibility),
412 Directive::Enum(e) => e.get_md_text(fence_size, max_visibility),
413 Directive::Executable(e) => e.get_md_text(fence_size, max_visibility),
414 Directive::Function(f) => f.get_md_text(fence_size, max_visibility),
415 Directive::Impl(i) => i.get_md_text(fence_size, max_visibility),
416 Directive::Macro(m) => m.get_md_text(fence_size, max_visibility),
417 Directive::Module(m) => m.get_md_text(fence_size, max_visibility),
418 Directive::Struct(s) => s.get_md_text(fence_size, max_visibility),
419 Directive::Trait(t) => t.get_md_text(fence_size, max_visibility),
420 Directive::Type(t) => t.get_md_text(fence_size, max_visibility),
421 Directive::Use(u) => u.get_md_text(fence_size, max_visibility),
422 Directive::Variable(v) => v.get_md_text(fence_size, max_visibility),
423 }
424 }
425
426 fn fence_size(&self) -> usize {
427 match self {
428 Directive::Crate(c) => c.fence_size(),
429 Directive::Enum(e) => e.fence_size(),
430 Directive::Executable(e) => e.fence_size(),
431 Directive::Function(f) => f.fence_size(),
432 Directive::Impl(i) => i.fence_size(),
433 Directive::Macro(m) => m.fence_size(),
434 Directive::Module(m) => m.fence_size(),
435 Directive::Struct(s) => s.fence_size(),
436 Directive::Trait(t) => t.fence_size(),
437 Directive::Type(t) => t.fence_size(),
438 Directive::Use(u) => u.fence_size(),
439 Directive::Variable(v) => v.fence_size(),
440 }
441 }
442}
443
444pub(crate) fn extract_doc_from_attrs(attrs: &Vec<Attribute>) -> Vec<String> {
454 let mut content = Vec::new();
455 for attr in attrs {
456 if attr.path().segments.is_empty() || attr.path().segments[0].ident != "doc" {
457 continue;
458 }
459
460 if let Expr::Lit(e) = &attr.meta.require_name_value().unwrap().value {
461 if let Lit::Str(d) = &e.lit {
462 let line = d.value();
463 content.push(line.strip_prefix(' ').unwrap_or(&line).to_string());
464 }
465 }
466 }
467 content
468}
469
470macro_rules! push_sorted {
472 ($sorted:expr, $items:expr, $name:expr) => {{
473 if !$items.is_empty() {
474 $items.sort_by(|a, b| a.name().cmp(b.name()));
475 $sorted.push(($name, $items));
476 }
477 }};
478}
479
480type ItemSections = Vec<(&'static str, Vec<Directive>)>;
482
483fn order_items(items: Vec<Directive>) -> ItemSections {
501 let mut enums = vec![];
502 let mut fns = vec![];
503 let mut impls = vec![];
504 let mut macros = vec![];
505 let mut structs = vec![];
506 let mut traits = vec![];
507 let mut types = vec![];
508 let mut vars = vec![];
509
510 for item in items {
511 match item {
512 Directive::Crate(_) => {
513 unreachable!("Unexpected crate directive as an item")
514 }
515 Directive::Enum(e) => enums.push(Directive::Enum(e)),
516 Directive::Executable(_) => {
517 unreachable!("Unexpected executable directive as an item")
518 }
519 Directive::Function(f) => fns.push(Directive::Function(f)),
520 Directive::Impl(i) => impls.push(Directive::Impl(i)),
521 Directive::Macro(m) => macros.push(Directive::Macro(m)),
522 Directive::Module(_) => unreachable!("Unexpected module directive as item"),
523 Directive::Struct(s) => structs.push(Directive::Struct(s)),
524 Directive::Trait(t) => traits.push(Directive::Trait(t)),
525 Directive::Type(t) => types.push(Directive::Type(t)),
526 Directive::Use(_) => unreachable!("Unexpected use directive as item"),
527 Directive::Variable(v) => vars.push(Directive::Variable(v)),
528 }
529 }
530
531 impls.sort_by(|a, b| a.name().cmp(b.name()));
532
533 let mut sorted = Vec::new();
534 push_sorted!(sorted, types, "Types");
535 push_sorted!(sorted, vars, "Variables");
536 push_sorted!(sorted, macros, "Macros");
537 push_sorted!(sorted, fns, "Functions");
538
539 push_sorted!(sorted, traits, "Traits");
540 push_sorted!(sorted, enums, "Enums");
541 push_sorted!(sorted, structs, "Structs and Unions");
542 push_sorted!(sorted, impls, "Impls");
543
544 sorted
545}
546
547#[derive(Clone, Debug)]
548pub(crate) struct FileDirectives {
549 pub(crate) modules: Vec<ModuleDirective>,
551 pub(crate) impls: Vec<ImplDirective>,
553 pub(crate) uses: Vec<UseDirective>,
555 pub(crate) items: Vec<Directive>,
558}
559
560impl FileDirectives {
561 fn from_ast_items(ast_items: &Vec<Item>, module_parent: &SourceCodeFile) -> Self {
568 let mut modules = vec![];
569 let mut impls = vec![];
570 let mut uses = vec![
571 UseDirective::for_path(&module_parent.item, "self"),
572 UseDirective::for_path(module_parent.crate_name(), "crate"),
573 ];
574 let mut items = vec![];
575
576 for item in ast_items {
577 match item {
578 Item::Mod(m) => {
579 if let Some(md) = ModuleDirective::from_item(module_parent, m) {
580 modules.push(md);
581 }
582 }
583 Item::Use(u) => {
584 uses.push(UseDirective::from_item(&module_parent.item, u));
585 }
586 Item::Impl(i) => {
587 impls.push(ImplDirective::from_item(&module_parent.item, i, &None));
588 }
589 Item::ForeignMod(f) => {
590 items.extend(Directive::from_extern_items(
591 &module_parent.item,
592 f.items.iter(),
593 ));
594 }
595 _ => {
596 if let Some(i) = Directive::from_item(&module_parent.item, item, &None) {
597 items.push(i);
598 }
599 }
600 }
601 }
602
603 for use_ in &mut uses {
605 use_.resolve_relative_paths(&modules);
606 }
607
608 for impl_ in &mut impls {
615 for use_ in &uses {
616 if let Some(path) = use_.find(&impl_.self_ty) {
617 impl_.resolved_self_ty = path.clone();
618 }
619 else if let Some(trait_) = &impl_.trait_ {
620 if let Some(path) =
621 use_.find(trait_.strip_prefix('!').unwrap_or_else(|| trait_))
622 {
623 impl_.resolved_trait = Some(path.clone());
624 }
625 }
626 }
627 }
628
629 FileDirectives {
630 modules,
631 impls,
632 uses,
633 items,
634 }
635 }
636
637 fn claim_impls(&mut self, parent_name: &str, impls: Vec<ImplDirective>) -> Vec<ImplDirective> {
638 let mut remaining = vec![];
639
640 'impl_loop: for impl_ in impls {
641 for item in &mut self.items {
643 match item {
644 Directive::Enum(e) if impl_.for_item(&e.name) => {
645 e.add_impl(impl_);
646 continue 'impl_loop;
647 }
648 Directive::Struct(s) if impl_.for_item(&s.name) => {
649 s.add_impl(impl_);
650 continue 'impl_loop;
651 }
652 _ => {}
653 }
654 }
655 for item in &mut self.items {
657 match item {
658 Directive::Trait(t) if impl_.for_trait(&t.name, parent_name) => {
659 t.add_impl(impl_);
660 continue 'impl_loop;
661 }
662 _ => {}
663 }
664 }
665 remaining.push(impl_)
666 }
667
668 for module in &mut self.modules {
670 remaining = module.claim_impls(remaining);
671 }
672 remaining
673 }
674}