Perform 'deep recollection' in test helper macros

Currently, the print helper macro performs 'recollection' by doing
`token_stream.into_iter().collect()`. However, this will not affect
nonterminals that occur nested inside delimited groups, since the
wrapping delimited group will be left untouched.

This commit adds 'deep recollection', which recursively recollects every
delimited group in the token stream. As with normal recollection, we
only print out something if deep recollection results in a different
stringified token stream.

This is useful for catching bugs where we update the AST of a
nonterminal (which affects pretty-printing), but do not update the
attatched `TokenStream`
This commit is contained in:
Aaron Hill 2021-03-21 00:17:19 -04:00
parent 61edfd591c
commit 6d7294a00c
No known key found for this signature in database
GPG key ID: B4087E510E98B164
3 changed files with 34 additions and 1 deletions

View file

@ -83,21 +83,52 @@ fn print_helper(input: TokenStream, kind: &str) -> TokenStream {
print_helper_ext(input, kind, true)
}
fn deep_recollect(input: TokenStream) -> TokenStream {
input.into_iter().map(|tree| {
match tree {
TokenTree::Group(group) => {
let inner = deep_recollect(group.stream());
let mut new_group = TokenTree::Group(
proc_macro::Group::new(group.delimiter(), inner)
);
new_group.set_span(group.span());
new_group
}
_ => tree,
}
}).collect()
}
fn print_helper_ext(input: TokenStream, kind: &str, debug: bool) -> TokenStream {
let input_display = format!("{}", input);
let input_debug = format!("{:#?}", input);
let recollected = input.into_iter().collect();
let recollected = input.clone().into_iter().collect();
let recollected_display = format!("{}", recollected);
let recollected_debug = format!("{:#?}", recollected);
let deep_recollected = deep_recollect(input);
let deep_recollected_display = format!("{}", deep_recollected);
let deep_recollected_debug = format!("{:#?}", deep_recollected);
println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display);
if recollected_display != input_display {
println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display);
}
if deep_recollected_display != recollected_display {
println!("PRINT-{} DEEP-RE-COLLECTED (DISPLAY): {}", kind, deep_recollected_display);
}
if debug {
println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug);
if recollected_debug != input_debug {
println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug);
}
if deep_recollected_debug != recollected_debug {
println!("PRINT-{} DEEP-RE-COLLETED (DEBUG): {}", kind, deep_recollected_debug);
}
}
recollected
}

View file

@ -1,6 +1,7 @@
PRINT-BANG INPUT (DISPLAY): foo ! { #[fake_attr] mod bar {
#![doc = r" Foo"]
} }
PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): foo ! { #[fake_attr] mod bar { # ! [doc = r" Foo"] } }
PRINT-BANG INPUT (DEBUG): TokenStream [
Ident {
ident: "foo",

View file

@ -71,6 +71,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
},
]
PRINT-BANG INPUT (DISPLAY): "hi" "hello".len() + "world".len() (1 + 1)
PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): "hi" "hello" . len() + "world" . len() (1 + 1)
PRINT-BANG INPUT (DEBUG): TokenStream [
Literal {
kind: Str,