mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 23:34:48 +00:00
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:
commit
3a24abd22f
@ -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!()
|
||||
}
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
@ -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, ","),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer,
|
||||
clean::StructItem(ref s) => item_struct(buf, cx, item, s),
|
||||
clean::UnionItem(ref s) => item_union(buf, cx, item, s),
|
||||
clean::EnumItem(ref e) => item_enum(buf, cx, item, e),
|
||||
clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t),
|
||||
clean::TypedefItem(ref t, is_associated) => item_typedef(buf, cx, item, t, is_associated),
|
||||
clean::MacroItem(ref m) => item_macro(buf, cx, item, m),
|
||||
clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m),
|
||||
clean::PrimitiveItem(_) => item_primitive(buf, cx, item),
|
||||
@ -837,9 +837,18 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
|
||||
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
|
||||
}
|
||||
|
||||
fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
|
||||
fn item_typedef(
|
||||
w: &mut Buffer,
|
||||
cx: &Context<'_>,
|
||||
it: &clean::Item,
|
||||
t: &clean::Typedef,
|
||||
is_associated: bool,
|
||||
) {
|
||||
w.write_str("<pre class=\"rust typedef\">");
|
||||
render_attributes_in_pre(w, it, "");
|
||||
if !is_associated {
|
||||
write!(w, "{}", it.visibility.print_with_space(it.def_id, cx));
|
||||
}
|
||||
write!(
|
||||
w,
|
||||
"type {}{}{where_clause} = {type_};</pre>",
|
||||
|
42
src/test/rustdoc/auxiliary/reexports.rs
Normal file
42
src/test/rustdoc/auxiliary/reexports.rs
Normal file
@ -0,0 +1,42 @@
|
||||
#![feature(decl_macro)]
|
||||
|
||||
pub macro addr_of($place:expr) {
|
||||
&raw const $place
|
||||
}
|
||||
|
||||
pub macro addr_of_self($place:expr) {
|
||||
&raw const $place
|
||||
}
|
||||
|
||||
pub macro addr_of_crate($place:expr) {
|
||||
&raw const $place
|
||||
}
|
||||
|
||||
pub struct Foo;
|
||||
pub struct FooSelf;
|
||||
pub struct FooCrate;
|
||||
|
||||
pub enum Bar { Foo, }
|
||||
pub enum BarSelf { Foo, }
|
||||
pub enum BarCrate { Foo, }
|
||||
|
||||
pub fn foo() {}
|
||||
pub fn foo_self() {}
|
||||
pub fn foo_crate() {}
|
||||
|
||||
pub type Type = i32;
|
||||
pub type TypeSelf = i32;
|
||||
pub type TypeCrate = i32;
|
||||
|
||||
pub union Union {
|
||||
a: i8,
|
||||
b: i8,
|
||||
}
|
||||
pub union UnionSelf {
|
||||
a: i8,
|
||||
b: i8,
|
||||
}
|
||||
pub union UnionCrate {
|
||||
a: i8,
|
||||
b: i8,
|
||||
}
|
53
src/test/rustdoc/reexports-priv.rs
Normal file
53
src/test/rustdoc/reexports-priv.rs
Normal file
@ -0,0 +1,53 @@
|
||||
// aux-build: reexports.rs
|
||||
// compile-flags: --document-private-items
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
extern crate reexports;
|
||||
|
||||
// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {'
|
||||
pub use reexports::addr_of;
|
||||
// @has 'foo/macro.addr_of_crate.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_crate($place : expr) {'
|
||||
pub(crate) use reexports::addr_of_crate;
|
||||
// @has 'foo/macro.addr_of_self.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_self($place : expr) {'
|
||||
pub(self) use reexports::addr_of_self;
|
||||
|
||||
// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;'
|
||||
pub use reexports::Foo;
|
||||
// @has 'foo/struct.FooCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooCrate;'
|
||||
pub(crate) use reexports::FooCrate;
|
||||
// @has 'foo/struct.FooSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooSelf;'
|
||||
pub(self) use reexports::FooSelf;
|
||||
|
||||
// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {'
|
||||
pub use reexports::Bar;
|
||||
// @has 'foo/enum.BarCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarCrate {'
|
||||
pub(crate) use reexports::BarCrate;
|
||||
// @has 'foo/enum.BarSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarSelf {'
|
||||
pub(self) use reexports::BarSelf;
|
||||
|
||||
// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
|
||||
pub use reexports::foo;
|
||||
// @has 'foo/fn.foo_crate.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_crate()'
|
||||
pub(crate) use reexports::foo_crate;
|
||||
// @has 'foo/fn.foo_self.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_self()'
|
||||
pub(self) use reexports::foo_self;
|
||||
|
||||
// @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type ='
|
||||
pub use reexports::Type;
|
||||
// @has 'foo/type.TypeCrate.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeCrate ='
|
||||
pub(crate) use reexports::TypeCrate;
|
||||
// @has 'foo/type.TypeSelf.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeSelf ='
|
||||
pub(self) use reexports::TypeSelf;
|
||||
|
||||
// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {'
|
||||
pub use reexports::Union;
|
||||
// @has 'foo/union.UnionCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionCrate {'
|
||||
pub(crate) use reexports::UnionCrate;
|
||||
// @has 'foo/union.UnionSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionSelf {'
|
||||
pub(self) use reexports::UnionSelf;
|
||||
|
||||
pub mod foo {
|
||||
// @!has 'foo/foo/union.Union.html'
|
||||
use crate::reexports::Union;
|
||||
}
|
47
src/test/rustdoc/reexports.rs
Normal file
47
src/test/rustdoc/reexports.rs
Normal file
@ -0,0 +1,47 @@
|
||||
// aux-build: reexports.rs
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
extern crate reexports;
|
||||
|
||||
// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {'
|
||||
pub use reexports::addr_of;
|
||||
// @!has 'foo/macro.addr_of_crate.html'
|
||||
pub(crate) use reexports::addr_of_crate;
|
||||
// @!has 'foo/macro.addr_of_self.html'
|
||||
pub(self) use reexports::addr_of_self;
|
||||
|
||||
// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;'
|
||||
pub use reexports::Foo;
|
||||
// @!has 'foo/struct.FooCrate.html'
|
||||
pub(crate) use reexports::FooCrate;
|
||||
// @!has 'foo/struct.FooSelf.html'
|
||||
pub(self) use reexports::FooSelf;
|
||||
|
||||
// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {'
|
||||
pub use reexports::Bar;
|
||||
// @!has 'foo/enum.BarCrate.html'
|
||||
pub(crate) use reexports::BarCrate;
|
||||
// @!has 'foo/enum.BarSelf.html'
|
||||
pub(self) use reexports::BarSelf;
|
||||
|
||||
// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
|
||||
pub use reexports::foo;
|
||||
// @!has 'foo/fn.foo_crate.html'
|
||||
pub(crate) use reexports::foo_crate;
|
||||
// @!has 'foo/fn.foo_self.html'
|
||||
pub(self) use reexports::foo_self;
|
||||
|
||||
// @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type ='
|
||||
pub use reexports::Type;
|
||||
// @!has 'foo/type.TypeCrate.html'
|
||||
pub(crate) use reexports::TypeCrate;
|
||||
// @!has 'foo/type.TypeSelf.html'
|
||||
pub(self) use reexports::TypeSelf;
|
||||
|
||||
// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {'
|
||||
pub use reexports::Union;
|
||||
// @!has 'foo/union.UnionCrate.html'
|
||||
pub(crate) use reexports::UnionCrate;
|
||||
// @!has 'foo/union.UnionSelf.html'
|
||||
pub(self) use reexports::UnionSelf;
|
Loading…
Reference in New Issue
Block a user