|
| 1 | +use crate::core::DocContext; |
1 | 2 | use rustc_data_structures::fx::FxHashSet;
|
2 |
| -use rustc_hir::def::{DefKind, Res}; |
3 |
| -use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_ID}; |
| 3 | +use rustc_hir::def::DefKind; |
| 4 | +use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; |
4 | 5 | use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
|
5 | 6 | use rustc_middle::ty::{TyCtxt, Visibility};
|
6 | 7 |
|
7 | 8 | // FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses
|
8 | 9 |
|
| 10 | +pub(crate) fn lib_embargo_visit_item(cx: &mut DocContext<'_>, def_id: DefId) { |
| 11 | + assert!(!def_id.is_local()); |
| 12 | + LibEmbargoVisitor { |
| 13 | + tcx: cx.tcx, |
| 14 | + effective_visibilities: &mut cx.cache.effective_visibilities, |
| 15 | + visited_mods: FxHashSet::default(), |
| 16 | + } |
| 17 | + .visit_item(def_id) |
| 18 | +} |
| 19 | + |
9 | 20 | /// Similar to `librustc_privacy::EmbargoVisitor`, but also takes
|
10 | 21 | /// specific rustdoc annotations into account (i.e., `doc(hidden)`)
|
11 |
| -pub(crate) struct LibEmbargoVisitor<'a, 'tcx> { |
| 22 | +struct LibEmbargoVisitor<'a, 'tcx> { |
12 | 23 | tcx: TyCtxt<'tcx>,
|
13 | 24 | // Effective visibilities for reachable nodes
|
14 | 25 | effective_visibilities: &'a mut EffectiveVisibilities<DefId>,
|
15 |
| - // Previous level, None means unreachable |
16 |
| - prev_level: Option<Level>, |
17 | 26 | // Keeps track of already visited modules, in case a module re-exports its parent
|
18 | 27 | visited_mods: FxHashSet<DefId>,
|
19 | 28 | }
|
20 | 29 |
|
21 |
| -impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { |
22 |
| - pub(crate) fn new(cx: &'a mut crate::core::DocContext<'tcx>) -> LibEmbargoVisitor<'a, 'tcx> { |
23 |
| - LibEmbargoVisitor { |
24 |
| - tcx: cx.tcx, |
25 |
| - effective_visibilities: &mut cx.cache.effective_visibilities, |
26 |
| - prev_level: Some(Level::Direct), |
27 |
| - visited_mods: FxHashSet::default(), |
28 |
| - } |
29 |
| - } |
30 |
| - |
31 |
| - pub(crate) fn visit_lib(&mut self, cnum: CrateNum) { |
32 |
| - let did = cnum.as_def_id(); |
33 |
| - self.update(did, Some(Level::Direct)); |
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<Level>) -> Option<Level> { |
39 |
| - let is_hidden = self.tcx.is_doc_hidden(did); |
40 |
| - |
41 |
| - let old_level = self.effective_visibilities.public_at_level(did); |
42 |
| - // Visibility levels can only grow |
43 |
| - if level > old_level && !is_hidden { |
44 |
| - self.effective_visibilities.set_public_at_level( |
45 |
| - did, |
46 |
| - || Visibility::Restricted(CRATE_DEF_ID), |
47 |
| - level.unwrap(), |
48 |
| - ); |
49 |
| - level |
50 |
| - } else { |
51 |
| - old_level |
52 |
| - } |
53 |
| - } |
54 |
| - |
55 |
| - pub(crate) fn visit_mod(&mut self, def_id: DefId) { |
| 30 | +impl LibEmbargoVisitor<'_, '_> { |
| 31 | + fn visit_mod(&mut self, def_id: DefId) { |
56 | 32 | if !self.visited_mods.insert(def_id) {
|
57 | 33 | return;
|
58 | 34 | }
|
59 | 35 |
|
60 | 36 | for item in self.tcx.module_children(def_id).iter() {
|
61 | 37 | if let Some(def_id) = item.res.opt_def_id() {
|
62 |
| - if self.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index) |
63 |
| - || item.vis.is_public() |
64 |
| - { |
65 |
| - self.visit_item(item.res); |
| 38 | + if item.vis.is_public() { |
| 39 | + self.visit_item(def_id); |
66 | 40 | }
|
67 | 41 | }
|
68 | 42 | }
|
69 | 43 | }
|
70 | 44 |
|
71 |
| - fn visit_item(&mut self, res: Res<!>) { |
72 |
| - let def_id = res.def_id(); |
73 |
| - let vis = self.tcx.visibility(def_id); |
74 |
| - let inherited_item_level = if vis.is_public() { self.prev_level } else { None }; |
75 |
| - |
76 |
| - let item_level = self.update(def_id, inherited_item_level); |
77 |
| - |
78 |
| - if let Res::Def(DefKind::Mod, _) = res { |
79 |
| - let orig_level = self.prev_level; |
80 |
| - |
81 |
| - self.prev_level = item_level; |
82 |
| - self.visit_mod(def_id); |
83 |
| - self.prev_level = orig_level; |
| 45 | + fn visit_item(&mut self, def_id: DefId) { |
| 46 | + if !self.tcx.is_doc_hidden(def_id) { |
| 47 | + self.effective_visibilities.set_public_at_level( |
| 48 | + def_id, |
| 49 | + || Visibility::Restricted(CRATE_DEF_ID), |
| 50 | + Level::Direct, |
| 51 | + ); |
| 52 | + if self.tcx.def_kind(def_id) == DefKind::Mod { |
| 53 | + self.visit_mod(def_id); |
| 54 | + } |
84 | 55 | }
|
85 | 56 | }
|
86 | 57 | }
|
0 commit comments