about summary refs log tree commit diff
path: root/src/librustdoc/passes/collapse_docs.rs
blob: be7250f833f0042f2460f2e01f666828279a3afb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use crate::clean::{self, DocFragment, DocFragmentKind, Item};
use crate::core::DocContext;
use crate::fold;
use crate::fold::DocFolder;
use crate::passes::Pass;

use std::mem::take;

pub const COLLAPSE_DOCS: Pass = Pass {
    name: "collapse-docs",
    run: collapse_docs,
    description: "concatenates all document attributes into one document attribute",
};

pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
    let mut krate = Collapser.fold_crate(krate);
    krate.collapsed = true;
    krate
}

struct Collapser;

impl fold::DocFolder for Collapser {
    fn fold_item(&mut self, mut i: Item) -> Option<Item> {
        i.attrs.collapse_doc_comments();
        self.fold_item_recur(i)
    }
}

fn collapse(doc_strings: &mut Vec<DocFragment>) {
    let mut docs = vec![];
    let mut last_frag: Option<DocFragment> = None;

    for frag in take(doc_strings) {
        if let Some(mut curr_frag) = last_frag.take() {
            let curr_kind = &curr_frag.kind;
            let new_kind = &frag.kind;

            if matches!(*curr_kind, DocFragmentKind::Include { .. }) || curr_kind != new_kind {
                if *curr_kind == DocFragmentKind::SugaredDoc
                    || *curr_kind == DocFragmentKind::RawDoc
                {
                    // add a newline for extra padding between segments
                    curr_frag.doc.push('\n');
                }
                docs.push(curr_frag);
                last_frag = Some(frag);
            } else {
                curr_frag.doc.push('\n');
                curr_frag.doc.push_str(&frag.doc);
                curr_frag.span = curr_frag.span.to(frag.span);
                last_frag = Some(curr_frag);
            }
        } else {
            last_frag = Some(frag);
        }
    }

    if let Some(frag) = last_frag.take() {
        docs.push(frag);
    }
    *doc_strings = docs;
}

impl clean::Attributes {
    pub fn collapse_doc_comments(&mut self) {
        collapse(&mut self.doc_strings);
    }
}