1#![doc = include_str!("../README.md")]
2
3use proc_macro::TokenStream;
4use proc_macro2::TokenStream as TokenStream2;
5use syn::{parse_macro_input, parse_quote, parse_quote_spanned, spanned::Spanned, Attribute, Block, Error, Expr, ItemFn, ExprMacro, Result, Stmt};
6use quote::ToTokens;
7#[proc_macro_attribute]
69pub fn log(args: TokenStream, input: TokenStream) -> TokenStream {
70 let mut item = parse_macro_input!(input as ItemFn);
71 let args = TokenStream2::from(args);
72
73 item.block.stmts.insert(0, parse_quote!(
74 let _logger = ::report::Report::log(|| format!(#args));
75 ));
76
77 return TokenStream::from(item.to_token_stream())
78}
79
80#[proc_macro_attribute]
165pub fn report(args: TokenStream, input: TokenStream) -> TokenStream {
166
167 let mut item = parse_macro_input!(input as ItemFn);
168
169 if !args.is_empty() {
170 let args = TokenStream2::from(args);
171 let mut error = Error::new_spanned(args, "This attribute does not take any arguments")
172 .to_compile_error();
173 error.extend(item.to_token_stream());
174 return TokenStream::from(error);
175 }
176
177 if let Err(err) = iter_block(&mut item.block) {
178 return TokenStream::from(err.to_compile_error())
179 }
180
181 return TokenStream::from(item.to_token_stream())
182}
183
184fn process_expr(expr: &mut Expr, local_attrs: Option<&mut Vec<Attribute>>) -> Result<()> {
185 iter_expr(expr)?;
186
187 let mut attrs = Vec::new();
188
189 if let Some(local_attrs) = local_attrs {
190 local_attrs.retain(|attr| {
191 let res = !attr.path().is_ident("report");
192 if !res { attrs.push(attr.clone()) }
193 res
194 });
195 }
196
197 if let Some(expr_attrs) = get_attrs(expr) {
198 expr_attrs.retain(|attr| {
199 let res = !attr.path().is_ident("report");
200 if !res { attrs.push(attr.clone()) }
201 res
202 });
203 }
204
205 for attr in attrs {
206 let list = attr.meta.require_list()?.tokens.clone();
207 *expr = parse_quote_spanned!(attr.span() => {
208 let _logger = ::report::Report::rec(|| format!(#list));
209 #expr
210 });
211 }
212
213 return Ok(());
214}
215
216fn iter_block(block: &mut Block) -> Result<()> {
217 for statement in block.stmts.iter_mut() {
218 match statement {
219 Stmt::Local(local) => if let Some(init) = local.init.as_mut() {
220 process_expr(&mut init.expr, Some(&mut local.attrs))?;
221 if let Some((.., expr)) = init.diverge.as_mut() {
222 iter_expr(expr)?;
223 }
224 },
225 Stmt::Expr(expr, ..) => {
226 process_expr(expr, None)?;
227 },
228 Stmt::Macro(macro_expr) => {
229 let mut attrs = Vec::new();
230
231 macro_expr.attrs.retain(|attr| {
232 let res = !attr.path().is_ident("report");
233 if !res { attrs.push(attr.clone()) }
234 res
235 });
236
237 if attrs.is_empty() { continue }
238 let mut expr = Expr::Macro(ExprMacro {
239 attrs,
240 mac: macro_expr.mac.clone()
241 });
242
243 process_expr(&mut expr, None)?;
244 *statement = Stmt::Expr(expr, macro_expr.semi_token)
245 },
246 Stmt::Item(..) => ()
247 }
248 }
249 Ok(())
250}
251
252fn iter_expr(expr: &mut Expr) -> Result<()> {
253 match expr {
254 Expr::Try(try_expr) => process_expr(&mut try_expr.expr, None),
255 Expr::Call(call_expr) => {
256 process_expr(&mut call_expr.func, None)?;
257 for arg in call_expr.args.iter_mut() {
258 process_expr(arg, None)?;
259 }
260 Ok(())
261 },
262 Expr::Tuple(tuple_expr) => {
263 for expr in tuple_expr.elems.iter_mut() {
264 process_expr(expr, None)?;
265 }
266 Ok(())
267 },
268 Expr::Macro(..) => Ok(()),
269 Expr::MethodCall(method_call_expr) => {
270 process_expr(&mut method_call_expr.receiver, None)?;
271 for arg in method_call_expr.args.iter_mut() {
272 process_expr(arg, None)?;
273 }
274 Ok(())
275 },
276 Expr::Match(match_expr) => {
277 process_expr(&mut match_expr.expr, None)?;
278 for arm in match_expr.arms.iter_mut() {
279 process_expr(arm.body.as_mut(), Some(arm.attrs.as_mut()))?;
280 }
281 Ok(())
282 },
283 Expr::Closure(closure_expr) => {
284 process_expr(&mut closure_expr.body, None)?;
285 Ok(())
286 },
287 Expr::Unsafe(unsafe_expr) => iter_block(&mut unsafe_expr.block),
288 Expr::Block(block_expr) => iter_block(&mut block_expr.block),
289 Expr::Assign(assign_expr) => {
290 process_expr(&mut assign_expr.left, None)?;
291 process_expr(&mut assign_expr.right, None)
292 },
293 Expr::Field(field_expr) => process_expr(&mut field_expr.base, None),
294 Expr::Index(index_expr) => {
295 process_expr(&mut index_expr.expr, None)?;
296 process_expr(&mut index_expr.index, None)
297 },
298 Expr::Range(range_expr) => {
299 if let Some(start) = range_expr.start.as_mut() {
300 process_expr(start, None)?;
301 }
302 if let Some(end) = range_expr.end.as_mut() {
303 process_expr(end, None)?;
304 }
305 Ok(())
306 },
307 Expr::Path(..) => Ok(()),
308 Expr::Reference(reference_expr) => process_expr(&mut reference_expr.expr, None),
309 Expr::Break(break_expr) => if let Some(expr) = break_expr.expr.as_mut() {
310 process_expr(expr, None)
311 } else { Ok(()) },
312 Expr::Continue(..) => Ok(()),
313 Expr::Return(return_expr) => if let Some(expr) = return_expr.expr.as_mut() {
314 process_expr(expr, None)
315 } else { Ok(()) },
316 Expr::Struct(struct_expr) => {
317 for field in struct_expr.fields.iter_mut() {
318 process_expr(&mut field.expr, None)?;
319 }
320 Ok(())
321 },
322 Expr::Repeat(repeat_expr) => {
323 process_expr(&mut repeat_expr.expr, None)?;
324 process_expr(&mut repeat_expr.len, None)
325 },
326 Expr::Paren(paren_expr) => process_expr(&mut paren_expr.expr, None),
327 Expr::Group(group_expr) => process_expr(&mut group_expr.expr, None),
328 Expr::TryBlock(try_block_expr) => iter_block(&mut try_block_expr.block),
329 Expr::Async(async_expr) => iter_block(&mut async_expr.block),
330 Expr::Await(await_expr) => process_expr(&mut await_expr.base, None),
331 Expr::Yield(yield_expr) => if let Some(expr) = yield_expr.expr.as_mut() {
332 process_expr(expr, None)
333 } else { Ok(()) },
334 Expr::ForLoop(for_loop_expr) => {
335 process_expr(&mut for_loop_expr.expr, None)?;
336 iter_block(&mut for_loop_expr.body)
337 },
338 Expr::While(while_expr) => {
339 process_expr(&mut while_expr.cond, None)?;
340 iter_block(&mut while_expr.body)
341 },
342 Expr::Loop(loop_expr) => iter_block(&mut loop_expr.body),
343 Expr::If(if_expr) => {
344 process_expr(&mut if_expr.cond, None)?;
345 iter_block(&mut if_expr.then_branch)?;
346 if let Some((_, else_branch)) = if_expr.else_branch.as_mut() {
347 process_expr(else_branch, None)?;
348 }
349 Ok(())
350 },
351 Expr::Let(let_expr) => process_expr(&mut let_expr.expr, None),
352 Expr::Lit(..) => Ok(()),
353 Expr::Cast(cast_expr) => {
354 process_expr(&mut cast_expr.expr, None)?;
355 Ok(())
356 },
357 Expr::Infer(..) => Ok(()),
358 Expr::Array(array_expr) => {
359 for expr in array_expr.elems.iter_mut() {
360 process_expr(expr, None)?;
361 }
362 Ok(())
363 },
364 Expr::Unary(unary_expr) => process_expr(&mut unary_expr.expr, None),
365 Expr::Binary(binary_expr) => {
366 process_expr(&mut binary_expr.left, None)?;
367 process_expr(&mut binary_expr.right, None)
368 },
369 Expr::Const(const_expr) => iter_block(&mut const_expr.block),
370 _ => Ok(())
371 }
372}
373
374fn get_attrs(expr: &mut Expr) -> Option<&mut Vec<Attribute>> {
375 match expr {
376 Expr::Try(try_expr) => Some(&mut try_expr.attrs),
377 Expr::Call(call_expr) => Some(&mut call_expr.attrs),
378 Expr::Tuple(tuple_expr) => Some(&mut tuple_expr.attrs),
379 Expr::Macro(macro_expr) => Some(&mut macro_expr.attrs),
380 Expr::MethodCall(method_call_expr) => Some(&mut method_call_expr.attrs),
381 Expr::Match(match_expr) => Some(&mut match_expr.attrs),
382 Expr::Closure(closure_expr) => Some(&mut closure_expr.attrs),
383 Expr::Unsafe(unsafe_expr) => Some(&mut unsafe_expr.attrs),
384 Expr::Block(block_expr) => Some(&mut block_expr.attrs),
385 Expr::Assign(assign_expr) => Some(&mut assign_expr.attrs),
386 Expr::Field(field_expr) => Some(&mut field_expr.attrs),
387 Expr::Index(index_expr) => Some(&mut index_expr.attrs),
388 Expr::Range(range_expr) => Some(&mut range_expr.attrs),
389 Expr::Path(path_expr) => Some(&mut path_expr.attrs),
390 Expr::Reference(reference_expr) => Some(&mut reference_expr.attrs),
391 Expr::Break(break_expr) => Some(&mut break_expr.attrs),
392 Expr::Continue(continue_expr) => Some(&mut continue_expr.attrs),
393 Expr::Return(return_expr) => Some(&mut return_expr.attrs),
394 Expr::Struct(struct_expr) => Some(&mut struct_expr.attrs),
395 Expr::Repeat(repeat_expr) => Some(&mut repeat_expr.attrs),
396 Expr::Paren(paren_expr) => Some(&mut paren_expr.attrs),
397 Expr::Group(group_expr) => Some(&mut group_expr.attrs),
398 Expr::TryBlock(try_block_expr) => Some(&mut try_block_expr.attrs),
399 Expr::Async(async_expr) => Some(&mut async_expr.attrs),
400 Expr::Await(await_expr) => Some(&mut await_expr.attrs),
401 Expr::Yield(yield_expr) => Some(&mut yield_expr.attrs),
402 Expr::ForLoop(for_loop_expr) => Some(&mut for_loop_expr.attrs),
403 Expr::While(while_expr) => Some(&mut while_expr.attrs),
404 Expr::Loop(loop_expr) => Some(&mut loop_expr.attrs),
405 Expr::If(if_expr) => Some(&mut if_expr.attrs),
406 Expr::Let(let_expr) => Some(&mut let_expr.attrs),
407 Expr::Lit(lit_expr) => Some(&mut lit_expr.attrs),
408 Expr::Cast(cast_expr) => Some(&mut cast_expr.attrs),
409 Expr::Infer(info_expr) => Some(&mut info_expr.attrs),
410 Expr::Array(array_expr) => Some(&mut array_expr.attrs),
411 Expr::Unary(unary_expr) => Some(&mut unary_expr.attrs),
412 Expr::Binary(binary_expr) => Some(&mut binary_expr.attrs),
413 Expr::Const(const_expr) => Some(&mut const_expr.attrs),
414 _ => None
415 }
416}