mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
rustdoc: Preserve rendering of macro_rules matchers when possible
This commit is contained in:
parent
f8abed9ed4
commit
336c85a053
@ -16,6 +16,8 @@ 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, TyCtxt};
|
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
|
||||||
|
use rustc_session::parse::ParseSess;
|
||||||
|
use rustc_span::source_map::FilePathMapping;
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use std::fmt::Write as _;
|
use std::fmt::Write as _;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -484,20 +486,67 @@ crate const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
|
|||||||
/// 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>(
|
pub(super) fn render_macro_arms<'a>(
|
||||||
|
cx: &DocContext<'_>,
|
||||||
matchers: impl Iterator<Item = &'a TokenTree>,
|
matchers: impl Iterator<Item = &'a TokenTree>,
|
||||||
arm_delim: &str,
|
arm_delim: &str,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
for matcher in matchers {
|
for matcher in matchers {
|
||||||
writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(matcher), arm_delim).unwrap();
|
writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(cx, matcher), arm_delim)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render a macro matcher in a format suitable for displaying to the user
|
/// Render a macro matcher 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_matcher(matcher: &TokenTree) -> String {
|
pub(super) fn render_macro_matcher(cx: &DocContext<'_>, matcher: &TokenTree) -> String {
|
||||||
rustc_ast_pretty::pprust::tt_to_string(matcher)
|
if let Some(snippet) = snippet_equal_to_token(cx, matcher) {
|
||||||
|
snippet
|
||||||
|
} else {
|
||||||
|
rustc_ast_pretty::pprust::tt_to_string(matcher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the source snippet for this token's Span, reparse it, and return the
|
||||||
|
/// snippet if the reparsed TokenTree matches the argument TokenTree.
|
||||||
|
fn snippet_equal_to_token(cx: &DocContext<'_>, matcher: &TokenTree) -> Option<String> {
|
||||||
|
// Find what rustc thinks is the source snippet.
|
||||||
|
// This may not actually be anything meaningful if this matcher was itself
|
||||||
|
// generated by a macro.
|
||||||
|
let source_map = cx.sess().source_map();
|
||||||
|
let span = matcher.span();
|
||||||
|
let snippet = source_map.span_to_snippet(span).ok()?;
|
||||||
|
|
||||||
|
// Create a Parser.
|
||||||
|
let sess = ParseSess::new(FilePathMapping::empty());
|
||||||
|
let file_name = source_map.span_to_filename(span);
|
||||||
|
let mut parser =
|
||||||
|
match rustc_parse::maybe_new_parser_from_source_str(&sess, file_name, snippet.clone()) {
|
||||||
|
Ok(parser) => parser,
|
||||||
|
Err(diagnostics) => {
|
||||||
|
for mut diagnostic in diagnostics {
|
||||||
|
diagnostic.cancel();
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reparse a single token tree.
|
||||||
|
let mut reparsed_trees = match parser.parse_all_token_trees() {
|
||||||
|
Ok(reparsed_trees) => reparsed_trees,
|
||||||
|
Err(mut diagnostic) => {
|
||||||
|
diagnostic.cancel();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if reparsed_trees.len() != 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let reparsed_tree = reparsed_trees.pop().unwrap();
|
||||||
|
|
||||||
|
// Compare against the original tree.
|
||||||
|
if reparsed_tree.eq_unspanned(matcher) { Some(snippet) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn display_macro_source(
|
pub(super) fn display_macro_source(
|
||||||
@ -512,21 +561,21 @@ pub(super) fn display_macro_source(
|
|||||||
let matchers = tts.chunks(4).map(|arm| &arm[0]);
|
let matchers = tts.chunks(4).map(|arm| &arm[0]);
|
||||||
|
|
||||||
if def.macro_rules {
|
if def.macro_rules {
|
||||||
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
|
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(cx, matchers, ";"))
|
||||||
} else {
|
} else {
|
||||||
if matchers.len() <= 1 {
|
if matchers.len() <= 1 {
|
||||||
format!(
|
format!(
|
||||||
"{}macro {}{} {{\n ...\n}}",
|
"{}macro {}{} {{\n ...\n}}",
|
||||||
vis.to_src_with_space(cx.tcx, def_id),
|
vis.to_src_with_space(cx.tcx, def_id),
|
||||||
name,
|
name,
|
||||||
matchers.map(render_macro_matcher).collect::<String>(),
|
matchers.map(|matcher| render_macro_matcher(cx, matcher)).collect::<String>(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"{}macro {} {{\n{}}}",
|
"{}macro {} {{\n{}}}",
|
||||||
vis.to_src_with_space(cx.tcx, def_id),
|
vis.to_src_with_space(cx.tcx, def_id),
|
||||||
name,
|
name,
|
||||||
render_macro_arms(matchers, ","),
|
render_macro_arms(cx, matchers, ","),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ pub macro my_macro() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @has decl_macro/macro.my_macro_2.html //pre 'pub macro my_macro_2($($tok : tt) *) {'
|
// @has decl_macro/macro.my_macro_2.html //pre 'pub macro my_macro_2($($tok:tt)*) {'
|
||||||
// @has - //pre '...'
|
// @has - //pre '...'
|
||||||
// @has - //pre '}'
|
// @has - //pre '}'
|
||||||
pub macro my_macro_2($($tok:tt)*) {
|
pub macro my_macro_2($($tok:tt)*) {
|
||||||
@ -18,8 +18,8 @@ pub macro my_macro_2($($tok:tt)*) {
|
|||||||
|
|
||||||
// @has decl_macro/macro.my_macro_multi.html //pre 'pub macro my_macro_multi {'
|
// @has decl_macro/macro.my_macro_multi.html //pre 'pub macro my_macro_multi {'
|
||||||
// @has - //pre '(_) => { ... },'
|
// @has - //pre '(_) => { ... },'
|
||||||
// @has - //pre '($foo : ident.$bar : expr) => { ... },'
|
// @has - //pre '($foo:ident . $bar:expr) => { ... },'
|
||||||
// @has - //pre '($($foo : literal), +) => { ... },'
|
// @has - //pre '($($foo:literal),+) => { ... },'
|
||||||
// @has - //pre '}'
|
// @has - //pre '}'
|
||||||
pub macro my_macro_multi {
|
pub macro my_macro_multi {
|
||||||
(_) => {
|
(_) => {
|
||||||
@ -33,7 +33,7 @@ pub macro my_macro_multi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @has decl_macro/macro.by_example_single.html //pre 'pub macro by_example_single($foo : expr) {'
|
// @has decl_macro/macro.by_example_single.html //pre 'pub macro by_example_single($foo:expr) {'
|
||||||
// @has - //pre '...'
|
// @has - //pre '...'
|
||||||
// @has - //pre '}'
|
// @has - //pre '}'
|
||||||
pub macro by_example_single {
|
pub macro by_example_single {
|
||||||
@ -42,12 +42,12 @@ pub macro by_example_single {
|
|||||||
|
|
||||||
mod a {
|
mod a {
|
||||||
mod b {
|
mod b {
|
||||||
// @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo : expr) {'
|
// @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo:expr) {'
|
||||||
pub(in super) macro by_example_vis {
|
pub(in super) macro by_example_vis {
|
||||||
($foo:expr) => {}
|
($foo:expr) => {}
|
||||||
}
|
}
|
||||||
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) {'
|
||||||
pub(in a) macro by_example_vis_named {
|
pub(in a) macro by_example_vis_named {
|
||||||
($foo:expr) => {}
|
($foo:expr) => {}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @has macros/macro.my_macro.html //pre 'macro_rules! my_macro {'
|
// @has macros/macro.my_macro.html //pre 'macro_rules! my_macro {'
|
||||||
// @has - //pre '() => { ... };'
|
// @has - //pre '() => { ... };'
|
||||||
// @has - //pre '($a : tt) => { ... };'
|
// @has - //pre '($a:tt) => { ... };'
|
||||||
// @has - //pre '($e : expr) => { ... };'
|
// @has - //pre '($e:expr) => { ... };'
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! my_macro {
|
macro_rules! my_macro {
|
||||||
() => [];
|
() => [];
|
||||||
@ -12,8 +12,8 @@ macro_rules! my_macro {
|
|||||||
// Check that exported macro defined in a module are shown at crate root.
|
// Check that exported macro defined in a module are shown at crate root.
|
||||||
// @has macros/macro.my_sub_macro.html //pre 'macro_rules! my_sub_macro {'
|
// @has macros/macro.my_sub_macro.html //pre 'macro_rules! my_sub_macro {'
|
||||||
// @has - //pre '() => { ... };'
|
// @has - //pre '() => { ... };'
|
||||||
// @has - //pre '($a : tt) => { ... };'
|
// @has - //pre '($a:tt) => { ... };'
|
||||||
// @has - //pre '($e : expr) => { ... };'
|
// @has - //pre '($e:expr) => { ... };'
|
||||||
mod sub {
|
mod sub {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! my_sub_macro {
|
macro_rules! my_sub_macro {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
extern crate reexports;
|
extern crate reexports;
|
||||||
|
|
||||||
// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {'
|
// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
|
||||||
pub use reexports::addr_of;
|
pub use reexports::addr_of;
|
||||||
// @!has 'foo/macro.addr_of_crate.html'
|
// @!has 'foo/macro.addr_of_crate.html'
|
||||||
pub(crate) use reexports::addr_of_crate;
|
pub(crate) use reexports::addr_of_crate;
|
||||||
@ -61,11 +61,11 @@ use reexports::UnionLocal;
|
|||||||
|
|
||||||
pub mod outer {
|
pub mod outer {
|
||||||
pub mod inner {
|
pub mod inner {
|
||||||
// @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {'
|
// @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
|
||||||
pub use reexports::addr_of;
|
pub use reexports::addr_of;
|
||||||
// @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="docblock item-decl"]' 'pub(crate) macro addr_of_crate($place : expr) {'
|
// @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="docblock item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
|
||||||
pub(crate) use reexports::addr_of_crate;
|
pub(crate) use reexports::addr_of_crate;
|
||||||
// @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="docblock item-decl"]' 'pub(in outer) macro addr_of_super($place : expr) {'
|
// @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="docblock item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
|
||||||
pub(super) use reexports::addr_of_super;
|
pub(super) use reexports::addr_of_super;
|
||||||
// @!has 'foo/outer/inner/macro.addr_of_self.html'
|
// @!has 'foo/outer/inner/macro.addr_of_self.html'
|
||||||
pub(self) use reexports::addr_of_self;
|
pub(self) use reexports::addr_of_self;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
extern crate reexports;
|
extern crate reexports;
|
||||||
|
|
||||||
// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {'
|
// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
|
||||||
pub use reexports::addr_of;
|
pub use reexports::addr_of;
|
||||||
// @!has 'foo/macro.addr_of_crate.html'
|
// @!has 'foo/macro.addr_of_crate.html'
|
||||||
pub(crate) use reexports::addr_of_crate;
|
pub(crate) use reexports::addr_of_crate;
|
||||||
@ -60,7 +60,7 @@ use reexports::UnionLocal;
|
|||||||
|
|
||||||
pub mod outer {
|
pub mod outer {
|
||||||
pub mod inner {
|
pub mod inner {
|
||||||
// @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {'
|
// @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
|
||||||
pub use reexports::addr_of;
|
pub use reexports::addr_of;
|
||||||
// @!has 'foo/outer/inner/macro.addr_of_crate.html'
|
// @!has 'foo/outer/inner/macro.addr_of_crate.html'
|
||||||
pub(crate) use reexports::addr_of_crate;
|
pub(crate) use reexports::addr_of_crate;
|
||||||
|
Loading…
Reference in New Issue
Block a user