1
Fork 0

Auto merge of #86841 - GuillaumeGomez:reexported-macro-2-render, r=Stupremee

Fix rendering of reexported macros 2.0 and fix visibility of reexported items

So, this PR grew a bit out of focus, it does the following things:

* Fixes #86276.
* Fixes visibility display for reexported items: it now takes the visibility of the "use" statement rather than the visibility of the reexported item itself).
* Fixes the display of reexported items if "--document-private-items" option is used. Before, they were simply skipped.
* Fixes inconsistency on typedef items: they didn't display their visibility contrary to other items.

I added tests to check everything listed above.

cc `@camelid` `@ollie27` (in case one of you want to review?)

r? `@jyn514`
This commit is contained in:
bors 2021-07-12 11:52:55 +00:00
commit 3a24abd22f
7 changed files with 232 additions and 56 deletions

View file

@ -41,6 +41,7 @@ type Attrs<'hir> = rustc_middle::ty::Attributes<'hir>;
crate fn try_inline(
cx: &mut DocContext<'_>,
parent_module: DefId,
import_def_id: Option<DefId>,
res: Res,
name: Symbol,
attrs: Option<Attrs<'_>>,
@ -108,7 +109,7 @@ crate fn try_inline(
clean::ConstantItem(build_const(cx, did))
}
Res::Def(DefKind::Macro(kind), did) => {
let mac = build_macro(cx, did, name);
let mac = build_macro(cx, did, name, import_def_id);
let type_kind = match kind {
MacroKind::Bang => ItemType::Macro,
@ -123,14 +124,13 @@ crate fn try_inline(
let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone);
cx.inlined.insert(did.into());
ret.push(clean::Item::from_def_id_and_attrs_and_parts(
did,
Some(name),
kind,
box attrs,
cx,
cfg,
));
let mut item =
clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, box attrs, cx, cfg);
if let Some(import_def_id) = import_def_id {
// The visibility needs to reflect the one from the reexport and not from the "source" DefId.
item.visibility = cx.tcx.visibility(import_def_id).clean(cx);
}
ret.push(item);
Some(ret)
}
@ -509,7 +509,9 @@ fn build_module(
)),
cfg: None,
});
} else if let Some(i) = try_inline(cx, did, item.res, item.ident.name, None, visited) {
} else if let Some(i) =
try_inline(cx, did, None, item.res, item.ident.name, None, visited)
{
items.extend(i)
}
}
@ -543,21 +545,26 @@ fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::St
}
}
fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::ItemKind {
let imported_from = cx.tcx.crate_name(did.krate);
match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) {
LoadedMacro::MacroDef(def, _) => {
if let ast::ItemKind::MacroDef(ref def) = def.kind {
let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
let matchers = tts.chunks(4).map(|arm| &arm[0]);
let source = format!(
"macro_rules! {} {{\n{}}}",
name,
utils::render_macro_arms(matchers, ";")
);
clean::MacroItem(clean::Macro { source, imported_from: Some(imported_from) })
fn build_macro(
cx: &mut DocContext<'_>,
def_id: DefId,
name: Symbol,
import_def_id: Option<DefId>,
) -> clean::ItemKind {
let imported_from = cx.tcx.crate_name(def_id.krate);
match cx.enter_resolver(|r| r.cstore().load_macro_untracked(def_id, cx.sess())) {
LoadedMacro::MacroDef(item_def, _) => {
if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
clean::MacroItem(clean::Macro {
source: utils::display_macro_source(
cx,
name,
def,
def_id,
cx.tcx.visibility(import_def_id.unwrap_or(def_id)),
),
imported_from: Some(imported_from),
})
} else {
unreachable!()
}

View file

@ -1997,6 +1997,7 @@ fn clean_extern_crate(
if let Some(items) = inline::try_inline(
cx,
cx.tcx.parent_module(krate.hir_id()).to_def_id(),
Some(krate.def_id.to_def_id()),
res,
name,
Some(attrs),
@ -2052,7 +2053,8 @@ fn clean_use_statement(
// forcefully don't inline if this is not public or if the
// #[doc(no_inline)] attribute is present.
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
let mut denied = !import.vis.node.is_pub()
let mut denied = !(import.vis.node.is_pub()
|| (cx.render_options.document_private && import.vis.node.is_pub_restricted()))
|| pub_underscore
|| attrs.iter().any(|a| {
a.has_name(sym::doc)
@ -2088,17 +2090,19 @@ fn clean_use_statement(
}
if !denied {
let mut visited = FxHashSet::default();
let import_def_id = import.def_id.to_def_id();
if let Some(mut items) = inline::try_inline(
cx,
cx.tcx.parent_module(import.hir_id()).to_def_id(),
Some(import_def_id),
path.res,
name,
Some(attrs),
&mut visited,
) {
items.push(Item::from_def_id_and_parts(
import.def_id.to_def_id(),
import_def_id,
None,
ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
cx,
@ -2157,37 +2161,15 @@ impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let (item, renamed) = self;
let name = renamed.unwrap_or(item.ident.name);
let tts = item.ast.body.inner_tokens().trees().collect::<Vec<_>>();
// Extract the macro's matchers. They represent the "interface" of the macro.
let matchers = tts.chunks(4).map(|arm| &arm[0]);
let source = if item.ast.macro_rules {
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
} else {
let vis = item.vis.clean(cx);
let def_id = item.def_id.to_def_id();
if matchers.len() <= 1 {
format!(
"{}macro {}{} {{\n ...\n}}",
vis.to_src_with_space(cx.tcx, def_id),
name,
matchers.map(render_macro_matcher).collect::<String>(),
)
} else {
format!(
"{}macro {} {{\n{}}}",
vis.to_src_with_space(cx.tcx, def_id),
name,
render_macro_arms(matchers, ","),
)
}
};
let def_id = item.def_id.to_def_id();
Item::from_hir_id_and_parts(
item.hir_id(),
Some(name),
MacroItem(Macro { source, imported_from: None }),
MacroItem(Macro {
source: display_macro_source(cx, name, &item.ast, def_id, &item.vis),
imported_from: None,
}),
cx,
)
}

View file

@ -3,10 +3,12 @@ use crate::clean::blanket_impl::BlanketImplFinder;
use crate::clean::{
inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
Visibility,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
use rustc_ast as ast;
use rustc_ast::tokenstream::TokenTree;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
@ -577,3 +579,37 @@ pub(super) fn render_macro_arms<'a>(
pub(super) fn render_macro_matcher(matcher: &TokenTree) -> String {
rustc_ast_pretty::pprust::tt_to_string(matcher)
}
pub(super) fn display_macro_source(
cx: &mut DocContext<'_>,
name: Symbol,
def: &ast::MacroDef,
def_id: DefId,
vis: impl Clean<Visibility>,
) -> String {
let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
// Extract the spans of all matchers. They represent the "interface" of the macro.
let matchers = tts.chunks(4).map(|arm| &arm[0]);
if def.macro_rules {
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
} else {
let vis = vis.clean(cx);
if matchers.len() <= 1 {
format!(
"{}macro {}{} {{\n ...\n}}",
vis.to_src_with_space(cx.tcx, def_id),
name,
matchers.map(render_macro_matcher).collect::<String>(),
)
} else {
format!(
"{}macro {} {{\n{}}}",
vis.to_src_with_space(cx.tcx, def_id),
name,
render_macro_arms(matchers, ","),
)
}
}
}