未验证 提交 7d247c92 编写于 作者: D Dylan DPC 提交者: GitHub

Rollup merge of #80368 - camelid:rustdoc-succinct-vis, r=jyn514

rustdoc: Render visibilities succinctly

Fixes #79139.

r? `@jyn514`
...@@ -2325,18 +2325,19 @@ fn clean(&self, cx: &DocContext<'_>) -> Item { ...@@ -2325,18 +2325,19 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
) )
} else { } else {
let vis = item.vis.clean(cx); let vis = item.vis.clean(cx);
let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id();
if matchers.len() <= 1 { if matchers.len() <= 1 {
format!( format!(
"{}macro {}{} {{\n ...\n}}", "{}macro {}{} {{\n ...\n}}",
vis.print_with_space(cx.tcx), vis.print_with_space(cx.tcx, def_id),
name, name,
matchers.iter().map(|span| span.to_src(cx)).collect::<String>(), matchers.iter().map(|span| span.to_src(cx)).collect::<String>(),
) )
} else { } else {
format!( format!(
"{}macro {} {{\n{}}}", "{}macro {} {{\n{}}}",
vis.print_with_space(cx.tcx), vis.print_with_space(cx.tcx, def_id),
name, name,
matchers matchers
.iter() .iter()
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::mir::interpret::ConstValue; use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, Ty}; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::symbol::{kw, sym, Symbol};
use std::mem; use std::mem;
...@@ -623,3 +623,24 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const ...@@ -623,3 +623,24 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const
*cx.impl_trait_bounds.borrow_mut() = old_bounds; *cx.impl_trait_bounds.borrow_mut() = old_bounds;
r r
} }
/// Find the nearest parent module of a [`DefId`].
///
/// **Panics if the item it belongs to [is fake][Item::is_fake].**
crate fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
if def_id.is_top_level_module() {
// The crate root has no parent. Use it as the root instead.
Some(def_id)
} else {
let mut current = def_id;
// The immediate parent might not always be a module.
// Find the first parent which is.
while let Some(parent) = tcx.parent(current) {
if tcx.def_kind(parent) == DefKind::Mod {
return Some(parent);
}
current = parent;
}
None
}
}
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
use rustc_span::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_span::def_id::{DefId, CRATE_DEF_INDEX};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use crate::clean::{self, PrimitiveType}; use crate::clean::{self, utils::find_nearest_parent_module, PrimitiveType};
use crate::formats::cache::cache; use crate::formats::cache::cache;
use crate::formats::item_type::ItemType; use crate::formats::item_type::ItemType;
use crate::html::escape::Escape; use crate::html::escape::Escape;
...@@ -1085,32 +1085,54 @@ impl Function<'_> { ...@@ -1085,32 +1085,54 @@ impl Function<'_> {
} }
impl clean::Visibility { impl clean::Visibility {
crate fn print_with_space<'tcx>(self, tcx: TyCtxt<'tcx>) -> impl fmt::Display + 'tcx { crate fn print_with_space<'tcx>(
self,
tcx: TyCtxt<'tcx>,
item_did: DefId,
) -> impl fmt::Display + 'tcx {
use rustc_span::symbol::kw; use rustc_span::symbol::kw;
display_fn(move |f| match self { display_fn(move |f| match self {
clean::Public => f.write_str("pub "), clean::Public => f.write_str("pub "),
clean::Inherited => Ok(()), clean::Inherited => Ok(()),
clean::Visibility::Restricted(did) if did.index == CRATE_DEF_INDEX => {
write!(f, "pub(crate) ") clean::Visibility::Restricted(vis_did) => {
} // FIXME(camelid): This may not work correctly if `item_did` is a module.
clean::Visibility::Restricted(did) => { // However, rustdoc currently never displays a module's
f.write_str("pub(")?; // visibility, so it shouldn't matter.
let path = tcx.def_path(did); let parent_module = find_nearest_parent_module(tcx, item_did);
debug!("path={:?}", path);
let first_name = if vis_did.index == CRATE_DEF_INDEX {
path.data[0].data.get_opt_name().expect("modules are always named"); write!(f, "pub(crate) ")
if path.data.len() != 1 || (first_name != kw::SelfLower && first_name != kw::Super) } else if parent_module == Some(vis_did) {
// `pub(in foo)` where `foo` is the parent module
// is the same as no visibility modifier
Ok(())
} else if parent_module
.map(|parent| find_nearest_parent_module(tcx, parent))
.flatten()
== Some(vis_did)
{ {
f.write_str("in ")?; write!(f, "pub(super) ")
} } else {
// modified from `resolved_path()` to work with `DefPathData` f.write_str("pub(")?;
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); let path = tcx.def_path(vis_did);
for seg in &path.data[..path.data.len() - 1] { debug!("path={:?}", path);
write!(f, "{}::", seg.data.get_opt_name().unwrap())?; let first_name =
path.data[0].data.get_opt_name().expect("modules are always named");
if path.data.len() != 1
|| (first_name != kw::SelfLower && first_name != kw::Super)
{
f.write_str("in ")?;
}
// modified from `resolved_path()` to work with `DefPathData`
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
for seg in &path.data[..path.data.len() - 1] {
write!(f, "{}::", seg.data.get_opt_name().unwrap())?;
}
let path = anchor(vis_did, &last_name.as_str()).to_string();
write!(f, "{}) ", path)
} }
let path = anchor(did, &last_name.as_str()).to_string();
write!(f, "{}) ", path)
} }
}) })
} }
......
...@@ -2157,14 +2157,14 @@ fn cmp( ...@@ -2157,14 +2157,14 @@ fn cmp(
Some(ref src) => write!( Some(ref src) => write!(
w, w,
"<tr><td><code>{}extern crate {} as {};", "<tr><td><code>{}extern crate {} as {};",
myitem.visibility.print_with_space(cx.tcx()), myitem.visibility.print_with_space(cx.tcx(), myitem.def_id),
anchor(myitem.def_id, &*src.as_str()), anchor(myitem.def_id, &*src.as_str()),
name name
), ),
None => write!( None => write!(
w, w,
"<tr><td><code>{}extern crate {};", "<tr><td><code>{}extern crate {};",
myitem.visibility.print_with_space(cx.tcx()), myitem.visibility.print_with_space(cx.tcx(), myitem.def_id),
anchor(myitem.def_id, &*name.as_str()) anchor(myitem.def_id, &*name.as_str())
), ),
} }
...@@ -2175,7 +2175,7 @@ fn cmp( ...@@ -2175,7 +2175,7 @@ fn cmp(
write!( write!(
w, w,
"<tr><td><code>{}{}</code></td></tr>", "<tr><td><code>{}{}</code></td></tr>",
myitem.visibility.print_with_space(cx.tcx()), myitem.visibility.print_with_space(cx.tcx(), myitem.def_id),
import.print() import.print()
); );
} }
...@@ -2392,7 +2392,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean:: ...@@ -2392,7 +2392,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
write!( write!(
w, w,
"{vis}const {name}: {typ}", "{vis}const {name}: {typ}",
vis = it.visibility.print_with_space(cx.tcx()), vis = it.visibility.print_with_space(cx.tcx(), it.def_id),
name = it.name.as_ref().unwrap(), name = it.name.as_ref().unwrap(),
typ = c.type_.print(), typ = c.type_.print(),
); );
...@@ -2426,7 +2426,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St ...@@ -2426,7 +2426,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
write!( write!(
w, w,
"{vis}static {mutability}{name}: {typ}</pre>", "{vis}static {mutability}{name}: {typ}</pre>",
vis = it.visibility.print_with_space(cx.tcx()), vis = it.visibility.print_with_space(cx.tcx(), it.def_id),
mutability = s.mutability.print_with_space(), mutability = s.mutability.print_with_space(),
name = it.name.as_ref().unwrap(), name = it.name.as_ref().unwrap(),
typ = s.type_.print() typ = s.type_.print()
...@@ -2437,7 +2437,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St ...@@ -2437,7 +2437,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) { fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
let header_len = format!( let header_len = format!(
"{}{}{}{}{:#}fn {}{:#}", "{}{}{}{}{:#}fn {}{:#}",
it.visibility.print_with_space(cx.tcx()), it.visibility.print_with_space(cx.tcx(), it.def_id),
f.header.constness.print_with_space(), f.header.constness.print_with_space(),
f.header.asyncness.print_with_space(), f.header.asyncness.print_with_space(),
f.header.unsafety.print_with_space(), f.header.unsafety.print_with_space(),
...@@ -2452,7 +2452,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean:: ...@@ -2452,7 +2452,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
w, w,
"{vis}{constness}{asyncness}{unsafety}{abi}fn \ "{vis}{constness}{asyncness}{unsafety}{abi}fn \
{name}{generics}{decl}{spotlight}{where_clause}</pre>", {name}{generics}{decl}{spotlight}{where_clause}</pre>",
vis = it.visibility.print_with_space(cx.tcx()), vis = it.visibility.print_with_space(cx.tcx(), it.def_id),
constness = f.header.constness.print_with_space(), constness = f.header.constness.print_with_space(),
asyncness = f.header.asyncness.print_with_space(), asyncness = f.header.asyncness.print_with_space(),
unsafety = f.header.unsafety.print_with_space(), unsafety = f.header.unsafety.print_with_space(),
...@@ -2578,7 +2578,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra ...@@ -2578,7 +2578,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
write!( write!(
w, w,
"{}{}{}trait {}{}{}", "{}{}{}trait {}{}{}",
it.visibility.print_with_space(cx.tcx()), it.visibility.print_with_space(cx.tcx(), it.def_id),
t.unsafety.print_with_space(), t.unsafety.print_with_space(),
if t.is_auto { "auto " } else { "" }, if t.is_auto { "auto " } else { "" },
it.name.as_ref().unwrap(), it.name.as_ref().unwrap(),
...@@ -2896,7 +2896,7 @@ fn assoc_const( ...@@ -2896,7 +2896,7 @@ fn assoc_const(
w, w,
"{}{}const <a href=\"{}\" class=\"constant\"><b>{}</b></a>: {}", "{}{}const <a href=\"{}\" class=\"constant\"><b>{}</b></a>: {}",
extra, extra,
it.visibility.print_with_space(cx.tcx()), it.visibility.print_with_space(cx.tcx(), it.def_id),
naive_assoc_href(it, link), naive_assoc_href(it, link),
it.name.as_ref().unwrap(), it.name.as_ref().unwrap(),
ty.print() ty.print()
...@@ -3015,7 +3015,7 @@ fn method( ...@@ -3015,7 +3015,7 @@ fn method(
}; };
let mut header_len = format!( let mut header_len = format!(
"{}{}{}{}{}{:#}fn {}{:#}", "{}{}{}{}{}{:#}fn {}{:#}",
meth.visibility.print_with_space(cx.tcx()), meth.visibility.print_with_space(cx.tcx(), meth.def_id),
header.constness.print_with_space(), header.constness.print_with_space(),
header.asyncness.print_with_space(), header.asyncness.print_with_space(),
header.unsafety.print_with_space(), header.unsafety.print_with_space(),
...@@ -3037,7 +3037,7 @@ fn method( ...@@ -3037,7 +3037,7 @@ fn method(
"{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\ "{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\
{generics}{decl}{spotlight}{where_clause}", {generics}{decl}{spotlight}{where_clause}",
if parent == ItemType::Trait { " " } else { "" }, if parent == ItemType::Trait { " " } else { "" },
meth.visibility.print_with_space(cx.tcx()), meth.visibility.print_with_space(cx.tcx(), meth.def_id),
header.constness.print_with_space(), header.constness.print_with_space(),
header.asyncness.print_with_space(), header.asyncness.print_with_space(),
header.unsafety.print_with_space(), header.unsafety.print_with_space(),
...@@ -3189,7 +3189,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum ...@@ -3189,7 +3189,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
write!( write!(
w, w,
"{}enum {}{}{}", "{}enum {}{}{}",
it.visibility.print_with_space(cx.tcx()), it.visibility.print_with_space(cx.tcx(), it.def_id),
it.name.as_ref().unwrap(), it.name.as_ref().unwrap(),
e.generics.print(), e.generics.print(),
WhereClause { gens: &e.generics, indent: 0, end_newline: true } WhereClause { gens: &e.generics, indent: 0, end_newline: true }
...@@ -3365,7 +3365,7 @@ fn render_struct( ...@@ -3365,7 +3365,7 @@ fn render_struct(
write!( write!(
w, w,
"{}{}{}", "{}{}{}",
it.visibility.print_with_space(cx.tcx()), it.visibility.print_with_space(cx.tcx(), it.def_id),
if structhead { "struct " } else { "" }, if structhead { "struct " } else { "" },
it.name.as_ref().unwrap() it.name.as_ref().unwrap()
); );
...@@ -3385,7 +3385,7 @@ fn render_struct( ...@@ -3385,7 +3385,7 @@ fn render_struct(
w, w,
"\n{} {}{}: {},", "\n{} {}{}: {},",
tab, tab,
field.visibility.print_with_space(cx.tcx()), field.visibility.print_with_space(cx.tcx(), field.def_id),
field.name.as_ref().unwrap(), field.name.as_ref().unwrap(),
ty.print() ty.print()
); );
...@@ -3414,7 +3414,12 @@ fn render_struct( ...@@ -3414,7 +3414,12 @@ fn render_struct(
match *field.kind { match *field.kind {
clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"), clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"),
clean::StructFieldItem(ref ty) => { clean::StructFieldItem(ref ty) => {
write!(w, "{}{}", field.visibility.print_with_space(cx.tcx()), ty.print()) write!(
w,
"{}{}",
field.visibility.print_with_space(cx.tcx(), field.def_id),
ty.print()
)
} }
_ => unreachable!(), _ => unreachable!(),
} }
...@@ -3447,7 +3452,7 @@ fn render_union( ...@@ -3447,7 +3452,7 @@ fn render_union(
write!( write!(
w, w,
"{}{}{}", "{}{}{}",
it.visibility.print_with_space(cx.tcx()), it.visibility.print_with_space(cx.tcx(), it.def_id),
if structhead { "union " } else { "" }, if structhead { "union " } else { "" },
it.name.as_ref().unwrap() it.name.as_ref().unwrap()
); );
...@@ -3462,7 +3467,7 @@ fn render_union( ...@@ -3462,7 +3467,7 @@ fn render_union(
write!( write!(
w, w,
" {}{}: {},\n{}", " {}{}: {},\n{}",
field.visibility.print_with_space(cx.tcx()), field.visibility.print_with_space(cx.tcx(), field.def_id),
field.name.as_ref().unwrap(), field.name.as_ref().unwrap(),
ty.print(), ty.print(),
tab tab
...@@ -4101,7 +4106,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, cache: ...@@ -4101,7 +4106,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, cache:
write!( write!(
w, w,
" {}type {};\n}}</pre>", " {}type {};\n}}</pre>",
it.visibility.print_with_space(cx.tcx()), it.visibility.print_with_space(cx.tcx(), it.def_id),
it.name.as_ref().unwrap(), it.name.as_ref().unwrap(),
); );
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
use std::mem; use std::mem;
use std::ops::Range; use std::ops::Range;
use crate::clean::{self, Crate, Item, ItemLink, PrimitiveType}; use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType};
use crate::core::DocContext; use crate::core::DocContext;
use crate::fold::DocFolder; use crate::fold::DocFolder;
use crate::html::markdown::markdown_links; use crate::html::markdown::markdown_links;
...@@ -830,31 +830,9 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> { ...@@ -830,31 +830,9 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
use rustc_middle::ty::DefIdTree; use rustc_middle::ty::DefIdTree;
let parent_node = if item.is_fake() { let parent_node = if item.is_fake() {
// FIXME: is this correct?
None None
// If we're documenting the crate root itself, it has no parent. Use the root instead.
} else if item.def_id.is_top_level_module() {
Some(item.def_id)
} else { } else {
let mut current = item.def_id; find_nearest_parent_module(self.cx.tcx, item.def_id)
// The immediate parent might not always be a module.
// Find the first parent which is.
loop {
if let Some(parent) = self.cx.tcx.parent(current) {
if self.cx.tcx.def_kind(parent) == DefKind::Mod {
break Some(parent);
}
current = parent;
} else {
debug!(
"{:?} has no parent (kind={:?}, original was {:?})",
current,
self.cx.tcx.def_kind(current),
item.def_id
);
break None;
}
}
}; };
if parent_node.is_some() { if parent_node.is_some() {
......
...@@ -14,19 +14,31 @@ ...@@ -14,19 +14,31 @@
pub(self) struct FooSelf; pub(self) struct FooSelf;
// @has 'foo/struct.FooInSelf.html' '//pre' 'pub(crate) struct FooInSelf' // @has 'foo/struct.FooInSelf.html' '//pre' 'pub(crate) struct FooInSelf'
pub(in self) struct FooInSelf; pub(in self) struct FooInSelf;
// @has 'foo/struct.FooPriv.html' '//pre' 'pub(crate) struct FooPriv'
struct FooPriv;
mod a { mod a {
// @has 'foo/a/struct.FooSuper.html' '//pre' 'pub(crate) struct FooSuper' // @has 'foo/a/struct.FooASuper.html' '//pre' 'pub(crate) struct FooASuper'
pub(super) struct FooSuper; pub(super) struct FooASuper;
// @has 'foo/a/struct.FooInSuper.html' '//pre' 'pub(crate) struct FooInSuper' // @has 'foo/a/struct.FooAInSuper.html' '//pre' 'pub(crate) struct FooAInSuper'
pub(in super) struct FooInSuper; pub(in super) struct FooAInSuper;
// @has 'foo/a/struct.FooInA.html' '//pre' 'pub(in a) struct FooInA' // @has 'foo/a/struct.FooAInA.html' '//pre' 'struct FooAInA'
pub(in a) struct FooInA; // @!has 'foo/a/struct.FooAInA.html' '//pre' 'pub'
pub(in a) struct FooAInA;
// @has 'foo/a/struct.FooAPriv.html' '//pre' 'struct FooAPriv'
// @!has 'foo/a/struct.FooAPriv.html' '//pre' 'pub'
struct FooAPriv;
mod b { mod b {
// @has 'foo/a/b/struct.FooInSelfSuperB.html' '//pre' 'pub(in a::b) struct FooInSelfSuperB' // @has 'foo/a/b/struct.FooBSuper.html' '//pre' 'pub(super) struct FooBSuper'
pub(in a::b) struct FooInSelfSuperB; pub(super) struct FooBSuper;
// @has 'foo/a/b/struct.FooInSuperSuper.html' '//pre' 'pub(crate) struct FooInSuperSuper' // @has 'foo/a/b/struct.FooBInSuperSuper.html' '//pre' 'pub(crate) struct FooBInSuperSuper'
pub(in super::super) struct FooInSuperSuper; pub(in super::super) struct FooBInSuperSuper;
// @has 'foo/a/b/struct.FooInAB.html' '//pre' 'pub(in a::b) struct FooInAB' // @has 'foo/a/b/struct.FooBInAB.html' '//pre' 'struct FooBInAB'
pub(in a::b) struct FooInAB; // @!has 'foo/a/b/struct.FooBInAB.html' '//pre' 'pub'
pub(in a::b) struct FooBInAB;
// @has 'foo/a/b/struct.FooBPriv.html' '//pre' 'struct FooBPriv'
// @!has 'foo/a/b/struct.FooBPriv.html' '//pre' 'pub'
struct FooBPriv;
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册