1
0
Fork 0
mirror of https://gitlab.com/msrd0/gotham-restful.git synced 2025-02-22 20:52:27 +00:00

Merge branch 'keep-fn-on-method-handlers' into 'master'

Keep fn on method handlers

Closes #8

See merge request msrd0/gotham-restful!3
This commit is contained in:
msrd0 2019-10-27 20:44:23 +00:00
commit 6b44c40141
3 changed files with 24 additions and 19 deletions

View file

@ -19,6 +19,7 @@ gitlab = { repository = "msrd0/gotham-restful", branch = "master" }
codecov = { repository = "msrd0/gotham-restful", branch = "master", service = "gitlab" }
[dependencies]
heck = "0.3.1"
proc-macro2 = "1"
quote = "1"
syn = { version = "1", features = ["extra-traits", "full"] }

View file

@ -1,3 +1,4 @@
use heck::SnakeCase;
use proc_macro::TokenStream;
use proc_macro2::{Ident, TokenStream as TokenStream2};
use quote::{format_ident, quote};
@ -76,19 +77,25 @@ impl Method
format_ident!("{}", name)
}
pub fn setup_ident(&self) -> Ident
pub fn setup_ident(&self, resource : String) -> Ident
{
format_ident!("{}_setup_impl", self.fn_ident())
format_ident!("{}_{}_setup_impl", resource.to_snake_case(), self.fn_ident())
}
}
pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -> TokenStream
{
let krate = super::krate();
let ident = parse_macro_input!(attrs as Ident);
let resource_ident = parse_macro_input!(attrs as Ident);
let fun = parse_macro_input!(item as ItemFn);
let fun_ident = &fun.sig.ident;
let fun_vis = &fun.vis;
let (ret, is_no_content) = match fun.sig.output {
let trait_ident = method.trait_ident();
let method_ident = method.fn_ident();
let setup_ident = method.setup_ident(resource_ident.to_string());
let (ret, is_no_content) = match &fun.sig.output {
ReturnType::Default => (quote!(#krate::NoContent), true),
ReturnType::Type(_, ty) => (quote!(#ty), false)
};
@ -102,29 +109,26 @@ pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -
}).collect();
let mut generics : Vec<TokenStream2> = args.iter().skip(1).map(|(_, ty)| quote!(#ty)).collect();
generics.push(quote!(#ret));
let args : Vec<TokenStream2> = args.into_iter().map(|(pat, ty)| quote!(#pat : #ty)).collect();
let block = fun.block.stmts;
let ret_stmt = if is_no_content { Some(quote!(Default::default())) } else { None };
let trait_ident = method.trait_ident();
let fn_ident = method.fn_ident();
let setup_ident = method.setup_ident();
let args_def : Vec<TokenStream2> = args.iter().map(|(pat, ty)| quote!(#pat : #ty)).collect();
let args_pass : Vec<TokenStream2> = args.iter().map(|(pat, _)| quote!(#pat)).collect();
let block = if is_no_content { quote!(#fun_ident(#(#args_pass),*); Default::default()) } else { quote!(#fun_ident(#(#args_pass),*)) };
let output = quote! {
impl #krate::#trait_ident<#(#generics),*> for #ident
where #ident : #krate::Resource
#fun
impl #krate::#trait_ident<#(#generics),*> for #resource_ident
where #resource_ident : #krate::Resource
{
fn #fn_ident(#(#args),*) -> #ret
fn #method_ident(#(#args_def),*) -> #ret
{
#(#block)*
#ret_stmt
#block
}
}
#[deny(dead_code)]
fn #setup_ident<D : #krate::DrawResourceRoutes>(route : &mut D)
#fun_vis fn #setup_ident<D : #krate::DrawResourceRoutes>(route : &mut D)
{
route.#fn_ident::<#ident, #(#generics),*>();
route.#method_ident::<#resource_ident, #(#generics),*>();
}
};
output.into()

View file

@ -39,7 +39,7 @@ pub fn expand_resource(tokens : TokenStream) -> TokenStream
m.0.into_iter()
}).map(|method| {
let method = Method::from_str(&method.to_string()).expect("unknown method");
let ident = method.setup_ident();
let ident = method.setup_ident(ident.to_string());
quote!(#ident(&mut route);)
}).collect();