use proc_macro2::TokenStream as TokenStream2;
use syn::{parse2, spanned::Spanned, Error, ItemFn, Result, Path};
use crate::util;
pub fn after(input: TokenStream2) -> Result<TokenStream2> {
let fun = parse2::<ItemFn>(input)?;
let ItemFn {
attrs,
vis,
mut sig,
block,
} = fun;
match sig.inputs.len() {
c if c != 3 => {
return Err(Error::new(sig.inputs.span(), "Expected three arguments"));
}
_ => (),
};
let ident = sig.ident.clone();
let fn_ident = quote::format_ident!("_{}", &ident);
sig.ident = fn_ident.clone();
util::check_return_type(&sig.output, quote::quote!(()))?;
let result_type = util::get_path(&util::get_pat(sig.inputs.iter().nth(2).unwrap())?.ty, false)?;
let returnable = util::get_returnable_trait();
let optional = parse2::<Path>(quote::quote!(::zephyrus::extract::Optional))?;
let ty = util::get_context_type(&sig, true)?;
let hook = util::get_hook_macro();
let path = quote::quote!(::zephyrus::hook::AfterHook);
Ok(quote::quote! {
pub fn #ident()
-> #path<
#ty,
<<#result_type as #optional>::Inner as #returnable>::Ok,
<<#result_type as #optional>::Inner as #returnable>::Err
> {
#path(#fn_ident)
}
#[#hook]
#(#attrs)*
#vis #sig #block
})
}