1 | // FIXME: this can be greatly simplified via $()? |
2 | // as soon as MRSV hits 1.32 |
3 | |
4 | /// Build [`Diagnostic`](struct.Diagnostic.html) instance from provided arguments. |
5 | /// |
6 | /// # Syntax |
7 | /// |
8 | /// See [the guide](index.html#guide). |
9 | /// |
10 | #[macro_export ] |
11 | macro_rules! diagnostic { |
12 | // from alias |
13 | ($err:expr) => { $crate::Diagnostic::from($err) }; |
14 | |
15 | // span, message, help |
16 | ($span:expr, $level:expr, $fmt:expr, $($args:expr),+ ; $($rest:tt)+) => {{ |
17 | #[allow(unused_imports)] |
18 | use $crate::__export::{ |
19 | ToTokensAsSpanRange, |
20 | Span2AsSpanRange, |
21 | SpanAsSpanRange, |
22 | SpanRangeAsSpanRange |
23 | }; |
24 | use $crate::DiagnosticExt; |
25 | let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(); |
26 | |
27 | let diag = $crate::Diagnostic::spanned_range( |
28 | span_range, |
29 | $level, |
30 | format!($fmt, $($args),*) |
31 | ); |
32 | $crate::__pme__suggestions!(diag $($rest)*); |
33 | diag |
34 | }}; |
35 | |
36 | ($span:expr, $level:expr, $msg:expr ; $($rest:tt)+) => {{ |
37 | #[allow(unused_imports)] |
38 | use $crate::__export::{ |
39 | ToTokensAsSpanRange, |
40 | Span2AsSpanRange, |
41 | SpanAsSpanRange, |
42 | SpanRangeAsSpanRange |
43 | }; |
44 | use $crate::DiagnosticExt; |
45 | let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(); |
46 | |
47 | let diag = $crate::Diagnostic::spanned_range(span_range, $level, $msg.to_string()); |
48 | $crate::__pme__suggestions!(diag $($rest)*); |
49 | diag |
50 | }}; |
51 | |
52 | // span, message, no help |
53 | ($span:expr, $level:expr, $fmt:expr, $($args:expr),+) => {{ |
54 | #[allow(unused_imports)] |
55 | use $crate::__export::{ |
56 | ToTokensAsSpanRange, |
57 | Span2AsSpanRange, |
58 | SpanAsSpanRange, |
59 | SpanRangeAsSpanRange |
60 | }; |
61 | use $crate::DiagnosticExt; |
62 | let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(); |
63 | |
64 | $crate::Diagnostic::spanned_range( |
65 | span_range, |
66 | $level, |
67 | format!($fmt, $($args),*) |
68 | ) |
69 | }}; |
70 | |
71 | ($span:expr, $level:expr, $msg:expr) => {{ |
72 | #[allow(unused_imports)] |
73 | use $crate::__export::{ |
74 | ToTokensAsSpanRange, |
75 | Span2AsSpanRange, |
76 | SpanAsSpanRange, |
77 | SpanRangeAsSpanRange |
78 | }; |
79 | use $crate::DiagnosticExt; |
80 | let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange(); |
81 | |
82 | $crate::Diagnostic::spanned_range(span_range, $level, $msg.to_string()) |
83 | }}; |
84 | |
85 | |
86 | // trailing commas |
87 | |
88 | ($span:expr, $level:expr, $fmt:expr, $($args:expr),+, ; $($rest:tt)+) => { |
89 | $crate::diagnostic!($span, $level, $fmt, $($args),* ; $($rest)*) |
90 | }; |
91 | ($span:expr, $level:expr, $msg:expr, ; $($rest:tt)+) => { |
92 | $crate::diagnostic!($span, $level, $msg ; $($rest)*) |
93 | }; |
94 | ($span:expr, $level:expr, $fmt:expr, $($args:expr),+,) => { |
95 | $crate::diagnostic!($span, $level, $fmt, $($args),*) |
96 | }; |
97 | ($span:expr, $level:expr, $msg:expr,) => { |
98 | $crate::diagnostic!($span, $level, $msg) |
99 | }; |
100 | // ($err:expr,) => { $crate::diagnostic!($err) }; |
101 | } |
102 | |
103 | /// Abort proc-macro execution right now and display the error. |
104 | /// |
105 | /// # Syntax |
106 | /// |
107 | /// See [the guide](index.html#guide). |
108 | #[macro_export ] |
109 | macro_rules! abort { |
110 | ($err:expr) => { |
111 | $crate::diagnostic!($err).abort() |
112 | }; |
113 | |
114 | ($span:expr, $($tts:tt)*) => { |
115 | $crate::diagnostic!($span, $crate::Level::Error, $($tts)*).abort() |
116 | }; |
117 | } |
118 | |
119 | /// Shortcut for `abort!(Span::call_site(), msg...)`. This macro |
120 | /// is still preferable over plain panic, panics are not for error reporting. |
121 | /// |
122 | /// # Syntax |
123 | /// |
124 | /// See [the guide](index.html#guide). |
125 | /// |
126 | #[macro_export ] |
127 | macro_rules! abort_call_site { |
128 | ($($tts:tt)*) => { |
129 | $crate::abort!($crate::__export::proc_macro2::Span::call_site(), $($tts)*) |
130 | }; |
131 | } |
132 | |
133 | /// Emit an error while not aborting the proc-macro right away. |
134 | /// |
135 | /// # Syntax |
136 | /// |
137 | /// See [the guide](index.html#guide). |
138 | /// |
139 | #[macro_export ] |
140 | macro_rules! emit_error { |
141 | ($err:expr) => { |
142 | $crate::diagnostic!($err).emit() |
143 | }; |
144 | |
145 | ($span:expr, $($tts:tt)*) => {{ |
146 | let level = $crate::Level::Error; |
147 | $crate::diagnostic!($span, level, $($tts)*).emit() |
148 | }}; |
149 | } |
150 | |
151 | /// Shortcut for `emit_error!(Span::call_site(), ...)`. This macro |
152 | /// is still preferable over plain panic, panics are not for error reporting.. |
153 | /// |
154 | /// # Syntax |
155 | /// |
156 | /// See [the guide](index.html#guide). |
157 | /// |
158 | #[macro_export ] |
159 | macro_rules! emit_call_site_error { |
160 | ($($tts:tt)*) => { |
161 | $crate::emit_error!($crate::__export::proc_macro2::Span::call_site(), $($tts)*) |
162 | }; |
163 | } |
164 | |
165 | /// Emit a warning. Warnings are not errors and compilation won't fail because of them. |
166 | /// |
167 | /// **Does nothing on stable** |
168 | /// |
169 | /// # Syntax |
170 | /// |
171 | /// See [the guide](index.html#guide). |
172 | /// |
173 | #[macro_export ] |
174 | macro_rules! emit_warning { |
175 | ($span:expr, $($tts:tt)*) => { |
176 | $crate::diagnostic!($span, $crate::Level::Warning, $($tts)*).emit() |
177 | }; |
178 | } |
179 | |
180 | /// Shortcut for `emit_warning!(Span::call_site(), ...)`. |
181 | /// |
182 | /// **Does nothing on stable** |
183 | /// |
184 | /// # Syntax |
185 | /// |
186 | /// See [the guide](index.html#guide). |
187 | /// |
188 | #[macro_export ] |
189 | macro_rules! emit_call_site_warning { |
190 | ($($tts:tt)*) => {{ |
191 | $crate::emit_warning!($crate::__export::proc_macro2::Span::call_site(), $($tts)*) |
192 | }}; |
193 | } |
194 | |
195 | #[doc (hidden)] |
196 | #[macro_export ] |
197 | macro_rules! __pme__suggestions { |
198 | ($var:ident) => (); |
199 | |
200 | ($var:ident $help:ident =? $msg:expr) => { |
201 | let $var = if let Some(msg) = $msg { |
202 | $var.suggestion(stringify!($help), msg.to_string()) |
203 | } else { |
204 | $var |
205 | }; |
206 | }; |
207 | ($var:ident $help:ident =? $span:expr => $msg:expr) => { |
208 | let $var = if let Some(msg) = $msg { |
209 | $var.span_suggestion($span.into(), stringify!($help), msg.to_string()) |
210 | } else { |
211 | $var |
212 | }; |
213 | }; |
214 | |
215 | ($var:ident $help:ident =? $msg:expr ; $($rest:tt)*) => { |
216 | $crate::__pme__suggestions!($var $help =? $msg); |
217 | $crate::__pme__suggestions!($var $($rest)*); |
218 | }; |
219 | ($var:ident $help:ident =? $span:expr => $msg:expr ; $($rest:tt)*) => { |
220 | $crate::__pme__suggestions!($var $help =? $span => $msg); |
221 | $crate::__pme__suggestions!($var $($rest)*); |
222 | }; |
223 | |
224 | |
225 | ($var:ident $help:ident = $msg:expr) => { |
226 | let $var = $var.suggestion(stringify!($help), $msg.to_string()); |
227 | }; |
228 | ($var:ident $help:ident = $fmt:expr, $($args:expr),+) => { |
229 | let $var = $var.suggestion( |
230 | stringify!($help), |
231 | format!($fmt, $($args),*) |
232 | ); |
233 | }; |
234 | ($var:ident $help:ident = $span:expr => $msg:expr) => { |
235 | let $var = $var.span_suggestion($span.into(), stringify!($help), $msg.to_string()); |
236 | }; |
237 | ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),+) => { |
238 | let $var = $var.span_suggestion( |
239 | $span.into(), |
240 | stringify!($help), |
241 | format!($fmt, $($args),*) |
242 | ); |
243 | }; |
244 | |
245 | ($var:ident $help:ident = $msg:expr ; $($rest:tt)*) => { |
246 | $crate::__pme__suggestions!($var $help = $msg); |
247 | $crate::__pme__suggestions!($var $($rest)*); |
248 | }; |
249 | ($var:ident $help:ident = $fmt:expr, $($args:expr),+ ; $($rest:tt)*) => { |
250 | $crate::__pme__suggestions!($var $help = $fmt, $($args),*); |
251 | $crate::__pme__suggestions!($var $($rest)*); |
252 | }; |
253 | ($var:ident $help:ident = $span:expr => $msg:expr ; $($rest:tt)*) => { |
254 | $crate::__pme__suggestions!($var $help = $span => $msg); |
255 | $crate::__pme__suggestions!($var $($rest)*); |
256 | }; |
257 | ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),+ ; $($rest:tt)*) => { |
258 | $crate::__pme__suggestions!($var $help = $span => $fmt, $($args),*); |
259 | $crate::__pme__suggestions!($var $($rest)*); |
260 | }; |
261 | |
262 | // trailing commas |
263 | |
264 | ($var:ident $help:ident = $msg:expr,) => { |
265 | $crate::__pme__suggestions!($var $help = $msg) |
266 | }; |
267 | ($var:ident $help:ident = $fmt:expr, $($args:expr),+,) => { |
268 | $crate::__pme__suggestions!($var $help = $fmt, $($args)*) |
269 | }; |
270 | ($var:ident $help:ident = $span:expr => $msg:expr,) => { |
271 | $crate::__pme__suggestions!($var $help = $span => $msg) |
272 | }; |
273 | ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),*,) => { |
274 | $crate::__pme__suggestions!($var $help = $span => $fmt, $($args)*) |
275 | }; |
276 | ($var:ident $help:ident = $msg:expr, ; $($rest:tt)*) => { |
277 | $crate::__pme__suggestions!($var $help = $msg; $($rest)*) |
278 | }; |
279 | ($var:ident $help:ident = $fmt:expr, $($args:expr),+, ; $($rest:tt)*) => { |
280 | $crate::__pme__suggestions!($var $help = $fmt, $($args),*; $($rest)*) |
281 | }; |
282 | ($var:ident $help:ident = $span:expr => $msg:expr, ; $($rest:tt)*) => { |
283 | $crate::__pme__suggestions!($var $help = $span => $msg; $($rest)*) |
284 | }; |
285 | ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),+, ; $($rest:tt)*) => { |
286 | $crate::__pme__suggestions!($var $help = $span => $fmt, $($args),*; $($rest)*) |
287 | }; |
288 | } |
289 | |