extern crate proc_macro;
use quote::ToTokens;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, AttributeArgs, ItemFn, Token, spanned::Spanned};
#[cfg(feature = "todo_attr")]
#[proc_macro_attribute]
pub fn todo_attr(attr: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(attr as AttributeArgs);
let message = if !args.is_empty() {
let first_arg = &args[0];
if let syn::NestedMeta::Lit(lit) = first_arg {
lit.to_token_stream().to_string()
} else {
return syn::Error::new_spanned(first_arg, "Invalid attribute argument").to_compile_error().into();
}
} else {
String::new()
};
let mut func = parse_macro_input!(input as ItemFn);
let allow_unused_attr = syn::parse_quote! { #[allow(unused)] };
func.attrs.push(allow_unused_attr);
let todo_macro = if message.is_empty() {
quote! { todo!() }
} else {
quote! { todo!(#message) }
};
func.block = Box::new(syn::parse_quote! { { #todo_macro } });
TokenStream::from(quote! { #func })
}
#[cfg(feature = "thread")]
#[proc_macro_attribute]
pub fn thread(attr: TokenStream, input: TokenStream) -> TokenStream {
let mut input: syn::ItemFn = syn::parse_macro_input!(input);
let fb = input.block;
let rv = match input.sig.output.clone() {
syn::ReturnType::Default => {
syn::Type::Tuple(syn::parse_quote!{()})
},
syn::ReturnType::Type(_, t) => {
*t
}
};
let rv = quote::quote_spanned! { rv.span() => #rv };
input.block = syn::parse2(quote! {{
::std::thread::spawn(move || {#fb})
}}).unwrap();
input.sig.output = syn::ReturnType::Type(
Token),
Box::new(syn::parse_quote! { ::std::thread::JoinHandle<#rv> }),
);
quote! {#input}.into()
}