Skip to content

Commit

Permalink
Rollup merge of rust-lang#92334 - dtolnay:rustdocmatcher, r=camelid,G…
Browse files Browse the repository at this point in the history
…uillaumeGomez

rustdoc: Preserve rendering of macro_rules matchers when possible

Fixes rust-lang#92331. This approach restores the behavior prior to rust-lang#86282 **if** the matcher token held by the compiler **and** the matcher token found in the source code are identical TokenTrees. Thus rust-lang#86208 remains fixed, but without regressing formatting for the vast majority of macros which are not macro-generated.
  • Loading branch information
matthiaskrgr committed Jan 10, 2022
2 parents 423e355 + 0f8415b commit 5501751
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 22 deletions.
61 changes: 55 additions & 6 deletions src/librustdoc/clean/utils.rs
Expand Up @@ -17,6 +17,8 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
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 std::fmt::Write as _;
use std::mem;
Expand Down Expand Up @@ -486,20 +488,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
/// as part of an item declaration.
pub(super) fn render_macro_arms<'a>(
tcx: TyCtxt<'_>,
matchers: impl Iterator<Item = &'a TokenTree>,
arm_delim: &str,
) -> String {
let mut out = String::new();
for matcher in matchers {
writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(matcher), arm_delim).unwrap();
writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(tcx, matcher), arm_delim)
.unwrap();
}
out
}

/// Render a macro matcher in a format suitable for displaying to the user
/// as part of an item declaration.
pub(super) fn render_macro_matcher(matcher: &TokenTree) -> String {
rustc_ast_pretty::pprust::tt_to_string(matcher)
pub(super) fn render_macro_matcher(tcx: TyCtxt<'_>, matcher: &TokenTree) -> String {
if let Some(snippet) = snippet_equal_to_token(tcx, 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(tcx: TyCtxt<'_>, 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 = tcx.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(
Expand All @@ -514,21 +563,21 @@ pub(super) fn display_macro_source(
let matchers = tts.chunks(4).map(|arm| &arm[0]);

if def.macro_rules {
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(cx.tcx, matchers, ";"))
} else {
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>(),
matchers.map(|matcher| render_macro_matcher(cx.tcx, matcher)).collect::<String>(),
)
} else {
format!(
"{}macro {} {{\n{}}}",
vis.to_src_with_space(cx.tcx, def_id),
name,
render_macro_arms(matchers, ","),
render_macro_arms(cx.tcx, matchers, ","),
)
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/test/rustdoc/decl_macro.rs
Expand Up @@ -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 '}'
pub macro my_macro_2($($tok:tt)*) {
Expand All @@ -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 - //pre '(_) => { ... },'
// @has - //pre '($foo : ident.$bar : expr) => { ... },'
// @has - //pre '($($foo : literal), +) => { ... },'
// @has - //pre '($foo:ident . $bar:expr) => { ... },'
// @has - //pre '($($foo:literal),+) => { ... },'
// @has - //pre '}'
pub macro my_macro_multi {
(_) => {
Expand All @@ -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 '}'
pub macro by_example_single {
Expand All @@ -42,12 +42,12 @@ pub macro by_example_single {

mod a {
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 {
($foo:expr) => {}
}
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 {
($foo:expr) => {}
}
Expand Down
14 changes: 14 additions & 0 deletions src/test/rustdoc/macro-generated-macro.rs
@@ -0,0 +1,14 @@
macro_rules! outer {
($($matcher:tt)*) => {
#[macro_export]
macro_rules! inner {
(<= $($matcher)* =>) => {};
}
}
}

// @has macro_generated_macro/macro.inner.html //pre 'macro_rules! inner {'
// @has - //pre '(<= type $($i : ident) :: * + $e : expr =>) => { ... };'
outer!(type $($i:ident)::* + $e:expr);

inner!(<= type foo::bar + x.sort() =>);
8 changes: 4 additions & 4 deletions src/test/rustdoc/macros.rs
@@ -1,7 +1,7 @@
// @has macros/macro.my_macro.html //pre 'macro_rules! my_macro {'
// @has - //pre '() => { ... };'
// @has - //pre '($a : tt) => { ... };'
// @has - //pre '($e : expr) => { ... };'
// @has - //pre '($a:tt) => { ... };'
// @has - //pre '($e:expr) => { ... };'
#[macro_export]
macro_rules! my_macro {
() => [];
Expand All @@ -12,8 +12,8 @@ macro_rules! my_macro {
// 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 - //pre '() => { ... };'
// @has - //pre '($a : tt) => { ... };'
// @has - //pre '($e : expr) => { ... };'
// @has - //pre '($a:tt) => { ... };'
// @has - //pre '($e:expr) => { ... };'
mod sub {
#[macro_export]
macro_rules! my_sub_macro {
Expand Down
8 changes: 4 additions & 4 deletions src/test/rustdoc/reexports-priv.rs
Expand Up @@ -5,7 +5,7 @@

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;
// @!has 'foo/macro.addr_of_crate.html'
pub(crate) use reexports::addr_of_crate;
Expand Down Expand Up @@ -61,11 +61,11 @@ use reexports::UnionLocal;

pub mod outer {
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;
// @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;
// @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;
// @!has 'foo/outer/inner/macro.addr_of_self.html'
pub(self) use reexports::addr_of_self;
Expand Down
4 changes: 2 additions & 2 deletions src/test/rustdoc/reexports.rs
Expand Up @@ -4,7 +4,7 @@

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;
// @!has 'foo/macro.addr_of_crate.html'
pub(crate) use reexports::addr_of_crate;
Expand Down Expand Up @@ -60,7 +60,7 @@ use reexports::UnionLocal;

pub mod outer {
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;
// @!has 'foo/outer/inner/macro.addr_of_crate.html'
pub(crate) use reexports::addr_of_crate;
Expand Down

0 comments on commit 5501751

Please sign in to comment.