rustdoc/
visit_lib.rs
1use rustc_hir::def::DefKind;
2use rustc_hir::def_id::{DefId, DefIdSet};
3use rustc_middle::ty::TyCtxt;
4
5use crate::core::DocContext;
6
7#[derive(Default)]
10pub(crate) struct RustdocEffectiveVisibilities {
11 extern_public: DefIdSet,
12}
13
14macro_rules! define_method {
15 ($method:ident) => {
16 pub(crate) fn $method(&self, tcx: TyCtxt<'_>, def_id: DefId) -> bool {
17 match def_id.as_local() {
18 Some(def_id) => tcx.effective_visibilities(()).$method(def_id),
19 None => self.extern_public.contains(&def_id),
20 }
21 }
22 };
23}
24
25impl RustdocEffectiveVisibilities {
26 define_method!(is_directly_public);
27 define_method!(is_exported);
28 define_method!(is_reachable);
29}
30
31pub(crate) fn lib_embargo_visit_item(cx: &mut DocContext<'_>, def_id: DefId) {
32 assert!(!def_id.is_local());
33 LibEmbargoVisitor {
34 tcx: cx.tcx,
35 extern_public: &mut cx.cache.effective_visibilities.extern_public,
36 visited_mods: Default::default(),
37 document_hidden: cx.render_options.document_hidden,
38 }
39 .visit_item(def_id)
40}
41
42struct LibEmbargoVisitor<'a, 'tcx> {
45 tcx: TyCtxt<'tcx>,
46 extern_public: &'a mut DefIdSet,
48 visited_mods: DefIdSet,
50 document_hidden: bool,
51}
52
53impl LibEmbargoVisitor<'_, '_> {
54 fn visit_mod(&mut self, def_id: DefId) {
55 if !self.visited_mods.insert(def_id) {
56 return;
57 }
58
59 for item in self.tcx.module_children(def_id).iter() {
60 if let Some(def_id) = item.res.opt_def_id() {
61 if item.vis.is_public() {
62 self.visit_item(def_id);
63 }
64 }
65 }
66 }
67
68 fn visit_item(&mut self, def_id: DefId) {
69 if self.document_hidden || !self.tcx.is_doc_hidden(def_id) {
70 self.extern_public.insert(def_id);
71 if self.tcx.def_kind(def_id) == DefKind::Mod {
72 self.visit_mod(def_id);
73 }
74 }
75 }
76}