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]
11macro_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]
109macro_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]
127macro_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]
140macro_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]
159macro_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]
174macro_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]
189macro_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]
197macro_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