181 lines
5.0 KiB
Rust
181 lines
5.0 KiB
Rust
//@ force-host
|
|
//@ no-prefer-dynamic
|
|
|
|
// Proc macros commonly used by tests.
|
|
// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros.
|
|
|
|
#![crate_type = "proc-macro"]
|
|
|
|
extern crate proc_macro;
|
|
use proc_macro::{TokenStream, TokenTree};
|
|
|
|
// Macro that return empty token stream.
|
|
|
|
#[proc_macro]
|
|
pub fn empty(_: TokenStream) -> TokenStream {
|
|
TokenStream::new()
|
|
}
|
|
|
|
#[proc_macro_attribute]
|
|
pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream {
|
|
TokenStream::new()
|
|
}
|
|
|
|
#[proc_macro_derive(Empty, attributes(empty_helper))]
|
|
pub fn empty_derive(_: TokenStream) -> TokenStream {
|
|
TokenStream::new()
|
|
}
|
|
|
|
// Macro that panics.
|
|
|
|
#[proc_macro]
|
|
pub fn panic_bang(_: TokenStream) -> TokenStream {
|
|
panic!("panic-bang");
|
|
}
|
|
|
|
#[proc_macro_attribute]
|
|
pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream {
|
|
panic!("panic-attr");
|
|
}
|
|
|
|
#[proc_macro_derive(Panic, attributes(panic_helper))]
|
|
pub fn panic_derive(_: TokenStream) -> TokenStream {
|
|
panic!("panic-derive");
|
|
}
|
|
|
|
// Macros that return the input stream.
|
|
|
|
#[proc_macro]
|
|
pub fn identity(input: TokenStream) -> TokenStream {
|
|
input
|
|
}
|
|
|
|
#[proc_macro_attribute]
|
|
pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream {
|
|
input
|
|
}
|
|
|
|
#[proc_macro_derive(Identity, attributes(identity_helper))]
|
|
pub fn identity_derive(input: TokenStream) -> TokenStream {
|
|
input
|
|
}
|
|
|
|
// Macros that iterate and re-collect the input stream.
|
|
|
|
#[proc_macro]
|
|
pub fn recollect(input: TokenStream) -> TokenStream {
|
|
input.into_iter().collect()
|
|
}
|
|
|
|
#[proc_macro_attribute]
|
|
pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream {
|
|
input.into_iter().collect()
|
|
}
|
|
|
|
#[proc_macro_derive(Recollect, attributes(recollect_helper))]
|
|
pub fn recollect_derive(input: TokenStream) -> TokenStream {
|
|
input.into_iter().collect()
|
|
}
|
|
|
|
// Macros that print their input in the original and re-collected forms (if they differ).
|
|
|
|
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.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
|
|
}
|
|
|
|
#[proc_macro]
|
|
pub fn print_bang(input: TokenStream) -> TokenStream {
|
|
print_helper(input, "BANG")
|
|
}
|
|
|
|
#[proc_macro]
|
|
pub fn print_bang_consume(input: TokenStream) -> TokenStream {
|
|
print_helper(input, "BANG");
|
|
TokenStream::new()
|
|
}
|
|
|
|
#[proc_macro_attribute]
|
|
pub fn print_attr(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
let debug = match &args.into_iter().collect::<Vec<_>>()[..] {
|
|
[TokenTree::Ident(ident)] if ident.to_string() == "nodebug" => false,
|
|
_ => true,
|
|
};
|
|
print_helper_ext(input, "ATTR", debug)
|
|
}
|
|
|
|
#[proc_macro_attribute]
|
|
pub fn print_attr_args(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
print_helper(args, "ATTR_ARGS");
|
|
input
|
|
}
|
|
|
|
#[proc_macro_attribute]
|
|
pub fn print_target_and_args(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
print_helper(args, "ATTR_ARGS");
|
|
print_helper(input.clone(), "ATTR");
|
|
input
|
|
}
|
|
|
|
#[proc_macro_attribute]
|
|
pub fn print_target_and_args_consume(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
print_helper(args, "ATTR_ARGS");
|
|
print_helper(input.clone(), "ATTR");
|
|
TokenStream::new()
|
|
}
|
|
|
|
#[proc_macro_derive(Print, attributes(print_helper))]
|
|
pub fn print_derive(input: TokenStream) -> TokenStream {
|
|
print_helper(input, "DERIVE");
|
|
TokenStream::new()
|
|
}
|