]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/passes/strip_hidden.rs
Rollup merge of #103694 - WaffleLapkin:mask_doc_example, r=scottmcm
[rust.git] / src / librustdoc / passes / strip_hidden.rs
1 //! Strip all doc(hidden) items from the output.
2 use rustc_span::symbol::sym;
3 use std::mem;
4
5 use crate::clean;
6 use crate::clean::{Item, ItemIdSet, NestedAttributesExt};
7 use crate::core::DocContext;
8 use crate::fold::{strip_item, DocFolder};
9 use crate::passes::{ImplStripper, Pass};
10
11 pub(crate) const STRIP_HIDDEN: Pass = Pass {
12     name: "strip-hidden",
13     run: strip_hidden,
14     description: "strips all `#[doc(hidden)]` items from the output",
15 };
16
17 /// Strip items marked `#[doc(hidden)]`
18 pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
19     let mut retained = ItemIdSet::default();
20     let is_json_output = cx.output_format.is_json() && !cx.show_coverage;
21
22     // strip all #[doc(hidden)] items
23     let krate = {
24         let mut stripper = Stripper { retained: &mut retained, update_retained: true };
25         stripper.fold_crate(krate)
26     };
27
28     // strip all impls referencing stripped items
29     let mut stripper = ImplStripper {
30         tcx: cx.tcx,
31         retained: &retained,
32         cache: &cx.cache,
33         is_json_output,
34         document_private: cx.render_options.document_private,
35     };
36     stripper.fold_crate(krate)
37 }
38
39 struct Stripper<'a> {
40     retained: &'a mut ItemIdSet,
41     update_retained: bool,
42 }
43
44 impl<'a> DocFolder for Stripper<'a> {
45     fn fold_item(&mut self, i: Item) -> Option<Item> {
46         if i.attrs.lists(sym::doc).has_word(sym::hidden) {
47             debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
48             // Use a dedicated hidden item for fields, variants, and modules.
49             // We need to keep private fields and variants, so that the docs
50             // can show a placeholder "// some variants omitted". We need to keep
51             // private modules, because they can contain impl blocks, and impl
52             // block privacy is inherited from the type and trait, not from the
53             // module it's defined in. Both of these are marked "stripped," and
54             // not included in the final docs, but since they still have an effect
55             // on the final doc, cannot be completely removed from the Clean IR.
56             match *i.kind {
57                 clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
58                     // We need to recurse into stripped modules to
59                     // strip things like impl methods but when doing so
60                     // we must not add any items to the `retained` set.
61                     let old = mem::replace(&mut self.update_retained, false);
62                     let ret = strip_item(self.fold_item_recur(i));
63                     self.update_retained = old;
64                     return Some(ret);
65                 }
66                 _ => return None,
67             }
68         } else {
69             if self.update_retained {
70                 self.retained.insert(i.item_id);
71             }
72         }
73         Some(self.fold_item_recur(i))
74     }
75 }