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