mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-09 05:23:07 +00:00
Pretty-print macro matchers instead of using source code
The output is not quite as nice as it used to be, but it does work.
This commit is contained in:
parent
f749d97b8a
commit
f82d4845f2
@ -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;
|
||||
@ -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()
|
||||
let matchers = tts.chunks(4).map(|arm| &arm[0]);
|
||||
|
||||
let source = format!(
|
||||
"macro_rules! {} {{\n{}}}",
|
||||
name.clean(cx),
|
||||
utils::render_macro_arms(matchers, ";")
|
||||
);
|
||||
|
||||
clean::MacroItem(clean::Macro { source, imported_from: Some(imported_from) })
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let source = format!(
|
||||
"macro_rules! {} {{\n{}}}",
|
||||
name.clean(cx),
|
||||
matchers
|
||||
.iter()
|
||||
.map(|span| { format!(" {} => {{ ... }};\n", span.to_src(cx)) })
|
||||
.collect::<String>()
|
||||
);
|
||||
|
||||
clean::MacroItem(clean::Macro { source, imported_from: Some(imported_from) })
|
||||
}
|
||||
}
|
||||
LoadedMacro::ProcMacro(ext) => clean::ProcMacroItem(clean::ProcMacro {
|
||||
kind: ext.macro_kind(),
|
||||
|
@ -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();
|
||||
@ -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, ","),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
@ -7,6 +7,7 @@ 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};
|
||||
@ -14,6 +15,7 @@ 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)]
|
||||
@ -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);
|
||||
@ -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)
|
||||
}
|
||||
|
@ -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)*) {
|
||||
@ -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 {
|
||||
(_) => {
|
||||
@ -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 {
|
||||
@ -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) => {}
|
||||
}
|
||||
|
@ -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"]' '+'
|
||||
@ -28,7 +27,7 @@ mod mod1 {
|
||||
// @has - 'macro_rules!'
|
||||
// @has - 'macro1'
|
||||
// @has - '{ ()'
|
||||
// @has - '($('
|
||||
// @has - '($ ('
|
||||
// @has - 'arg'
|
||||
// @has - 'expr'
|
||||
// @has - ','
|
||||
|
@ -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 {
|
||||
() => [];
|
||||
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user