Skip to content

Commit 336c85a

Browse files
committed
rustdoc: Preserve rendering of macro_rules matchers when possible
1 parent f8abed9 commit 336c85a

File tree

5 files changed

+71
-22
lines changed

5 files changed

+71
-22
lines changed

Diff for: src/librustdoc/clean/utils.rs

+55-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
1616
use rustc_middle::mir::interpret::ConstValue;
1717
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
1818
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
19+
use rustc_session::parse::ParseSess;
20+
use rustc_span::source_map::FilePathMapping;
1921
use rustc_span::symbol::{kw, sym, Symbol};
2022
use std::fmt::Write as _;
2123
use std::mem;
@@ -484,20 +486,67 @@ crate const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
484486
/// Render a sequence of macro arms in a format suitable for displaying to the user
485487
/// as part of an item declaration.
486488
pub(super) fn render_macro_arms<'a>(
489+
cx: &DocContext<'_>,
487490
matchers: impl Iterator<Item = &'a TokenTree>,
488491
arm_delim: &str,
489492
) -> String {
490493
let mut out = String::new();
491494
for matcher in matchers {
492-
writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(matcher), arm_delim).unwrap();
495+
writeln!(out, " {} => {{ ... }}{}", render_macro_matcher(cx, matcher), arm_delim)
496+
.unwrap();
493497
}
494498
out
495499
}
496500

497501
/// Render a macro matcher in a format suitable for displaying to the user
498502
/// as part of an item declaration.
499-
pub(super) fn render_macro_matcher(matcher: &TokenTree) -> String {
500-
rustc_ast_pretty::pprust::tt_to_string(matcher)
503+
pub(super) fn render_macro_matcher(cx: &DocContext<'_>, matcher: &TokenTree) -> String {
504+
if let Some(snippet) = snippet_equal_to_token(cx, matcher) {
505+
snippet
506+
} else {
507+
rustc_ast_pretty::pprust::tt_to_string(matcher)
508+
}
509+
}
510+
511+
/// Find the source snippet for this token's Span, reparse it, and return the
512+
/// snippet if the reparsed TokenTree matches the argument TokenTree.
513+
fn snippet_equal_to_token(cx: &DocContext<'_>, matcher: &TokenTree) -> Option<String> {
514+
// Find what rustc thinks is the source snippet.
515+
// This may not actually be anything meaningful if this matcher was itself
516+
// generated by a macro.
517+
let source_map = cx.sess().source_map();
518+
let span = matcher.span();
519+
let snippet = source_map.span_to_snippet(span).ok()?;
520+
521+
// Create a Parser.
522+
let sess = ParseSess::new(FilePathMapping::empty());
523+
let file_name = source_map.span_to_filename(span);
524+
let mut parser =
525+
match rustc_parse::maybe_new_parser_from_source_str(&sess, file_name, snippet.clone()) {
526+
Ok(parser) => parser,
527+
Err(diagnostics) => {
528+
for mut diagnostic in diagnostics {
529+
diagnostic.cancel();
530+
}
531+
return None;
532+
}
533+
};
534+
535+
// Reparse a single token tree.
536+
let mut reparsed_trees = match parser.parse_all_token_trees() {
537+
Ok(reparsed_trees) => reparsed_trees,
538+
Err(mut diagnostic) => {
539+
diagnostic.cancel();
540+
return None;
541+
}
542+
};
543+
if reparsed_trees.len() != 1 {
544+
return None;
545+
}
546+
let reparsed_tree = reparsed_trees.pop().unwrap();
547+
548+
// Compare against the original tree.
549+
if reparsed_tree.eq_unspanned(matcher) { Some(snippet) } else { None }
501550
}
502551

503552
pub(super) fn display_macro_source(
@@ -512,21 +561,21 @@ pub(super) fn display_macro_source(
512561
let matchers = tts.chunks(4).map(|arm| &arm[0]);
513562

514563
if def.macro_rules {
515-
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
564+
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(cx, matchers, ";"))
516565
} else {
517566
if matchers.len() <= 1 {
518567
format!(
519568
"{}macro {}{} {{\n ...\n}}",
520569
vis.to_src_with_space(cx.tcx, def_id),
521570
name,
522-
matchers.map(render_macro_matcher).collect::<String>(),
571+
matchers.map(|matcher| render_macro_matcher(cx, matcher)).collect::<String>(),
523572
)
524573
} else {
525574
format!(
526575
"{}macro {} {{\n{}}}",
527576
vis.to_src_with_space(cx.tcx, def_id),
528577
name,
529-
render_macro_arms(matchers, ","),
578+
render_macro_arms(cx, matchers, ","),
530579
)
531580
}
532581
}

Diff for: src/test/rustdoc/decl_macro.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub macro my_macro() {
99

1010
}
1111

12-
// @has decl_macro/macro.my_macro_2.html //pre 'pub macro my_macro_2($($tok : tt) *) {'
12+
// @has decl_macro/macro.my_macro_2.html //pre 'pub macro my_macro_2($($tok:tt)*) {'
1313
// @has - //pre '...'
1414
// @has - //pre '}'
1515
pub macro my_macro_2($($tok:tt)*) {
@@ -18,8 +18,8 @@ pub macro my_macro_2($($tok:tt)*) {
1818

1919
// @has decl_macro/macro.my_macro_multi.html //pre 'pub macro my_macro_multi {'
2020
// @has - //pre '(_) => { ... },'
21-
// @has - //pre '($foo : ident.$bar : expr) => { ... },'
22-
// @has - //pre '($($foo : literal), +) => { ... },'
21+
// @has - //pre '($foo:ident . $bar:expr) => { ... },'
22+
// @has - //pre '($($foo:literal),+) => { ... },'
2323
// @has - //pre '}'
2424
pub macro my_macro_multi {
2525
(_) => {
@@ -33,7 +33,7 @@ pub macro my_macro_multi {
3333
}
3434
}
3535

36-
// @has decl_macro/macro.by_example_single.html //pre 'pub macro by_example_single($foo : expr) {'
36+
// @has decl_macro/macro.by_example_single.html //pre 'pub macro by_example_single($foo:expr) {'
3737
// @has - //pre '...'
3838
// @has - //pre '}'
3939
pub macro by_example_single {
@@ -42,12 +42,12 @@ pub macro by_example_single {
4242

4343
mod a {
4444
mod b {
45-
// @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo : expr) {'
45+
// @has decl_macro/a/b/macro.by_example_vis.html //pre 'pub(super) macro by_example_vis($foo:expr) {'
4646
pub(in super) macro by_example_vis {
4747
($foo:expr) => {}
4848
}
4949
mod c {
50-
// @has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo : expr) {'
50+
// @has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo:expr) {'
5151
pub(in a) macro by_example_vis_named {
5252
($foo:expr) => {}
5353
}

Diff for: src/test/rustdoc/macros.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @has macros/macro.my_macro.html //pre 'macro_rules! my_macro {'
22
// @has - //pre '() => { ... };'
3-
// @has - //pre '($a : tt) => { ... };'
4-
// @has - //pre '($e : expr) => { ... };'
3+
// @has - //pre '($a:tt) => { ... };'
4+
// @has - //pre '($e:expr) => { ... };'
55
#[macro_export]
66
macro_rules! my_macro {
77
() => [];
@@ -12,8 +12,8 @@ macro_rules! my_macro {
1212
// Check that exported macro defined in a module are shown at crate root.
1313
// @has macros/macro.my_sub_macro.html //pre 'macro_rules! my_sub_macro {'
1414
// @has - //pre '() => { ... };'
15-
// @has - //pre '($a : tt) => { ... };'
16-
// @has - //pre '($e : expr) => { ... };'
15+
// @has - //pre '($a:tt) => { ... };'
16+
// @has - //pre '($e:expr) => { ... };'
1717
mod sub {
1818
#[macro_export]
1919
macro_rules! my_sub_macro {

Diff for: src/test/rustdoc/reexports-priv.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
extern crate reexports;
77

8-
// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {'
8+
// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
99
pub use reexports::addr_of;
1010
// @!has 'foo/macro.addr_of_crate.html'
1111
pub(crate) use reexports::addr_of_crate;
@@ -61,11 +61,11 @@ use reexports::UnionLocal;
6161

6262
pub mod outer {
6363
pub mod inner {
64-
// @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {'
64+
// @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
6565
pub use reexports::addr_of;
66-
// @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="docblock item-decl"]' 'pub(crate) macro addr_of_crate($place : expr) {'
66+
// @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="docblock item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
6767
pub(crate) use reexports::addr_of_crate;
68-
// @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="docblock item-decl"]' 'pub(in outer) macro addr_of_super($place : expr) {'
68+
// @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="docblock item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
6969
pub(super) use reexports::addr_of_super;
7070
// @!has 'foo/outer/inner/macro.addr_of_self.html'
7171
pub(self) use reexports::addr_of_self;

Diff for: src/test/rustdoc/reexports.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
extern crate reexports;
66

7-
// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {'
7+
// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
88
pub use reexports::addr_of;
99
// @!has 'foo/macro.addr_of_crate.html'
1010
pub(crate) use reexports::addr_of_crate;
@@ -60,7 +60,7 @@ use reexports::UnionLocal;
6060

6161
pub mod outer {
6262
pub mod inner {
63-
// @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place : expr) {'
63+
// @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
6464
pub use reexports::addr_of;
6565
// @!has 'foo/outer/inner/macro.addr_of_crate.html'
6666
pub(crate) use reexports::addr_of_crate;

0 commit comments

Comments
 (0)