async_log_attributes/
lib.rs1#![forbid(unsafe_code, future_incompatible, rust_2018_idioms)]
4#![deny(missing_debug_implementations, nonstandard_style)]
5#![recursion_limit = "512"]
6
7extern crate proc_macro;
8
9use proc_macro::TokenStream;
10use quote::quote;
11
12#[proc_macro_attribute]
23pub fn instrument(_attr: TokenStream, item: TokenStream) -> TokenStream {
24 let input = syn::parse_macro_input!(item as syn::ItemFn);
25
26 let attrs = &input.attrs;
27 let vis = &input.vis;
28 let constness = &input.constness;
29 let unsafety = &input.unsafety;
30 let asyncness = &input.asyncness;
31 let abi = &input.abi;
32
33 let generics = &input.decl.generics;
34 let name = &input.ident;
35 let inputs = &input.decl.inputs;
36 let output = &input.decl.output;
37 let body = &input.block.stmts;
38
39 let args: Vec<syn::Pat> = inputs
40 .pairs()
41 .filter_map(|pair| match pair.into_value() {
42 syn::FnArg::Captured(arg) => Some(arg.pat.clone()),
43 _ => return None,
44 })
45 .collect();
46
47 let names: String = args
48 .iter()
49 .enumerate()
50 .map(|(i, _arg)| {
51 let mut string = format!(", arg_{}", i);
52 string.push_str("={}");
53 string
54 })
55 .collect();
56
57 let result = quote! {
58 #(#attrs)*
59 #vis #constness #unsafety #asyncness #abi fn #generics #name(#(#inputs)*) #output {
60 let __name = format!("{}#{}", file!(), stringify!(#name));
61 let __args = format!("{}{}", __name, format_args!(#names, #(#args)*));
62 async_log::span!(__args, {
63 #(#body)*
64 })
65 }
66 };
67
68 result.into()
69}