Skip to content

Commit

Permalink
Pretty-print macro matchers instead of using source code
Browse files Browse the repository at this point in the history
The output is not quite as nice as it used to be, but it does work.
  • Loading branch information
camelid committed Jul 3, 2021
1 parent f749d97 commit f82d484
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 62 deletions.
28 changes: 12 additions & 16 deletions src/librustdoc/clean/inline.rs
Expand Up @@ -13,10 +13,9 @@ use rustc_metadata::creader::LoadedMacro;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;

use crate::clean::{
self, Attributes, AttributesExt, FakeDefId, GetDefId, NestedAttributesExt, ToSource, Type,
self, utils, Attributes, AttributesExt, FakeDefId, GetDefId, NestedAttributesExt, Type,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
Expand Down Expand Up @@ -547,23 +546,20 @@ fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::Item
let imported_from = cx.tcx.crate_name(did.krate);
match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) {
LoadedMacro::MacroDef(def, _) => {
let matchers: Vec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.kind {
if let ast::ItemKind::MacroDef(ref def) = def.kind {
let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
tts.chunks(4).map(|arm| arm[0].span()).collect()
} else {
unreachable!()
};
let matchers = tts.chunks(4).map(|arm| &arm[0]);

let source = format!(
"macro_rules! {} {{\n{}}}",
name.clean(cx),
matchers
.iter()
.map(|span| { format!(" {} => {{ ... }};\n", span.to_src(cx)) })
.collect::<String>()
);
let source = format!(
"macro_rules! {} {{\n{}}}",
name.clean(cx),
utils::render_macro_arms(matchers, ";")
);

clean::MacroItem(clean::Macro { source, imported_from: Some(imported_from) })
clean::MacroItem(clean::Macro { source, imported_from: Some(imported_from) })
} else {
unreachable!()
}
}
LoadedMacro::ProcMacro(ext) => clean::ProcMacroItem(clean::ProcMacro {
kind: ext.macro_kind(),
Expand Down
21 changes: 6 additions & 15 deletions src/librustdoc/clean/mod.rs
Expand Up @@ -2172,17 +2172,11 @@ impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
let (item, renamed) = self;
let name = renamed.unwrap_or(item.ident.name);
let tts = item.ast.body.inner_tokens().trees().collect::<Vec<_>>();
// Extract the spans of all matchers. They represent the "interface" of the macro.
let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect::<Vec<_>>();
// Extract the macro's matchers. They represent the "interface" of the macro.
let matchers = tts.chunks(4).map(|arm| &arm[0]);

let source = if item.ast.macro_rules {
format!(
"macro_rules! {} {{\n{}}}",
name,
matchers
.iter()
.map(|span| { format!(" {} => {{ ... }};\n", span.to_src(cx)) })
.collect::<String>(),
)
format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
} else {
let vis = item.vis.clean(cx);
let def_id = item.def_id.to_def_id();
Expand All @@ -2192,17 +2186,14 @@ impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
"{}macro {}{} {{\n ...\n}}",
vis.to_src_with_space(cx.tcx, def_id),
name,
matchers.iter().map(|span| span.to_src(cx)).collect::<String>(),
matchers.map(render_macro_matcher).collect::<String>(),
)
} else {
format!(
"{}macro {} {{\n{}}}",
vis.to_src_with_space(cx.tcx, def_id),
name,
matchers
.iter()
.map(|span| { format!(" {} => {{ ... }},\n", span.to_src(cx)) })
.collect::<String>(),
render_macro_arms(matchers, ","),
)
}
};
Expand Down
37 changes: 21 additions & 16 deletions src/librustdoc/clean/utils.rs
Expand Up @@ -7,13 +7,15 @@ use crate::clean::{
use crate::core::DocContext;
use crate::formats::item_type::ItemType;

use rustc_ast::tokenstream::TokenTree;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
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_span::symbol::{kw, sym, Symbol};
use std::fmt::Write as _;
use std::mem;

#[cfg(test)]
Expand Down Expand Up @@ -248,22 +250,6 @@ crate fn build_deref_target_impls(cx: &mut DocContext<'_>, items: &[Item], ret:
}
}

crate trait ToSource {
fn to_src(&self, cx: &DocContext<'_>) -> String;
}

impl ToSource for rustc_span::Span {
fn to_src(&self, cx: &DocContext<'_>) -> String {
debug!("converting span {:?} to snippet", self);
let sn = match cx.sess().source_map().span_to_snippet(*self) {
Ok(x) => x,
Err(_) => String::new(),
};
debug!("got snippet {}", sn);
sn
}
}

crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
use rustc_hir::*;
debug!("trying to get a name from pattern: {:?}", p);
Expand Down Expand Up @@ -572,3 +558,22 @@ crate fn has_doc_flag(attrs: ty::Attributes<'_>, flag: Symbol) -> bool {
///
/// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
crate const DOC_RUST_LANG_ORG_CHANNEL: &'static 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>(
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();
}
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)
}
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
9 changes: 4 additions & 5 deletions src/test/rustdoc/macro_rules-matchers.rs
Expand Up @@ -7,16 +7,15 @@
// @has - '//span[@class="macro"]' 'macro_rules!'
// @has - '//span[@class="ident"]' 'todo'
// Note: count = 2 * ('=' + '>') + '+' = 2 * (1 + 1) + 1 = 5
// @count - '//span[@class="op"]' 5
// @count - '//pre[@class="rust macro"]//span[@class="op"]' 5

// @has - '{ ()'
// @has - '//span[@class="op"]' '='
// @has - '//span[@class="op"]' '>'
// @has - '{ ... };'

// @has - '($('
// @has - '//span[@class="macro-nonterminal"]' '$'
// @has - '//span[@class="macro-nonterminal"]' 'arg'
// @has - '($ ($'
// @has - '//span[@class="ident"]' 'arg'
// @has - ':'
// @has - '//span[@class="ident"]' 'tt'
// @has - '//span[@class="op"]' '+'
Expand All @@ -28,7 +27,7 @@ mod mod1 {
// @has - 'macro_rules!'
// @has - 'macro1'
// @has - '{ ()'
// @has - '($('
// @has - '($ ('
// @has - 'arg'
// @has - 'expr'
// @has - ','
Expand Down
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

0 comments on commit f82d484

Please sign in to comment.