]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/passes/collapse_docs.rs
8666ba357b832f92bc10cf1f1c506c514575a2a1
[rust.git] / src / librustdoc / passes / collapse_docs.rs
1 use crate::clean::{self, DocFragment, Item};
2 use crate::core::DocContext;
3 use crate::fold;
4 use crate::fold::{DocFolder};
5 use crate::passes::Pass;
6
7 use std::mem::replace;
8
9 pub const COLLAPSE_DOCS: Pass = Pass {
10     name: "collapse-docs",
11     pass: collapse_docs,
12     description: "concatenates all document attributes into one document attribute",
13 };
14
15 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
16 enum DocFragmentKind {
17     Sugared,
18     Raw,
19     Include,
20 }
21
22 impl DocFragment {
23     fn kind(&self) -> DocFragmentKind {
24         match *self {
25             DocFragment::SugaredDoc(..) => DocFragmentKind::Sugared,
26             DocFragment::RawDoc(..) => DocFragmentKind::Raw,
27             DocFragment::Include(..) => DocFragmentKind::Include,
28         }
29     }
30 }
31
32 pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
33     Collapser.fold_crate(krate)
34 }
35
36 struct Collapser;
37
38 impl fold::DocFolder for Collapser {
39     fn fold_item(&mut self, mut i: Item) -> Option<Item> {
40         i.attrs.collapse_doc_comments();
41         self.fold_item_recur(i)
42     }
43 }
44
45 fn collapse(doc_strings: &mut Vec<DocFragment>) {
46     let mut docs = vec![];
47     let mut last_frag: Option<DocFragment> = None;
48
49     for frag in replace(doc_strings, vec![]) {
50         if let Some(mut curr_frag) = last_frag.take() {
51             let curr_kind = curr_frag.kind();
52             let new_kind = frag.kind();
53
54             if curr_kind == DocFragmentKind::Include || curr_kind != new_kind {
55                 match curr_frag {
56                     DocFragment::SugaredDoc(_, _, ref mut doc_string)
57                         | DocFragment::RawDoc(_, _, ref mut doc_string) => {
58                             // add a newline for extra padding between segments
59                             doc_string.push('\n');
60                         }
61                     _ => {}
62                 }
63                 docs.push(curr_frag);
64                 last_frag = Some(frag);
65             } else {
66                 match curr_frag {
67                     DocFragment::SugaredDoc(_, ref mut span, ref mut doc_string)
68                         | DocFragment::RawDoc(_, ref mut span, ref mut doc_string) => {
69                             doc_string.push('\n');
70                             doc_string.push_str(frag.as_str());
71                             *span = span.to(frag.span());
72                         }
73                     _ => unreachable!(),
74                 }
75                 last_frag = Some(curr_frag);
76             }
77         } else {
78             last_frag = Some(frag);
79         }
80     }
81
82     if let Some(frag) = last_frag.take() {
83         docs.push(frag);
84     }
85     *doc_strings = docs;
86 }
87
88 impl clean::Attributes {
89     pub fn collapse_doc_comments(&mut self) {
90         collapse(&mut self.doc_strings);
91     }
92 }