rustdoc: Treat decl macros like other items
This commit is contained in:
parent
143ce0920a
commit
9016711bf1
9 changed files with 31 additions and 102 deletions
|
@ -134,11 +134,7 @@ pub(crate) fn try_inline(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::Macro(kind), did) => {
|
Res::Def(DefKind::Macro(kind), did) => {
|
||||||
let is_doc_hidden = cx.tcx.is_doc_hidden(did)
|
let mac = build_macro(cx, did, name, kind);
|
||||||
|| attrs_without_docs
|
|
||||||
.map(|(attrs, _)| attrs)
|
|
||||||
.is_some_and(|attrs| utils::attrs_have_doc_flag(attrs.iter(), sym::hidden));
|
|
||||||
let mac = build_macro(cx, did, name, import_def_id, kind, is_doc_hidden);
|
|
||||||
|
|
||||||
let type_kind = match kind {
|
let type_kind = match kind {
|
||||||
MacroKind::Bang => ItemType::Macro,
|
MacroKind::Bang => ItemType::Macro,
|
||||||
|
@ -740,18 +736,14 @@ fn build_macro(
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
import_def_id: Option<LocalDefId>,
|
|
||||||
macro_kind: MacroKind,
|
macro_kind: MacroKind,
|
||||||
is_doc_hidden: bool,
|
|
||||||
) -> clean::ItemKind {
|
) -> clean::ItemKind {
|
||||||
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
|
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
|
||||||
LoadedMacro::MacroDef { def, .. } => match macro_kind {
|
LoadedMacro::MacroDef { def, .. } => match macro_kind {
|
||||||
MacroKind::Bang => {
|
MacroKind::Bang => clean::MacroItem(clean::Macro {
|
||||||
let vis = cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id));
|
source: utils::display_macro_source(cx, name, &def),
|
||||||
clean::MacroItem(clean::Macro {
|
macro_rules: def.macro_rules,
|
||||||
source: utils::display_macro_source(cx, name, &def, def_id, vis, is_doc_hidden),
|
}),
|
||||||
})
|
|
||||||
}
|
|
||||||
MacroKind::Derive | MacroKind::Attr => {
|
MacroKind::Derive | MacroKind::Attr => {
|
||||||
clean::ProcMacroItem(clean::ProcMacro { kind: macro_kind, helpers: Vec::new() })
|
clean::ProcMacroItem(clean::ProcMacro { kind: macro_kind, helpers: Vec::new() })
|
||||||
}
|
}
|
||||||
|
|
|
@ -2787,13 +2787,10 @@ fn clean_maybe_renamed_item<'tcx>(
|
||||||
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
|
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
|
||||||
}),
|
}),
|
||||||
ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
|
ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
|
||||||
ItemKind::Macro(macro_def, MacroKind::Bang) => {
|
ItemKind::Macro(macro_def, MacroKind::Bang) => MacroItem(Macro {
|
||||||
let ty_vis = cx.tcx.visibility(def_id);
|
source: display_macro_source(cx, name, macro_def),
|
||||||
MacroItem(Macro {
|
macro_rules: macro_def.macro_rules,
|
||||||
// FIXME this shouldn't be false
|
}),
|
||||||
source: display_macro_source(cx, name, macro_def, def_id, ty_vis, false),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
|
ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
|
||||||
// proc macros can have a name set by attributes
|
// proc macros can have a name set by attributes
|
||||||
ItemKind::Fn(ref sig, generics, body_id) => {
|
ItemKind::Fn(ref sig, generics, body_id) => {
|
||||||
|
|
|
@ -2543,6 +2543,8 @@ pub(crate) struct ImportSource {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct Macro {
|
pub(crate) struct Macro {
|
||||||
pub(crate) source: String,
|
pub(crate) source: String,
|
||||||
|
/// Whether the macro was defined via `macro_rules!` as opposed to `macro`.
|
||||||
|
pub(crate) macro_rules: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -24,7 +24,6 @@ use crate::clean::{
|
||||||
clean_middle_ty, inline,
|
clean_middle_ty, inline,
|
||||||
};
|
};
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::html::format::visibility_to_src_with_space;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -599,7 +598,7 @@ pub(crate) static DOC_CHANNEL: Lazy<&'static str> =
|
||||||
|
|
||||||
/// Render a sequence of macro arms in a format suitable for displaying to the user
|
/// Render a sequence of macro arms in a format suitable for displaying to the user
|
||||||
/// as part of an item declaration.
|
/// as part of an item declaration.
|
||||||
pub(super) fn render_macro_arms<'a>(
|
fn render_macro_arms<'a>(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
matchers: impl Iterator<Item = &'a TokenTree>,
|
matchers: impl Iterator<Item = &'a TokenTree>,
|
||||||
arm_delim: &str,
|
arm_delim: &str,
|
||||||
|
@ -620,9 +619,6 @@ pub(super) fn display_macro_source(
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
def: &ast::MacroDef,
|
def: &ast::MacroDef,
|
||||||
def_id: DefId,
|
|
||||||
vis: ty::Visibility<DefId>,
|
|
||||||
is_doc_hidden: bool,
|
|
||||||
) -> String {
|
) -> String {
|
||||||
// Extract the spans of all matchers. They represent the "interface" of the macro.
|
// Extract the spans of all matchers. They represent the "interface" of the macro.
|
||||||
let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
|
let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
|
||||||
|
@ -632,18 +628,13 @@ pub(super) fn display_macro_source(
|
||||||
} else {
|
} else {
|
||||||
if matchers.len() <= 1 {
|
if matchers.len() <= 1 {
|
||||||
format!(
|
format!(
|
||||||
"{vis}macro {name}{matchers} {{\n ...\n}}",
|
"macro {name}{matchers} {{\n ...\n}}",
|
||||||
vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id, is_doc_hidden),
|
|
||||||
matchers = matchers
|
matchers = matchers
|
||||||
.map(|matcher| render_macro_matcher(cx.tcx, matcher))
|
.map(|matcher| render_macro_matcher(cx.tcx, matcher))
|
||||||
.collect::<String>(),
|
.collect::<String>(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!("macro {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ","))
|
||||||
"{vis}macro {name} {{\n{arms}}}",
|
|
||||||
vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id, is_doc_hidden),
|
|
||||||
arms = render_macro_arms(cx.tcx, matchers, ","),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1615,47 +1615,6 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is the same as print_with_space, except that it renders no links.
|
|
||||||
/// It's used for macros' rendered source view, which is syntax highlighted and cannot have
|
|
||||||
/// any HTML in it.
|
|
||||||
pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>(
|
|
||||||
visibility: Option<ty::Visibility<DefId>>,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
item_did: DefId,
|
|
||||||
is_doc_hidden: bool,
|
|
||||||
) -> impl Display + 'a + Captures<'tcx> {
|
|
||||||
let vis: Cow<'static, str> = match visibility {
|
|
||||||
None => "".into(),
|
|
||||||
Some(ty::Visibility::Public) => "pub ".into(),
|
|
||||||
Some(ty::Visibility::Restricted(vis_did)) => {
|
|
||||||
// FIXME(camelid): This may not work correctly if `item_did` is a module.
|
|
||||||
// However, rustdoc currently never displays a module's
|
|
||||||
// visibility, so it shouldn't matter.
|
|
||||||
let parent_module = find_nearest_parent_module(tcx, item_did);
|
|
||||||
|
|
||||||
if vis_did.is_crate_root() {
|
|
||||||
"pub(crate) ".into()
|
|
||||||
} else if parent_module == Some(vis_did) {
|
|
||||||
// `pub(in foo)` where `foo` is the parent module
|
|
||||||
// is the same as no visibility modifier
|
|
||||||
"".into()
|
|
||||||
} else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent))
|
|
||||||
== Some(vis_did)
|
|
||||||
{
|
|
||||||
"pub(super) ".into()
|
|
||||||
} else {
|
|
||||||
format!("pub(in {}) ", tcx.def_path_str(vis_did)).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
display_fn(move |f| {
|
|
||||||
if is_doc_hidden {
|
|
||||||
f.write_str("#[doc(hidden)] ")?;
|
|
||||||
}
|
|
||||||
f.write_str(&vis)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait PrintWithSpace {
|
pub(crate) trait PrintWithSpace {
|
||||||
fn print_with_space(&self) -> &str;
|
fn print_with_space(&self) -> &str;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,13 +58,6 @@ pub(crate) fn render_example_with_highlighting(
|
||||||
write_footer(out, playground_button);
|
write_footer(out, playground_button);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Highlights `src` as an item-decl, returning the HTML output.
|
|
||||||
pub(crate) fn render_item_decl_with_highlighting(src: &str, out: &mut Buffer) {
|
|
||||||
write!(out, "<pre class=\"rust item-decl\">");
|
|
||||||
write_code(out, src, None, None);
|
|
||||||
write!(out, "</pre>");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_header(
|
fn write_header(
|
||||||
out: &mut Buffer,
|
out: &mut Buffer,
|
||||||
class: &str,
|
class: &str,
|
||||||
|
|
|
@ -35,7 +35,6 @@ use crate::html::format::{
|
||||||
Buffer, Ending, PrintWithSpace, display_fn, join_with_double_colon, print_abi_with_space,
|
Buffer, Ending, PrintWithSpace, display_fn, join_with_double_colon, print_abi_with_space,
|
||||||
print_constness_with_space, print_where_clause, visibility_print_with_space,
|
print_constness_with_space, print_where_clause, visibility_print_with_space,
|
||||||
};
|
};
|
||||||
use crate::html::highlight;
|
|
||||||
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
|
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
|
||||||
use crate::html::render::{document_full, document_item_info};
|
use crate::html::render::{document_full, document_item_info};
|
||||||
use crate::html::url_parts_builder::UrlPartsBuilder;
|
use crate::html::url_parts_builder::UrlPartsBuilder;
|
||||||
|
@ -1745,7 +1744,13 @@ fn item_variants(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
|
fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
|
||||||
highlight::render_item_decl_with_highlighting(&t.source, w);
|
wrap_item(w, |w| {
|
||||||
|
// FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
|
||||||
|
if !t.macro_rules {
|
||||||
|
write!(w, "{}", visibility_print_with_space(it, cx));
|
||||||
|
}
|
||||||
|
write!(w, "{}", Escape(&t.source));
|
||||||
|
});
|
||||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
|
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ mod a {
|
||||||
}
|
}
|
||||||
mod c {
|
mod c {
|
||||||
//@ has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo:expr) {'
|
//@ has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo:expr) {'
|
||||||
|
// Regression test for <https://github.com/rust-lang/rust/issues/83000>:
|
||||||
|
//@ has - '//pre[@class="rust item-decl"]//a[@class="mod"]/@href' '../../index.html'
|
||||||
pub(in a) macro by_example_vis_named {
|
pub(in a) macro by_example_vis_named {
|
||||||
($foo:expr) => {}
|
($foo:expr) => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,29 +3,17 @@
|
||||||
|
|
||||||
#![crate_name = "foo"]
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
//@ has 'foo/macro.todo.html'
|
//@ has 'foo/macro.todo.html' '//pre' 'macro_rules! todo { \
|
||||||
//@ has - '//span[@class="macro"]' 'macro_rules!'
|
// () => { ... }; \
|
||||||
//@ hasraw - ' todo {'
|
// ($($arg:tt)+) => { ... }; \
|
||||||
|
// }'
|
||||||
//@ hasraw - '{ () => { ... }; ($('
|
|
||||||
//@ has - '//span[@class="macro-nonterminal"]' '$'
|
|
||||||
//@ has - '//span[@class="macro-nonterminal"]' 'arg'
|
|
||||||
//@ hasraw - ':tt)+'
|
|
||||||
//@ hasraw - ') => { ... }; }'
|
|
||||||
pub use std::todo;
|
pub use std::todo;
|
||||||
|
|
||||||
mod mod1 {
|
mod mod1 {
|
||||||
//@ has 'foo/macro.macro1.html'
|
//@ has 'foo/macro.macro1.html' '//pre' 'macro_rules! macro1 { \
|
||||||
//@ hasraw - 'macro_rules!'
|
// () => { ... }; \
|
||||||
//@ hasraw - 'macro1'
|
// ($($arg:expr),+) => { ... }; \
|
||||||
//@ hasraw - '{ () => { ... }; ($('
|
// }'
|
||||||
//@ has - '//span[@class="macro-nonterminal"]' '$'
|
|
||||||
//@ has - '//span[@class="macro-nonterminal"]' 'arg'
|
|
||||||
//@ hasraw - ':'
|
|
||||||
//@ hasraw - 'expr'
|
|
||||||
//@ hasraw - '),'
|
|
||||||
//@ hasraw - '+'
|
|
||||||
//@ hasraw - ') => { ... }; }'
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! macro1 {
|
macro_rules! macro1 {
|
||||||
() => {};
|
() => {};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue