1 use proc_macro2::TokenStream; 2 use quote::{quote, ToTokens}; 3 4 use crate::{ 5 ast::Data, 6 codegen::{ExtractAttribute, OuterFromImpl, TraitImpl}, 7 util::PathList, 8 }; 9 10 use super::ForwardAttrs; 11 12 pub struct FromAttributesImpl<'a> { 13 pub base: TraitImpl<'a>, 14 pub attr_names: &'a PathList, 15 pub forward_attrs: ForwardAttrs<'a>, 16 } 17 18 impl ToTokens for FromAttributesImpl<'_> { to_tokens(&self, tokens: &mut TokenStream)19 fn to_tokens(&self, tokens: &mut TokenStream) { 20 let ty_ident = self.base.ident; 21 let input = self.param_name(); 22 let post_transform = self.base.post_transform_call(); 23 24 if let Data::Struct(ref data) = self.base.data { 25 if data.is_newtype() { 26 self.wrap( 27 quote! { 28 fn from_attributes(#input: &[::darling::export::syn::Attribute]) -> ::darling::Result<Self> { 29 ::darling::export::Ok( 30 #ty_ident(::darling::FromAttributes::from_attributes(#input)?) 31 ) #post_transform 32 } 33 }, 34 tokens, 35 ); 36 37 return; 38 } 39 } 40 41 let passed_attrs = self.forward_attrs.as_initializer(); 42 let inits = self.base.initializers(); 43 let default = self.base.fallback_decl(); 44 45 let grab_attrs = self.extractor(); 46 47 let declare_errors = self.base.declare_errors(); 48 let require_fields = self.base.require_fields(); 49 let check_errors = self.base.check_errors(); 50 51 self.wrap( 52 quote! { 53 fn from_attributes(#input: &[::darling::export::syn::Attribute]) -> ::darling::Result<Self> { 54 #declare_errors 55 56 #grab_attrs 57 58 #require_fields 59 60 #check_errors 61 62 #default 63 64 ::darling::export::Ok(#ty_ident { 65 #passed_attrs 66 #inits 67 }) #post_transform 68 } 69 }, 70 tokens, 71 ); 72 } 73 } 74 75 impl<'a> ExtractAttribute for FromAttributesImpl<'a> { local_declarations(&self) -> TokenStream76 fn local_declarations(&self) -> TokenStream { 77 self.base.local_declarations() 78 } 79 attr_names(&self) -> &PathList80 fn attr_names(&self) -> &PathList { 81 self.attr_names 82 } 83 forward_attrs(&self) -> &super::ForwardAttrs<'_>84 fn forward_attrs(&self) -> &super::ForwardAttrs<'_> { 85 &self.forward_attrs 86 } 87 param_name(&self) -> TokenStream88 fn param_name(&self) -> TokenStream { 89 quote!(__di) 90 } 91 attrs_accessor(&self) -> TokenStream92 fn attrs_accessor(&self) -> TokenStream { 93 self.param_name() 94 } 95 core_loop(&self) -> TokenStream96 fn core_loop(&self) -> TokenStream { 97 self.base.core_loop() 98 } 99 } 100 101 impl<'a> OuterFromImpl<'a> for FromAttributesImpl<'a> { trait_path(&self) -> syn::Path102 fn trait_path(&self) -> syn::Path { 103 path!(::darling::FromAttributes) 104 } 105 trait_bound(&self) -> syn::Path106 fn trait_bound(&self) -> syn::Path { 107 path!(::darling::FromMeta) 108 } 109 base(&'a self) -> &'a TraitImpl<'a>110 fn base(&'a self) -> &'a TraitImpl<'a> { 111 &self.base 112 } 113 } 114