Fix handling of items inside a doc(hidden)
block
This commit is contained in:
parent
34685485c7
commit
5b654a7e5e
@ -2225,21 +2225,17 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||||||
get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs);
|
get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !extra_attrs.is_empty() {
|
let mut item = if !extra_attrs.is_empty() {
|
||||||
extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
|
extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
|
||||||
let attrs = Attributes::from_ast(&extra_attrs);
|
let attrs = Attributes::from_ast(&extra_attrs);
|
||||||
let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
|
let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
|
||||||
|
|
||||||
vec![Item::from_def_id_and_attrs_and_parts(
|
Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg)
|
||||||
def_id,
|
|
||||||
Some(name),
|
|
||||||
kind,
|
|
||||||
Box::new(attrs),
|
|
||||||
cfg,
|
|
||||||
)]
|
|
||||||
} else {
|
} else {
|
||||||
vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
|
Item::from_def_id_and_parts(def_id, Some(name), kind, cx)
|
||||||
}
|
};
|
||||||
|
item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id());
|
||||||
|
vec![item]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
//! Strip all doc(hidden) items from the output.
|
//! Strip all doc(hidden) items from the output.
|
||||||
|
|
||||||
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
@ -7,6 +9,7 @@ use crate::clean::{Item, ItemIdSet, NestedAttributesExt};
|
|||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::fold::{strip_item, DocFolder};
|
use crate::fold::{strip_item, DocFolder};
|
||||||
use crate::passes::{ImplStripper, Pass};
|
use crate::passes::{ImplStripper, Pass};
|
||||||
|
use crate::visit_ast::inherits_doc_hidden;
|
||||||
|
|
||||||
pub(crate) const STRIP_HIDDEN: Pass = Pass {
|
pub(crate) const STRIP_HIDDEN: Pass = Pass {
|
||||||
name: "strip-hidden",
|
name: "strip-hidden",
|
||||||
@ -21,7 +24,12 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
|
|||||||
|
|
||||||
// strip all #[doc(hidden)] items
|
// strip all #[doc(hidden)] items
|
||||||
let krate = {
|
let krate = {
|
||||||
let mut stripper = Stripper { retained: &mut retained, update_retained: true };
|
let mut stripper = Stripper {
|
||||||
|
retained: &mut retained,
|
||||||
|
update_retained: true,
|
||||||
|
tcx: cx.tcx,
|
||||||
|
is_in_hidden_item: false,
|
||||||
|
};
|
||||||
stripper.fold_crate(krate)
|
stripper.fold_crate(krate)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,14 +44,38 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
|
|||||||
stripper.fold_crate(krate)
|
stripper.fold_crate(krate)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Stripper<'a> {
|
struct Stripper<'a, 'tcx> {
|
||||||
retained: &'a mut ItemIdSet,
|
retained: &'a mut ItemIdSet,
|
||||||
update_retained: bool,
|
update_retained: bool,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
is_in_hidden_item: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DocFolder for Stripper<'a> {
|
impl<'a, 'tcx> Stripper<'a, 'tcx> {
|
||||||
|
fn set_is_in_hidden_item_and_fold(&mut self, is_in_hidden_item: bool, i: Item) -> Item {
|
||||||
|
let prev = self.is_in_hidden_item;
|
||||||
|
self.is_in_hidden_item |= is_in_hidden_item;
|
||||||
|
let ret = self.fold_item_recur(i);
|
||||||
|
self.is_in_hidden_item = prev;
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
|
||||||
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||||
if i.attrs.lists(sym::doc).has_word(sym::hidden) {
|
let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden);
|
||||||
|
let mut is_hidden = self.is_in_hidden_item || has_doc_hidden;
|
||||||
|
if !is_hidden && i.inline_stmt_id.is_none() {
|
||||||
|
// We don't need to check if it's coming from a reexport since the reexport itself was
|
||||||
|
// already checked.
|
||||||
|
is_hidden = i
|
||||||
|
.item_id
|
||||||
|
.as_def_id()
|
||||||
|
.and_then(|def_id| def_id.as_local())
|
||||||
|
.map(|def_id| inherits_doc_hidden(self.tcx, def_id))
|
||||||
|
.unwrap_or(false);
|
||||||
|
}
|
||||||
|
if is_hidden {
|
||||||
debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
|
debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
|
||||||
// Use a dedicated hidden item for fields, variants, and modules.
|
// Use a dedicated hidden item for fields, variants, and modules.
|
||||||
// We need to keep private fields and variants, so that the docs
|
// We need to keep private fields and variants, so that the docs
|
||||||
@ -53,23 +85,31 @@ impl<'a> DocFolder for Stripper<'a> {
|
|||||||
// module it's defined in. Both of these are marked "stripped," and
|
// module it's defined in. Both of these are marked "stripped," and
|
||||||
// not included in the final docs, but since they still have an effect
|
// not included in the final docs, but since they still have an effect
|
||||||
// on the final doc, cannot be completely removed from the Clean IR.
|
// on the final doc, cannot be completely removed from the Clean IR.
|
||||||
match *i.kind {
|
return match *i.kind {
|
||||||
clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
|
clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
|
||||||
// We need to recurse into stripped modules to
|
// We need to recurse into stripped modules to
|
||||||
// strip things like impl methods but when doing so
|
// strip things like impl methods but when doing so
|
||||||
// we must not add any items to the `retained` set.
|
// we must not add any items to the `retained` set.
|
||||||
let old = mem::replace(&mut self.update_retained, false);
|
let old = mem::replace(&mut self.update_retained, false);
|
||||||
let ret = strip_item(self.fold_item_recur(i));
|
let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i));
|
||||||
self.update_retained = old;
|
self.update_retained = old;
|
||||||
return Some(ret);
|
Some(ret)
|
||||||
}
|
|
||||||
_ => return None,
|
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
let ret = self.set_is_in_hidden_item_and_fold(true, i);
|
||||||
|
if has_doc_hidden {
|
||||||
|
// If the item itself has `#[doc(hidden)]`, then we simply remove it.
|
||||||
|
None
|
||||||
} else {
|
} else {
|
||||||
|
// However if it's a "descendant" of a `#[doc(hidden)]` item, then we strip it.
|
||||||
|
Some(strip_item(ret))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
if self.update_retained {
|
if self.update_retained {
|
||||||
self.retained.insert(i.item_id);
|
self.retained.insert(i.item_id);
|
||||||
}
|
}
|
||||||
}
|
Some(self.set_is_in_hidden_item_and_fold(is_hidden, i))
|
||||||
Some(self.fold_item_recur(i))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,6 +187,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.inside_public_path = orig_inside_public_path;
|
self.inside_public_path = orig_inside_public_path;
|
||||||
|
debug!("Leaving module {:?}", m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to resolve the target of a `pub use` statement and inlines the
|
/// Tries to resolve the target of a `pub use` statement and inlines the
|
||||||
@ -290,7 +291,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
item: &'tcx hir::Item<'_>,
|
item: &'tcx hir::Item<'_>,
|
||||||
renamed: Option<Symbol>,
|
renamed: Option<Symbol>,
|
||||||
parent_id: Option<LocalDefId>,
|
import_id: Option<LocalDefId>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug!("visiting item {:?}", item);
|
debug!("visiting item {:?}", item);
|
||||||
let name = renamed.unwrap_or(item.ident.name);
|
let name = renamed.unwrap_or(item.ident.name);
|
||||||
@ -347,7 +348,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add_to_current_mod(item, renamed, parent_id);
|
self.add_to_current_mod(item, renamed, import_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::Macro(ref macro_def, _) => {
|
hir::ItemKind::Macro(ref macro_def, _) => {
|
||||||
@ -383,13 +384,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||||||
| hir::ItemKind::Static(..)
|
| hir::ItemKind::Static(..)
|
||||||
| hir::ItemKind::Trait(..)
|
| hir::ItemKind::Trait(..)
|
||||||
| hir::ItemKind::TraitAlias(..) => {
|
| hir::ItemKind::TraitAlias(..) => {
|
||||||
self.add_to_current_mod(item, renamed, parent_id);
|
self.add_to_current_mod(item, renamed, import_id);
|
||||||
}
|
}
|
||||||
hir::ItemKind::Const(..) => {
|
hir::ItemKind::Const(..) => {
|
||||||
// Underscore constants do not correspond to a nameable item and
|
// Underscore constants do not correspond to a nameable item and
|
||||||
// so are never useful in documentation.
|
// so are never useful in documentation.
|
||||||
if name != kw::Underscore {
|
if name != kw::Underscore {
|
||||||
self.add_to_current_mod(item, renamed, parent_id);
|
self.add_to_current_mod(item, renamed, import_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::Impl(impl_) => {
|
hir::ItemKind::Impl(impl_) => {
|
||||||
@ -437,12 +438,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
|
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
|
||||||
let parent_id = if self.modules.len() > 1 {
|
if self.visit_item_inner(i, None, None) {
|
||||||
Some(self.modules[self.modules.len() - 2].def_id)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
if self.visit_item_inner(i, None, parent_id) {
|
|
||||||
walk_item(self, i);
|
walk_item(self, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user