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