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