Modules can be reexported and it should be handled by rustdoc

This commit is contained in:
Guillaume Gomez 2023-05-05 15:32:56 +02:00
parent 879f8de409
commit fb160d5d3b
3 changed files with 56 additions and 9 deletions

View File

@ -119,7 +119,28 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
}); });
let kind = ModuleItem(Module { items, span }); let kind = ModuleItem(Module { items, span });
Item::from_def_id_and_parts(doc.def_id.to_def_id(), Some(doc.name), kind, cx) let def_id = doc.def_id.to_def_id();
let target_attrs = inline::load_attrs(cx, def_id);
let attrs = if let Some(import_id) = doc.import_id {
let is_inline = inline::load_attrs(cx, import_id.to_def_id())
.lists(sym::doc)
.get_word_attr(sym::inline)
.is_some();
let mut attrs = get_all_import_attributes(cx, import_id, doc.def_id, is_inline);
add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None);
attrs
} else {
// We only keep the item's attributes.
target_attrs.iter().map(|attr| (Cow::Borrowed(attr), None)).collect()
};
let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
let name = doc.renamed.or_else(|| Some(doc.name));
let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, Box::new(attrs), cfg);
item.inline_stmt_id = doc.import_id.map(|local| local.to_def_id());
item
} }
fn clean_generic_bound<'tcx>( fn clean_generic_bound<'tcx>(

View File

@ -95,7 +95,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
} }
if cx.tcx.is_doc_hidden(def_id.to_def_id()) if cx.tcx.is_doc_hidden(def_id.to_def_id())
|| inherits_doc_hidden(cx.tcx, def_id) || inherits_doc_hidden(cx.tcx, def_id, None)
|| cx.tcx.def_span(def_id.to_def_id()).in_derive_expansion() || cx.tcx.def_span(def_id.to_def_id()).in_derive_expansion()
{ {
return false; return false;

View File

@ -27,6 +27,8 @@ pub(crate) struct Module<'hir> {
pub(crate) where_inner: Span, pub(crate) where_inner: Span,
pub(crate) mods: Vec<Module<'hir>>, pub(crate) mods: Vec<Module<'hir>>,
pub(crate) def_id: LocalDefId, pub(crate) def_id: LocalDefId,
pub(crate) renamed: Option<Symbol>,
pub(crate) import_id: Option<LocalDefId>,
/// The key is the item `ItemId` and the value is: (item, renamed, import_id). /// The key is the item `ItemId` and the value is: (item, renamed, import_id).
/// We use `FxIndexMap` to keep the insert order. /// We use `FxIndexMap` to keep the insert order.
pub(crate) items: FxIndexMap< pub(crate) items: FxIndexMap<
@ -37,11 +39,19 @@ pub(crate) struct Module<'hir> {
} }
impl Module<'_> { impl Module<'_> {
pub(crate) fn new(name: Symbol, def_id: LocalDefId, where_inner: Span) -> Self { pub(crate) fn new(
name: Symbol,
def_id: LocalDefId,
where_inner: Span,
renamed: Option<Symbol>,
import_id: Option<LocalDefId>,
) -> Self {
Module { Module {
name, name,
def_id, def_id,
where_inner, where_inner,
renamed,
import_id,
mods: Vec::new(), mods: Vec::new(),
items: FxIndexMap::default(), items: FxIndexMap::default(),
foreigns: Vec::new(), foreigns: Vec::new(),
@ -60,9 +70,16 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<Symbol> {
std::iter::once(crate_name).chain(relative).collect() std::iter::once(crate_name).chain(relative).collect()
} }
pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut def_id: LocalDefId) -> bool { pub(crate) fn inherits_doc_hidden(
tcx: TyCtxt<'_>,
mut def_id: LocalDefId,
stop_at: Option<LocalDefId>,
) -> bool {
let hir = tcx.hir(); let hir = tcx.hir();
while let Some(id) = tcx.opt_local_parent(def_id) { while let Some(id) = tcx.opt_local_parent(def_id) {
if let Some(stop_at) = stop_at && id == stop_at {
return false;
}
def_id = id; def_id = id;
if tcx.is_doc_hidden(def_id.to_def_id()) { if tcx.is_doc_hidden(def_id.to_def_id()) {
return true; return true;
@ -100,6 +117,8 @@ pub(crate) fn new(cx: &'a mut core::DocContext<'tcx>) -> RustdocVisitor<'a, 'tcx
cx.tcx.crate_name(LOCAL_CRATE), cx.tcx.crate_name(LOCAL_CRATE),
CRATE_DEF_ID, CRATE_DEF_ID,
cx.tcx.hir().root_module().spans.inner_span, cx.tcx.hir().root_module().spans.inner_span,
None,
None,
); );
RustdocVisitor { RustdocVisitor {
@ -260,7 +279,7 @@ fn maybe_inline_local(
let is_private = let is_private =
!self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, ori_res_did); !self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, ori_res_did);
let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did); let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did, None);
// Only inline if requested or if the item would otherwise be stripped. // Only inline if requested or if the item would otherwise be stripped.
if (!please_inline && !is_private && !is_hidden) || is_no_inline { if (!please_inline && !is_private && !is_hidden) || is_no_inline {
@ -277,7 +296,7 @@ fn maybe_inline_local(
.cache .cache
.effective_visibilities .effective_visibilities
.is_directly_public(self.cx.tcx, item_def_id.to_def_id()) && .is_directly_public(self.cx.tcx, item_def_id.to_def_id()) &&
!inherits_doc_hidden(self.cx.tcx, item_def_id) !inherits_doc_hidden(self.cx.tcx, item_def_id, None)
{ {
// The imported item is public and not `doc(hidden)` so no need to inline it. // The imported item is public and not `doc(hidden)` so no need to inline it.
return false; return false;
@ -426,7 +445,7 @@ fn visit_item_inner(
} }
} }
hir::ItemKind::Mod(ref m) => { hir::ItemKind::Mod(ref m) => {
self.enter_mod(item.owner_id.def_id, m, name); self.enter_mod(item.owner_id.def_id, m, name, renamed, import_id);
} }
hir::ItemKind::Fn(..) hir::ItemKind::Fn(..)
| hir::ItemKind::ExternCrate(..) | hir::ItemKind::ExternCrate(..)
@ -479,8 +498,15 @@ fn visit_foreign_item_inner(
/// This method will create a new module and push it onto the "modules stack" then call /// This method will create a new module and push it onto the "modules stack" then call
/// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
/// add into the list of modules of the current module. /// add into the list of modules of the current module.
fn enter_mod(&mut self, id: LocalDefId, m: &'tcx hir::Mod<'tcx>, name: Symbol) { fn enter_mod(
self.modules.push(Module::new(name, id, m.spans.inner_span)); &mut self,
id: LocalDefId,
m: &'tcx hir::Mod<'tcx>,
name: Symbol,
renamed: Option<Symbol>,
import_id: Option<LocalDefId>,
) {
self.modules.push(Module::new(name, id, m.spans.inner_span, renamed, import_id));
self.visit_mod_contents(id, m); self.visit_mod_contents(id, m);