]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/passes/stripper.rs
rustdoc: Rename `expect_real` to `expect_def_id`, remove `Item::is_fake`
[rust.git] / src / librustdoc / passes / stripper.rs
1 use rustc_hir::def_id::DefId;
2 use rustc_middle::middle::privacy::AccessLevels;
3 use std::mem;
4
5 use crate::clean::{self, GetDefId, Item, ItemIdSet};
6 use crate::fold::{strip_item, DocFolder};
7
8 crate struct Stripper<'a> {
9     crate retained: &'a mut ItemIdSet,
10     crate access_levels: &'a AccessLevels<DefId>,
11     crate update_retained: bool,
12 }
13
14 impl<'a> DocFolder for Stripper<'a> {
15     fn fold_item(&mut self, i: Item) -> Option<Item> {
16         match *i.kind {
17             clean::StrippedItem(..) => {
18                 // We need to recurse into stripped modules to strip things
19                 // like impl methods but when doing so we must not add any
20                 // items to the `retained` set.
21                 debug!("Stripper: recursing into stripped {:?} {:?}", i.type_(), i.name);
22                 let old = mem::replace(&mut self.update_retained, false);
23                 let ret = self.fold_item_recur(i);
24                 self.update_retained = old;
25                 return Some(ret);
26             }
27             // These items can all get re-exported
28             clean::OpaqueTyItem(..)
29             | clean::TypedefItem(..)
30             | clean::StaticItem(..)
31             | clean::StructItem(..)
32             | clean::EnumItem(..)
33             | clean::TraitItem(..)
34             | clean::FunctionItem(..)
35             | clean::VariantItem(..)
36             | clean::MethodItem(..)
37             | clean::ForeignFunctionItem(..)
38             | clean::ForeignStaticItem(..)
39             | clean::ConstantItem(..)
40             | clean::UnionItem(..)
41             | clean::AssocConstItem(..)
42             | clean::TraitAliasItem(..)
43             | clean::ForeignTypeItem => {
44                 if i.def_id.is_local() {
45                     if !self.access_levels.is_exported(i.def_id.expect_def_id()) {
46                         debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
47                         return None;
48                     }
49                 }
50             }
51
52             clean::StructFieldItem(..) => {
53                 if !i.visibility.is_public() {
54                     return Some(strip_item(i));
55                 }
56             }
57
58             clean::ModuleItem(..) => {
59                 if i.def_id.is_local() && !i.visibility.is_public() {
60                     debug!("Stripper: stripping module {:?}", i.name);
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             }
67
68             // handled in the `strip-priv-imports` pass
69             clean::ExternCrateItem { .. } | clean::ImportItem(..) => {}
70
71             clean::ImplItem(..) => {}
72
73             // tymethods/macros have no control over privacy
74             clean::MacroItem(..) | clean::TyMethodItem(..) => {}
75
76             // Proc-macros are always public
77             clean::ProcMacroItem(..) => {}
78
79             // Primitives are never stripped
80             clean::PrimitiveItem(..) => {}
81
82             // Associated types are never stripped
83             clean::AssocTypeItem(..) => {}
84
85             // Keywords are never stripped
86             clean::KeywordItem(..) => {}
87         }
88
89         let fastreturn = match *i.kind {
90             // nothing left to do for traits (don't want to filter their
91             // methods out, visibility controlled by the trait)
92             clean::TraitItem(..) => true,
93
94             // implementations of traits are always public.
95             clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
96             // Struct variant fields have inherited visibility
97             clean::VariantItem(clean::Variant::Struct(..)) => true,
98             _ => false,
99         };
100
101         let i = if fastreturn {
102             if self.update_retained {
103                 self.retained.insert(i.def_id);
104             }
105             return Some(i);
106         } else {
107             self.fold_item_recur(i)
108         };
109
110         if self.update_retained {
111             self.retained.insert(i.def_id);
112         }
113         Some(i)
114     }
115 }
116
117 /// This stripper discards all impls which reference stripped items
118 crate struct ImplStripper<'a> {
119     crate retained: &'a ItemIdSet,
120 }
121
122 impl<'a> DocFolder for ImplStripper<'a> {
123     fn fold_item(&mut self, i: Item) -> Option<Item> {
124         if let clean::ImplItem(ref imp) = *i.kind {
125             // emptied none trait impls can be stripped
126             if imp.trait_.is_none() && imp.items.is_empty() {
127                 return None;
128             }
129             if let Some(did) = imp.for_.def_id() {
130                 if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did.into())
131                 {
132                     debug!("ImplStripper: impl item for stripped type; removing");
133                     return None;
134                 }
135             }
136             if let Some(did) = imp.trait_.def_id() {
137                 if did.is_local() && !self.retained.contains(&did.into()) {
138                     debug!("ImplStripper: impl item for stripped trait; removing");
139                     return None;
140                 }
141             }
142             if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
143                 for typaram in generics {
144                     if let Some(did) = typaram.def_id() {
145                         if did.is_local() && !self.retained.contains(&did.into()) {
146                             debug!(
147                                 "ImplStripper: stripped item in trait's generics; removing impl"
148                             );
149                             return None;
150                         }
151                     }
152                 }
153             }
154         }
155         Some(self.fold_item_recur(i))
156     }
157 }
158
159 /// This stripper discards all private import statements (`use`, `extern crate`)
160 crate struct ImportStripper;
161
162 impl DocFolder for ImportStripper {
163     fn fold_item(&mut self, i: Item) -> Option<Item> {
164         match *i.kind {
165             clean::ExternCrateItem { .. } | clean::ImportItem(..) if !i.visibility.is_public() => {
166                 None
167             }
168             _ => Some(self.fold_item_recur(i)),
169         }
170     }
171 }