]> git.proxmox.com Git - rustc.git/blame - src/librustdoc/visit_lib.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / src / librustdoc / visit_lib.rs
CommitLineData
dfeec247
XL
1use rustc_data_structures::fx::FxHashSet;
2use rustc_hir::def::{DefKind, Res};
3use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
ba9703b0 4use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
3c0e092e 5use rustc_middle::ty::TyCtxt;
a7813a04
XL
6
7// FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses
8
9/// Similar to `librustc_privacy::EmbargoVisitor`, but also takes
0731742a 10/// specific rustdoc annotations into account (i.e., `doc(hidden)`)
fc512014 11crate struct LibEmbargoVisitor<'a, 'tcx> {
e1599b0c 12 tcx: TyCtxt<'tcx>,
a7813a04 13 // Accessibility levels for reachable nodes
e1599b0c 14 access_levels: &'a mut AccessLevels<DefId>,
a7813a04
XL
15 // Previous accessibility level, None means unreachable
16 prev_level: Option<AccessLevel>,
cc61c64b
XL
17 // Keeps track of already visited modules, in case a module re-exports its parent
18 visited_mods: FxHashSet<DefId>,
a7813a04
XL
19}
20
532ac7d7 21impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> {
fc512014 22 crate fn new(cx: &'a mut crate::core::DocContext<'tcx>) -> LibEmbargoVisitor<'a, 'tcx> {
a7813a04 23 LibEmbargoVisitor {
e1599b0c 24 tcx: cx.tcx,
6a06907d 25 access_levels: &mut cx.cache.access_levels,
a7813a04 26 prev_level: Some(AccessLevel::Public),
e1599b0c 27 visited_mods: FxHashSet::default(),
a7813a04
XL
28 }
29 }
30
fc512014 31 crate fn visit_lib(&mut self, cnum: CrateNum) {
a7813a04
XL
32 let did = DefId { krate: cnum, index: CRATE_DEF_INDEX };
33 self.update(did, Some(AccessLevel::Public));
34 self.visit_mod(did);
35 }
36
37 // Updates node level and returns the updated level
38 fn update(&mut self, did: DefId, level: Option<AccessLevel>) -> Option<AccessLevel> {
a2a8927a 39 let is_hidden = self.tcx.is_doc_hidden(did);
a7813a04
XL
40
41 let old_level = self.access_levels.map.get(&did).cloned();
42 // Accessibility levels can only grow
43 if level > old_level && !is_hidden {
44 self.access_levels.map.insert(did, level.unwrap());
45 level
46 } else {
47 old_level
48 }
49 }
50
fc512014 51 crate fn visit_mod(&mut self, def_id: DefId) {
cc61c64b
XL
52 if !self.visited_mods.insert(def_id) {
53 return;
54 }
55
5099ac24 56 for item in self.tcx.module_children(def_id).iter() {
48663c56 57 if let Some(def_id) = item.res.opt_def_id() {
dfeec247 58 if self.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index)
3c0e092e 59 || item.vis.is_public()
dfeec247 60 {
48663c56 61 self.visit_item(item.res);
0731742a 62 }
ff7c6d11 63 }
a7813a04
XL
64 }
65 }
66
c295e0f8 67 fn visit_item(&mut self, res: Res<!>) {
48663c56 68 let def_id = res.def_id();
e1599b0c 69 let vis = self.tcx.visibility(def_id);
3c0e092e 70 let inherited_item_level = if vis.is_public() { self.prev_level } else { None };
a7813a04 71
9e0c209e 72 let item_level = self.update(def_id, inherited_item_level);
a7813a04 73
48663c56 74 if let Res::Def(DefKind::Mod, _) = res {
a7813a04
XL
75 let orig_level = self.prev_level;
76
77 self.prev_level = item_level;
9e0c209e 78 self.visit_mod(def_id);
a7813a04
XL
79 self.prev_level = orig_level;
80 }
81 }
82}