1 // force-host
2 // no-prefer-dynamic
3
4 // Proc macros commonly used by tests.
5 // `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros.
6
7 #![crate_type = "proc-macro"]
8
9 extern crate proc_macro;
10 use proc_macro::{TokenStream, TokenTree};
11
12 // Macro that return empty token stream.
13
14 #[proc_macro]
empty(_: TokenStream) -> TokenStream15 pub fn empty(_: TokenStream) -> TokenStream {
16 TokenStream::new()
17 }
18
19 #[proc_macro_attribute]
empty_attr(_: TokenStream, _: TokenStream) -> TokenStream20 pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream {
21 TokenStream::new()
22 }
23
24 #[proc_macro_derive(Empty, attributes(empty_helper))]
empty_derive(_: TokenStream) -> TokenStream25 pub fn empty_derive(_: TokenStream) -> TokenStream {
26 TokenStream::new()
27 }
28
29 // Macro that panics.
30
31 #[proc_macro]
panic_bang(_: TokenStream) -> TokenStream32 pub fn panic_bang(_: TokenStream) -> TokenStream {
33 panic!("panic-bang");
34 }
35
36 #[proc_macro_attribute]
panic_attr(_: TokenStream, _: TokenStream) -> TokenStream37 pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream {
38 panic!("panic-attr");
39 }
40
41 #[proc_macro_derive(Panic, attributes(panic_helper))]
panic_derive(_: TokenStream) -> TokenStream42 pub fn panic_derive(_: TokenStream) -> TokenStream {
43 panic!("panic-derive");
44 }
45
46 // Macros that return the input stream.
47
48 #[proc_macro]
identity(input: TokenStream) -> TokenStream49 pub fn identity(input: TokenStream) -> TokenStream {
50 input
51 }
52
53 #[proc_macro_attribute]
identity_attr(_: TokenStream, input: TokenStream) -> TokenStream54 pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream {
55 input
56 }
57
58 #[proc_macro_derive(Identity, attributes(identity_helper))]
identity_derive(input: TokenStream) -> TokenStream59 pub fn identity_derive(input: TokenStream) -> TokenStream {
60 input
61 }
62
63 // Macros that iterate and re-collect the input stream.
64
65 #[proc_macro]
recollect(input: TokenStream) -> TokenStream66 pub fn recollect(input: TokenStream) -> TokenStream {
67 input.into_iter().collect()
68 }
69
70 #[proc_macro_attribute]
recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream71 pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream {
72 input.into_iter().collect()
73 }
74
75 #[proc_macro_derive(Recollect, attributes(recollect_helper))]
recollect_derive(input: TokenStream) -> TokenStream76 pub fn recollect_derive(input: TokenStream) -> TokenStream {
77 input.into_iter().collect()
78 }
79
80 // Macros that print their input in the original and re-collected forms (if they differ).
81
print_helper(input: TokenStream, kind: &str) -> TokenStream82 fn print_helper(input: TokenStream, kind: &str) -> TokenStream {
83 print_helper_ext(input, kind, true)
84 }
85
deep_recollect(input: TokenStream) -> TokenStream86 fn deep_recollect(input: TokenStream) -> TokenStream {
87 input.into_iter().map(|tree| {
88 match tree {
89 TokenTree::Group(group) => {
90 let inner = deep_recollect(group.stream());
91 let mut new_group = TokenTree::Group(
92 proc_macro::Group::new(group.delimiter(), inner)
93 );
94 new_group.set_span(group.span());
95 new_group
96 }
97 _ => tree,
98 }
99 }).collect()
100 }
101
print_helper_ext(input: TokenStream, kind: &str, debug: bool) -> TokenStream102 fn print_helper_ext(input: TokenStream, kind: &str, debug: bool) -> TokenStream {
103 let input_display = format!("{}", input);
104 let input_debug = format!("{:#?}", input);
105 let recollected = input.clone().into_iter().collect();
106 let recollected_display = format!("{}", recollected);
107 let recollected_debug = format!("{:#?}", recollected);
108
109 let deep_recollected = deep_recollect(input);
110 let deep_recollected_display = format!("{}", deep_recollected);
111 let deep_recollected_debug = format!("{:#?}", deep_recollected);
112
113
114
115 println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display);
116 if recollected_display != input_display {
117 println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display);
118 }
119
120 if deep_recollected_display != recollected_display {
121 println!("PRINT-{} DEEP-RE-COLLECTED (DISPLAY): {}", kind, deep_recollected_display);
122 }
123
124 if debug {
125 println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug);
126 if recollected_debug != input_debug {
127 println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug);
128 }
129 if deep_recollected_debug != recollected_debug {
130 println!("PRINT-{} DEEP-RE-COLLETED (DEBUG): {}", kind, deep_recollected_debug);
131 }
132 }
133 recollected
134 }
135
136 #[proc_macro]
print_bang(input: TokenStream) -> TokenStream137 pub fn print_bang(input: TokenStream) -> TokenStream {
138 print_helper(input, "BANG")
139 }
140
141 #[proc_macro]
print_bang_consume(input: TokenStream) -> TokenStream142 pub fn print_bang_consume(input: TokenStream) -> TokenStream {
143 print_helper(input, "BANG");
144 TokenStream::new()
145 }
146
147 #[proc_macro_attribute]
print_attr(args: TokenStream, input: TokenStream) -> TokenStream148 pub fn print_attr(args: TokenStream, input: TokenStream) -> TokenStream {
149 let debug = match &args.into_iter().collect::<Vec<_>>()[..] {
150 [TokenTree::Ident(ident)] if ident.to_string() == "nodebug" => false,
151 _ => true,
152 };
153 print_helper_ext(input, "ATTR", debug)
154 }
155
156 #[proc_macro_attribute]
print_attr_args(args: TokenStream, input: TokenStream) -> TokenStream157 pub fn print_attr_args(args: TokenStream, input: TokenStream) -> TokenStream {
158 print_helper(args, "ATTR_ARGS");
159 input
160 }
161
162 #[proc_macro_attribute]
print_target_and_args(args: TokenStream, input: TokenStream) -> TokenStream163 pub fn print_target_and_args(args: TokenStream, input: TokenStream) -> TokenStream {
164 print_helper(args, "ATTR_ARGS");
165 print_helper(input.clone(), "ATTR");
166 input
167 }
168
169 #[proc_macro_attribute]
print_target_and_args_consume(args: TokenStream, input: TokenStream) -> TokenStream170 pub fn print_target_and_args_consume(args: TokenStream, input: TokenStream) -> TokenStream {
171 print_helper(args, "ATTR_ARGS");
172 print_helper(input.clone(), "ATTR");
173 TokenStream::new()
174 }
175
176 #[proc_macro_derive(Print, attributes(print_helper))]
print_derive(input: TokenStream) -> TokenStream177 pub fn print_derive(input: TokenStream) -> TokenStream {
178 print_helper(input, "DERIVE");
179 TokenStream::new()
180 }
181