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