Improve tt::Subtree debug print

This commit is contained in:
Edwin Cheng 2020-04-09 23:48:08 +08:00
parent d416d892fc
commit 19d952c603
3 changed files with 136 additions and 2 deletions

View file

@ -232,7 +232,7 @@ mod tests {
let quoted = quote!(#a); let quoted = quote!(#a);
assert_eq!(quoted.to_string(), "hello"); assert_eq!(quoted.to_string(), "hello");
let t = format!("{:?}", quoted); let t = format!("{:?}", quoted);
assert_eq!(t, "Subtree { delimiter: None, token_trees: [Leaf(Ident(Ident { text: \"hello\", id: TokenId(4294967295) }))] }"); assert_eq!(t, "SUBTREE $\n IDENT hello 4294967295");
} }
#[test] #[test]

View file

@ -141,6 +141,79 @@ macro_rules! impl_froms {
); );
} }
#[test]
fn test_convert_tt2() {
parse_macro(
r#"
macro_rules! impl_froms {
($e:ident: $($v:ident),*) => {
$(
impl From<$v> for $e {
fn from(it: $v) -> $e {
$e::$v(it)
}
}
)*
}
}
"#,
)
.assert_expand(
"impl_froms!(TokenTree: Leaf, Subtree);",
r#"
SUBTREE $
IDENT impl 20
IDENT From 21
PUNCH < [joint] 22
IDENT Leaf 53
PUNCH > [alone] 25
IDENT for 26
IDENT TokenTree 51
SUBTREE {} 29
IDENT fn 30
IDENT from 31
SUBTREE () 32
IDENT it 33
PUNCH : [alone] 34
IDENT Leaf 53
PUNCH - [joint] 37
PUNCH > [alone] 38
IDENT TokenTree 51
SUBTREE {} 41
IDENT TokenTree 51
PUNCH : [joint] 44
PUNCH : [joint] 45
IDENT Leaf 53
SUBTREE () 48
IDENT it 49
IDENT impl 20
IDENT From 21
PUNCH < [joint] 22
IDENT Subtree 55
PUNCH > [alone] 25
IDENT for 26
IDENT TokenTree 51
SUBTREE {} 29
IDENT fn 30
IDENT from 31
SUBTREE () 32
IDENT it 33
PUNCH : [alone] 34
IDENT Subtree 55
PUNCH - [joint] 37
PUNCH > [alone] 38
IDENT TokenTree 51
SUBTREE {} 41
IDENT TokenTree 51
PUNCH : [joint] 44
PUNCH : [joint] 45
IDENT Subtree 55
SUBTREE () 48
IDENT it 49
"#,
);
}
#[test] #[test]
fn test_expr_order() { fn test_expr_order() {
let expanded = parse_macro( let expanded = parse_macro(
@ -1479,6 +1552,12 @@ impl MacroFixture {
assert_eq!(expansion.to_string(), expected); assert_eq!(expansion.to_string(), expected);
} }
fn assert_expand(&self, invocation: &str, expected: &str) {
let expansion = self.expand_tt(invocation);
let actual = format!("{:?}", expansion);
test_utils::assert_eq_text!(&actual.trim(), &expected.trim());
}
fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture { fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture {
self.assert_expansion(FragmentKind::Items, invocation, expected); self.assert_expansion(FragmentKind::Items, invocation, expected);
self self

View file

@ -57,7 +57,7 @@ pub enum Leaf {
} }
impl_froms!(Leaf: Literal, Punct, Ident); impl_froms!(Leaf: Literal, Punct, Ident);
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] #[derive(Clone, PartialEq, Eq, Hash, Default)]
pub struct Subtree { pub struct Subtree {
pub delimiter: Option<Delimiter>, pub delimiter: Option<Delimiter>,
pub token_trees: Vec<TokenTree>, pub token_trees: Vec<TokenTree>,
@ -101,6 +101,61 @@ pub struct Ident {
pub id: TokenId, pub id: TokenId,
} }
fn print_debug_subtree(f: &mut fmt::Formatter<'_>, subtree: &Subtree, level: usize) -> fmt::Result {
let align = std::iter::repeat(" ").take(level).collect::<String>();
let aux = match subtree.delimiter.map(|it| (it.kind, it.id.0)) {
None => "$".to_string(),
Some((DelimiterKind::Parenthesis, id)) => format!("() {}", id),
Some((DelimiterKind::Brace, id)) => format!("{{}} {}", id),
Some((DelimiterKind::Bracket, id)) => format!("[] {}", id),
};
if subtree.token_trees.is_empty() {
write!(f, "{}SUBTREE {}", align, aux)?;
} else {
writeln!(f, "{}SUBTREE {}", align, aux)?;
for (idx, child) in subtree.token_trees.iter().enumerate() {
print_debug_token(f, child, level + 1)?;
if idx != subtree.token_trees.len() - 1 {
writeln!(f, "")?;
}
}
}
Ok(())
}
fn print_debug_token(f: &mut fmt::Formatter<'_>, tkn: &TokenTree, level: usize) -> fmt::Result {
let align = std::iter::repeat(" ").take(level).collect::<String>();
match tkn {
TokenTree::Leaf(leaf) => match leaf {
Leaf::Literal(lit) => write!(f, "{}LITERAL {} {}", align, lit.text, lit.id.0)?,
Leaf::Punct(punct) => write!(
f,
"{}PUNCH {} [{}] {}",
align,
punct.char,
if punct.spacing == Spacing::Alone { "alone" } else { "joint" },
punct.id.0
)?,
Leaf::Ident(ident) => write!(f, "{}IDENT {} {}", align, ident.text, ident.id.0)?,
},
TokenTree::Subtree(subtree) => {
print_debug_subtree(f, subtree, level)?;
}
}
Ok(())
}
impl Debug for Subtree {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
print_debug_subtree(f, self, 0)
}
}
impl fmt::Display for TokenTree { impl fmt::Display for TokenTree {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {