1 use proc_macro2::TokenStream; 2 use quote::ToTokens; 3 use syn::{self, Ident}; 4 5 use ast::Data; 6 use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl}; 7 use options::{ForwardAttrs, Shape}; 8 use util::PathList; 9 10 pub struct FromDeriveInputImpl<'a> { 11 pub ident: Option<&'a Ident>, 12 pub generics: Option<&'a Ident>, 13 pub vis: Option<&'a Ident>, 14 pub attrs: Option<&'a Ident>, 15 pub data: Option<&'a Ident>, 16 pub base: TraitImpl<'a>, 17 pub attr_names: &'a PathList, 18 pub forward_attrs: Option<&'a ForwardAttrs>, 19 pub from_ident: bool, 20 pub supports: Option<&'a Shape>, 21 } 22 23 impl<'a> ToTokens for FromDeriveInputImpl<'a> { to_tokens(&self, tokens: &mut TokenStream)24 fn to_tokens(&self, tokens: &mut TokenStream) { 25 let ty_ident = self.base.ident; 26 let input = self.param_name(); 27 let map = self.base.map_fn(); 28 29 if let Data::Struct(ref data) = self.base.data { 30 if data.is_newtype() { 31 self.wrap( 32 quote!{ 33 fn from_derive_input(#input: &::syn::DeriveInput) -> ::darling::Result<Self> { 34 ::darling::export::Ok( 35 #ty_ident(::darling::FromDeriveInput::from_derive_input(#input)?) 36 ) #map 37 } 38 }, 39 tokens, 40 ); 41 42 return; 43 } 44 } 45 46 let passed_ident = self.ident 47 .as_ref() 48 .map(|i| quote!(#i: #input.ident.clone(),)); 49 let passed_vis = self.vis.as_ref().map(|i| quote!(#i: #input.vis.clone(),)); 50 let passed_generics = self.generics 51 .as_ref() 52 .map(|i| quote!(#i: ::darling::FromGenerics::from_generics(&#input.generics)?,)); 53 let passed_attrs = self.attrs.as_ref().map(|i| quote!(#i: __fwd_attrs,)); 54 let passed_body = self.data 55 .as_ref() 56 .map(|i| quote!(#i: ::darling::ast::Data::try_from(&#input.data)?,)); 57 58 let supports = self.supports.map(|i| { 59 quote!{ 60 #i 61 __validate_body(&#input.data)?; 62 } 63 }); 64 65 let inits = self.base.initializers(); 66 let default = if self.from_ident { 67 quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());) 68 } else { 69 self.base.fallback_decl() 70 }; 71 72 let grab_attrs = self.extractor(); 73 74 let declare_errors = self.base.declare_errors(); 75 let require_fields = self.base.require_fields(); 76 let check_errors = self.base.check_errors(); 77 78 self.wrap( 79 quote! { 80 fn from_derive_input(#input: &::syn::DeriveInput) -> ::darling::Result<Self> { 81 #declare_errors 82 83 #grab_attrs 84 85 #supports 86 87 #require_fields 88 89 #check_errors 90 91 #default 92 93 ::darling::export::Ok(#ty_ident { 94 #passed_ident 95 #passed_generics 96 #passed_vis 97 #passed_attrs 98 #passed_body 99 #inits 100 }) #map 101 } 102 }, 103 tokens, 104 ); 105 } 106 } 107 108 impl<'a> ExtractAttribute for FromDeriveInputImpl<'a> { attr_names(&self) -> &PathList109 fn attr_names(&self) -> &PathList { 110 &self.attr_names 111 } 112 forwarded_attrs(&self) -> Option<&ForwardAttrs>113 fn forwarded_attrs(&self) -> Option<&ForwardAttrs> { 114 self.forward_attrs 115 } 116 param_name(&self) -> TokenStream117 fn param_name(&self) -> TokenStream { 118 quote!(__di) 119 } 120 core_loop(&self) -> TokenStream121 fn core_loop(&self) -> TokenStream { 122 self.base.core_loop() 123 } 124 local_declarations(&self) -> TokenStream125 fn local_declarations(&self) -> TokenStream { 126 self.base.local_declarations() 127 } 128 immutable_declarations(&self) -> TokenStream129 fn immutable_declarations(&self) -> TokenStream { 130 self.base.immutable_declarations() 131 } 132 } 133 134 impl<'a> OuterFromImpl<'a> for FromDeriveInputImpl<'a> { trait_path(&self) -> syn::Path135 fn trait_path(&self) -> syn::Path { 136 path!(::darling::FromDeriveInput) 137 } 138 trait_bound(&self) -> syn::Path139 fn trait_bound(&self) -> syn::Path { 140 path!(::darling::FromMeta) 141 } 142 base(&'a self) -> &'a TraitImpl<'a>143 fn base(&'a self) -> &'a TraitImpl<'a> { 144 &self.base 145 } 146 } 147