|
| 1 | +use proc_macro2::Ident; |
| 2 | +use quote::{format_ident,ToTokens}; |
| 3 | +use syn::{ |
| 4 | + parse::Parser, |
| 5 | + punctuated::Punctuated, |
| 6 | + visit::{self,Visit}, |
| 7 | +ImplItemFn,ReturnType,Token,Visibility, |
| 8 | +}; |
| 9 | + |
| 10 | +usecrate::types::{GetOutputType,GetSupportedType,OutputType,SupportedType}; |
| 11 | + |
| 12 | +pubstructAttributeArgs{ |
| 13 | +pubargs:Vec<String>, |
| 14 | +} |
| 15 | + |
| 16 | +implAttributeArgs{ |
| 17 | +pubfnnew(attributes: proc_macro::TokenStream) ->Self{ |
| 18 | +let attribute_parser =Punctuated::<Ident,Token![,]>::parse_terminated; |
| 19 | +let parsed_attributes = attribute_parser |
| 20 | +.parse(attributes) |
| 21 | +.expect("Error parsing attributes for custom_methods macro"); |
| 22 | +let args:Vec<String> = parsed_attributes |
| 23 | +.into_pairs() |
| 24 | +.map(|p| p.value().to_string()) |
| 25 | +.collect(); |
| 26 | +Self{ args} |
| 27 | +} |
| 28 | +} |
| 29 | + |
| 30 | +#[derive(Debug)] |
| 31 | +pubstructGetImplMethod{ |
| 32 | +pubexists:bool, |
| 33 | +pubmethod_ident:Ident, |
| 34 | +pubis_async:bool, |
| 35 | +pubmethod_arguments:Vec<(String,SupportedType)>, |
| 36 | +pubreceiver:Option<proc_macro2::TokenStream>, |
| 37 | +puboutput_type:OutputType, |
| 38 | +} |
| 39 | + |
| 40 | +implDefaultforGetImplMethod{ |
| 41 | +fndefault() ->Self{ |
| 42 | +GetImplMethod{ |
| 43 | +exists:false, |
| 44 | +method_ident:format_ident!("nothing"), |
| 45 | +is_async:false, |
| 46 | +method_arguments:Vec::new(), |
| 47 | +receiver:None, |
| 48 | +output_type:OutputType::Default, |
| 49 | +} |
| 50 | +} |
| 51 | +} |
| 52 | + |
| 53 | +impl<'ast>Visit<'ast>forGetImplMethod{ |
| 54 | +fnvisit_impl_item_fn(&mutself,i:&'astImplItemFn){ |
| 55 | +ifletVisibility::Public(_p) = i.vis{ |
| 56 | +self.exists =true; |
| 57 | + visit::visit_impl_item_fn(self, i); |
| 58 | +} |
| 59 | +} |
| 60 | + |
| 61 | +fnvisit_signature(&mutself,i:&'ast syn::Signature){ |
| 62 | +self.method_ident = i.ident.clone(); |
| 63 | +self.is_async = i.asyncness.is_some(); |
| 64 | +self.output_type =match&i.output{ |
| 65 | +ReturnType::Default =>OutputType::Default, |
| 66 | +ReturnType::Type(_ra, ty) =>{ |
| 67 | +letmut get_output_type =GetOutputType::default(); |
| 68 | + get_output_type.visit_type(ty); |
| 69 | + get_output_type.output |
| 70 | +} |
| 71 | +}; |
| 72 | + visit::visit_signature(self, i); |
| 73 | +} |
| 74 | + |
| 75 | +fnvisit_receiver(&mutself,i:&'ast syn::Receiver){ |
| 76 | +self.receiver =Some(i.to_token_stream()); |
| 77 | + visit::visit_receiver(self, i); |
| 78 | +} |
| 79 | + |
| 80 | +fnvisit_pat_type(&mutself,i:&'ast syn::PatType){ |
| 81 | +let pat = i.pat.to_token_stream().to_string(); |
| 82 | +letmut ty =GetSupportedType::default(); |
| 83 | + ty.visit_type(&i.ty); |
| 84 | +let ty = ty.ty.expect("No type found"); |
| 85 | +self.method_arguments.push((pat, ty)); |
| 86 | + visit::visit_pat_type(self, i); |
| 87 | +} |
| 88 | + |
| 89 | +fnvisit_expr_return(&mutself,i:&'ast syn::ExprReturn){ |
| 90 | + visit::visit_expr_return(self, i); |
| 91 | +} |
| 92 | + |
| 93 | +// We don't want to visit any of the statments in the methods |
| 94 | +fnvisit_block(&mutself,_i:&'ast syn::Block){} |
| 95 | +} |