• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #[macro_use]
2 extern crate proc_macro_error;
3 extern crate proc_macro;
4 
5 use proc_macro2::{Span, TokenStream};
6 use proc_macro_error::{
7     abort, abort_call_site, diagnostic, emit_call_site_warning, emit_error, emit_warning,
8     proc_macro_error, set_dummy, Diagnostic, Level, OptionExt, ResultExt, SpanRange,
9 };
10 
11 use syn::{parse_macro_input, spanned::Spanned};
12 
13 // Macros and Diagnostic
14 
15 #[proc_macro]
16 #[proc_macro_error]
abort_from(input: proc_macro::TokenStream) -> proc_macro::TokenStream17 pub fn abort_from(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
18     let span = input.into_iter().next().unwrap().span();
19     abort!(
20         span,
21         syn::Error::new(Span::call_site(), "abort!(span, from) test")
22     )
23 }
24 
25 #[proc_macro]
26 #[proc_macro_error]
abort_to_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream27 pub fn abort_to_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
28     let span = input.into_iter().next().unwrap().span();
29     abort!(span, "abort!(span, single_expr) test")
30 }
31 
32 #[proc_macro]
33 #[proc_macro_error]
abort_format(input: proc_macro::TokenStream) -> proc_macro::TokenStream34 pub fn abort_format(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
35     let span = input.into_iter().next().unwrap().span();
36     abort!(span, "abort!(span, expr1, {}) test", "expr2")
37 }
38 
39 #[proc_macro]
40 #[proc_macro_error]
abort_call_site_test(_: proc_macro::TokenStream) -> proc_macro::TokenStream41 pub fn abort_call_site_test(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
42     abort_call_site!("abort_call_site! test")
43 }
44 
45 #[proc_macro]
46 #[proc_macro_error]
direct_abort(input: proc_macro::TokenStream) -> proc_macro::TokenStream47 pub fn direct_abort(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
48     let span = input.into_iter().next().unwrap().span();
49     Diagnostic::spanned(span.into(), Level::Error, "Diagnostic::abort() test".into()).abort()
50 }
51 
52 #[proc_macro]
53 #[proc_macro_error]
emit(input: proc_macro::TokenStream) -> proc_macro::TokenStream54 pub fn emit(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
55     let mut spans = input.into_iter().step_by(2).map(|t| t.span());
56     emit_error!(
57         spans.next().unwrap(),
58         syn::Error::new(Span::call_site(), "emit!(span, from) test")
59     );
60     emit_error!(
61         spans.next().unwrap(),
62         "emit!(span, expr1, {}) test",
63         "expr2"
64     );
65     emit_error!(spans.next().unwrap(), "emit!(span, single_expr) test");
66     Diagnostic::spanned(
67         spans.next().unwrap().into(),
68         Level::Error,
69         "Diagnostic::emit() test".into(),
70     )
71     .emit();
72 
73     emit_call_site_error!("emit_call_site_error!(expr) test");
74 
75     // NOOP on stable, just checking that the macros themselves compile.
76     emit_warning!(spans.next().unwrap(), "emit_warning! test");
77     emit_call_site_warning!("emit_call_site_warning! test");
78 
79     quote!().into()
80 }
81 
82 // Notes
83 
84 #[proc_macro]
85 #[proc_macro_error]
abort_notes(input: proc_macro::TokenStream) -> proc_macro::TokenStream86 pub fn abort_notes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
87     let mut spans = input.into_iter().map(|s| s.span());
88     let span = spans.next().unwrap();
89     let span2 = spans.next().unwrap();
90 
91     let some_note = Some("Some note");
92     let none_note: Option<&'static str> = None;
93 
94     abort! {
95         span, "This is {} error", "an";
96 
97         note = "simple note";
98         help = "simple help";
99         hint = "simple hint";
100         yay = "simple yay";
101 
102         note = "format {}", "note";
103 
104         note =? some_note;
105         note =? none_note;
106 
107         note = span2 => "spanned simple note";
108         note = span2 => "spanned format {}", "note";
109         note =? span2 => some_note;
110         note =? span2 => none_note;
111     }
112 }
113 
114 #[proc_macro]
115 #[proc_macro_error]
emit_notes(input: proc_macro::TokenStream) -> proc_macro::TokenStream116 pub fn emit_notes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
117     let mut spans = input.into_iter().step_by(2).map(|s| s.span());
118     let span = spans.next().unwrap();
119     let span2 = spans.next().unwrap();
120 
121     let some_note = Some("Some note");
122     let none_note: Option<&'static str> = None;
123 
124     abort! {
125         span, "This is {} error", "an";
126 
127         note = "simple note";
128         help = "simple help";
129         hint = "simple hint";
130         yay = "simple yay";
131 
132         note = "format {}", "note";
133 
134         note =? some_note;
135         note =? none_note;
136 
137         note = span2 => "spanned simple note";
138         note = span2 => "spanned format {}", "note";
139         note =? span2 => some_note;
140         note =? span2 => none_note;
141     }
142 }
143 
144 // Extension traits
145 
146 #[proc_macro]
147 #[proc_macro_error]
option_ext(_input: proc_macro::TokenStream) -> proc_macro::TokenStream148 pub fn option_ext(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
149     let none: Option<Diagnostic> = None;
150     none.expect_or_abort("Option::expect_or_abort() test");
151     quote!().into()
152 }
153 
154 #[proc_macro]
155 #[proc_macro_error]
result_unwrap_or_abort(input: proc_macro::TokenStream) -> proc_macro::TokenStream156 pub fn result_unwrap_or_abort(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
157     let span = input.into_iter().next().unwrap().span();
158     let err = Diagnostic::spanned(
159         span.into(),
160         Level::Error,
161         "Result::unwrap_or_abort() test".to_string(),
162     );
163     let res: Result<(), _> = Err(err);
164     res.unwrap_or_abort();
165     quote!().into()
166 }
167 
168 #[proc_macro]
169 #[proc_macro_error]
result_expect_or_abort(input: proc_macro::TokenStream) -> proc_macro::TokenStream170 pub fn result_expect_or_abort(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
171     let span = input.into_iter().next().unwrap().span();
172     let err = Diagnostic::spanned(
173         span.into(),
174         Level::Error,
175         "Result::expect_or_abort() test".to_string(),
176     );
177     let res: Result<(), _> = Err(err);
178     res.expect_or_abort("BOOM");
179     quote!().into()
180 }
181 
182 // Dummy
183 
184 #[proc_macro]
185 #[proc_macro_error]
dummy(input: proc_macro::TokenStream) -> proc_macro::TokenStream186 pub fn dummy(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
187     let span = input.into_iter().next().unwrap().span();
188     set_dummy(quote! {
189         impl Default for NeedDefault {
190             fn default() -> Self { NeedDefault::A }
191         }
192     });
193 
194     abort!(span, "set_dummy test")
195 }
196 
197 #[proc_macro]
198 #[proc_macro_error]
append_dummy(input: proc_macro::TokenStream) -> proc_macro::TokenStream199 pub fn append_dummy(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
200     let span = input.into_iter().next().unwrap().span();
201     set_dummy(quote! {
202         impl Default for NeedDefault
203     });
204 
205     proc_macro_error::append_dummy(quote!({
206         fn default() -> Self {
207             NeedDefault::A
208         }
209     }));
210 
211     abort!(span, "append_dummy test")
212 }
213 
214 // Panic
215 
216 #[proc_macro]
217 #[proc_macro_error]
unrelated_panic(_input: proc_macro::TokenStream) -> proc_macro::TokenStream218 pub fn unrelated_panic(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
219     panic!("unrelated panic test")
220 }
221 
222 // Success
223 
224 #[proc_macro]
225 #[proc_macro_error]
ok(input: proc_macro::TokenStream) -> proc_macro::TokenStream226 pub fn ok(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
227     let input = TokenStream::from(input);
228     quote!(fn #input() {}).into()
229 }
230 
231 // Multiple tokens
232 
233 #[proc_macro_attribute]
234 #[proc_macro_error]
multiple_tokens( _: proc_macro::TokenStream, input: proc_macro::TokenStream, ) -> proc_macro::TokenStream235 pub fn multiple_tokens(
236     _: proc_macro::TokenStream,
237     input: proc_macro::TokenStream,
238 ) -> proc_macro::TokenStream {
239     let input = proc_macro2::TokenStream::from(input);
240     abort!(input, "...");
241 }
242 
243 #[proc_macro]
244 #[proc_macro_error]
to_tokens_span(input: proc_macro::TokenStream) -> proc_macro::TokenStream245 pub fn to_tokens_span(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
246     let ty = parse_macro_input!(input as syn::Type);
247     emit_error!(ty, "whole type");
248     emit_error!(ty.span(), "explicit .span()");
249     quote!().into()
250 }
251 
252 #[proc_macro]
253 #[proc_macro_error]
explicit_span_range(input: proc_macro::TokenStream) -> proc_macro::TokenStream254 pub fn explicit_span_range(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
255     let mut spans = input.into_iter().step_by(2).map(|s| s.span());
256     let first = Span::from(spans.next().unwrap());
257     let last = Span::from(spans.nth(1).unwrap());
258     abort!(SpanRange { first, last }, "explicit SpanRange")
259 }
260 
261 // Children messages
262 
263 #[proc_macro]
264 #[proc_macro_error]
children_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream265 pub fn children_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
266     let mut spans = input.into_iter().step_by(2).map(|s| s.span());
267     diagnostic!(spans.next().unwrap(), Level::Error, "main macro message")
268         .span_error(spans.next().unwrap().into(), "child message".into())
269         .emit();
270 
271     let mut main = syn::Error::new(spans.next().unwrap().into(), "main syn::Error");
272     let child = syn::Error::new(spans.next().unwrap().into(), "child syn::Error");
273     main.combine(child);
274     Diagnostic::from(main).abort()
275 }
276