mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-02-23 04:52:28 +00:00
remove panics from expand_method
This commit is contained in:
parent
f677789747
commit
381a230b81
1 changed files with 47 additions and 23 deletions
|
@ -3,8 +3,10 @@ use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Ident, TokenStream as TokenStream2};
|
use proc_macro2::{Ident, TokenStream as TokenStream2};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{
|
use syn::{
|
||||||
|
spanned::Spanned,
|
||||||
Attribute,
|
Attribute,
|
||||||
AttributeArgs,
|
AttributeArgs,
|
||||||
|
Error,
|
||||||
FnArg,
|
FnArg,
|
||||||
ItemFn,
|
ItemFn,
|
||||||
Lit,
|
Lit,
|
||||||
|
@ -170,7 +172,7 @@ struct MethodArgument
|
||||||
ty : MethodArgumentType
|
ty : MethodArgumentType
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interpret_arg_ty(index : usize, attrs : &[Attribute], name : &str, ty : Type) -> MethodArgumentType
|
fn interpret_arg_ty(index : usize, attrs : &[Attribute], name : &str, ty : Type) -> Result<MethodArgumentType, Error>
|
||||||
{
|
{
|
||||||
let attr = attrs.into_iter()
|
let attr = attrs.into_iter()
|
||||||
.filter(|arg| arg.path.segments.iter().filter(|path| &path.ident.to_string() == "rest_arg").nth(0).is_some())
|
.filter(|arg| arg.path.segments.iter().filter(|path| &path.ident.to_string() == "rest_arg").nth(0).is_some())
|
||||||
|
@ -179,39 +181,39 @@ fn interpret_arg_ty(index : usize, attrs : &[Attribute], name : &str, ty : Type)
|
||||||
|
|
||||||
if cfg!(feature = "auth") && (attr.as_deref() == Some("auth") || (attr.is_none() && name == "auth"))
|
if cfg!(feature = "auth") && (attr.as_deref() == Some("auth") || (attr.is_none() && name == "auth"))
|
||||||
{
|
{
|
||||||
return match ty {
|
return Ok(match ty {
|
||||||
Type::Reference(ty) => MethodArgumentType::AuthStatusRef(*ty.elem),
|
Type::Reference(ty) => MethodArgumentType::AuthStatusRef(*ty.elem),
|
||||||
ty => MethodArgumentType::AuthStatus(ty)
|
ty => MethodArgumentType::AuthStatus(ty)
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg!(feature = "database") && (attr.as_deref() == Some("connection") || attr.as_deref() == Some("conn") || (attr.is_none() && name == "conn"))
|
if cfg!(feature = "database") && (attr.as_deref() == Some("connection") || attr.as_deref() == Some("conn") || (attr.is_none() && name == "conn"))
|
||||||
{
|
{
|
||||||
return MethodArgumentType::DatabaseConnection(match ty {
|
return Ok(MethodArgumentType::DatabaseConnection(match ty {
|
||||||
Type::Reference(ty) => *ty.elem,
|
Type::Reference(ty) => *ty.elem,
|
||||||
ty => ty
|
ty => ty
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == 0
|
if index == 0
|
||||||
{
|
{
|
||||||
return match ty {
|
return match ty {
|
||||||
Type::Reference(ty) => if ty.mutability.is_none() { MethodArgumentType::StateRef } else { MethodArgumentType::StateMutRef },
|
Type::Reference(ty) => Ok(if ty.mutability.is_none() { MethodArgumentType::StateRef } else { MethodArgumentType::StateMutRef }),
|
||||||
_ => panic!("The first argument, unless some feature is used, has to be a (mutable) reference to gotham::state::State")
|
_ => Err(Error::new(ty.span(), "The first argument, unless some feature is used, has to be a (mutable) reference to gotham::state::State"))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodArgumentType::MethodArg(ty)
|
Ok(MethodArgumentType::MethodArg(ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interpret_arg(index : usize, arg : &PatType) -> MethodArgument
|
fn interpret_arg(index : usize, arg : &PatType) -> Result<MethodArgument, Error>
|
||||||
{
|
{
|
||||||
let pat = &arg.pat;
|
let pat = &arg.pat;
|
||||||
let ident = format_ident!("arg{}", index);
|
let ident = format_ident!("arg{}", index);
|
||||||
let orig_name = quote!(#pat);
|
let orig_name = quote!(#pat);
|
||||||
let ty = interpret_arg_ty(index, &arg.attrs, &orig_name.to_string(), *arg.ty.clone());
|
let ty = interpret_arg_ty(index, &arg.attrs, &orig_name.to_string(), *arg.ty.clone())?;
|
||||||
|
|
||||||
MethodArgument { ident, ty }
|
Ok(MethodArgument { ident, ty })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "openapi")]
|
#[cfg(feature = "openapi")]
|
||||||
|
@ -248,19 +250,20 @@ fn expand_operation_id(_ : &AttributeArgs) -> TokenStream2
|
||||||
quote!()
|
quote!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -> TokenStream
|
fn expand(method : Method, attrs : TokenStream, item : TokenStream) -> Result<TokenStream2, Error>
|
||||||
{
|
{
|
||||||
let krate = super::krate();
|
let krate = super::krate();
|
||||||
|
|
||||||
// parse attributes
|
// parse attributes
|
||||||
let mut method_attrs = parse_macro_input!(attrs as AttributeArgs);
|
let mut method_attrs = parse_macro_input::parse::<AttributeArgs>(attrs)?;
|
||||||
let resource_path = match method_attrs.remove(0) {
|
let resource_path = match method_attrs.remove(0) {
|
||||||
NestedMeta::Meta(Meta::Path(path)) => path,
|
NestedMeta::Meta(Meta::Path(path)) => path,
|
||||||
_ => panic!("Expected resource name for rest macro")
|
p => return Err(Error::new(p.span(), "Expected name of the Resource struct this method belongs to"))
|
||||||
};
|
};
|
||||||
let resource_name = resource_path.segments.last().expect("Resource name must not be empty").ident.to_string();
|
let resource_name = resource_path.segments.last().map(|s| s.ident.to_string())
|
||||||
|
.ok_or_else(|| Error::new(resource_path.span(), "Resource name must not be empty"))?;
|
||||||
|
|
||||||
let fun = parse_macro_input!(item as ItemFn);
|
let fun = parse_macro_input::parse::<ItemFn>(item)?;
|
||||||
let fun_ident = &fun.sig.ident;
|
let fun_ident = &fun.sig.ident;
|
||||||
let fun_vis = &fun.vis;
|
let fun_vis = &fun.vis;
|
||||||
|
|
||||||
|
@ -282,10 +285,25 @@ pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -
|
||||||
let auth_ident = format_ident!("auth");
|
let auth_ident = format_ident!("auth");
|
||||||
|
|
||||||
// extract arguments into pattern, ident and type
|
// extract arguments into pattern, ident and type
|
||||||
let args : Vec<MethodArgument> = fun.sig.inputs.iter().enumerate().map(|(i, arg)| match arg {
|
let mut args : Vec<MethodArgument> = Vec::new();
|
||||||
FnArg::Typed(arg) => interpret_arg(i, arg),
|
let mut errors : Vec<Error> = Vec::new();
|
||||||
FnArg::Receiver(_) => panic!("didn't expect self parameter")
|
for (i, arg) in fun.sig.inputs.iter().enumerate()
|
||||||
}).collect();
|
{
|
||||||
|
let a = match arg {
|
||||||
|
FnArg::Typed(arg) => interpret_arg(i, arg),
|
||||||
|
FnArg::Receiver(_) => Err(Error::new(arg.span(), "Didn't expect self parameter"))
|
||||||
|
};
|
||||||
|
match a {
|
||||||
|
Ok(a) => args.push(a),
|
||||||
|
Err(e) => errors.push(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !errors.is_empty()
|
||||||
|
{
|
||||||
|
let mut iter = errors.into_iter();
|
||||||
|
let first = iter.nth(0).unwrap();
|
||||||
|
return Err(iter.fold(first, |mut e0, e1| { e0.combine(e1); e0 }));
|
||||||
|
}
|
||||||
|
|
||||||
// extract the generic parameters to use
|
// extract the generic parameters to use
|
||||||
let generics : Vec<TokenStream2> = args.iter()
|
let generics : Vec<TokenStream2> = args.iter()
|
||||||
|
@ -355,7 +373,7 @@ pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -
|
||||||
let operation_id = expand_operation_id(&method_attrs);
|
let operation_id = expand_operation_id(&method_attrs);
|
||||||
|
|
||||||
// put everything together
|
// put everything together
|
||||||
let output = quote! {
|
Ok(quote! {
|
||||||
#fun
|
#fun
|
||||||
|
|
||||||
#fun_vis mod #mod_ident
|
#fun_vis mod #mod_ident
|
||||||
|
@ -392,6 +410,12 @@ pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
})
|
||||||
output.into()
|
}
|
||||||
|
|
||||||
|
pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -> TokenStream
|
||||||
|
{
|
||||||
|
expand(method, attrs, item)
|
||||||
|
.unwrap_or_else(|err| err.to_compile_error())
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue