1 use proc_macro2::TokenStream; 2 use quote::ToTokens; 3 4 use crate::ast::Data; 5 use crate::codegen::FromMetaImpl; 6 use crate::error::Accumulator; 7 use crate::options::{Core, ParseAttribute, ParseData}; 8 use crate::{Error, Result}; 9 10 pub struct FromMetaOptions { 11 base: Core, 12 } 13 14 impl FromMetaOptions { new(di: &syn::DeriveInput) -> Result<Self>15 pub fn new(di: &syn::DeriveInput) -> Result<Self> { 16 (FromMetaOptions { 17 base: Core::start(di)?, 18 }) 19 .parse_attributes(&di.attrs)? 20 .parse_body(&di.data) 21 } 22 } 23 24 impl ParseAttribute for FromMetaOptions { parse_nested(&mut self, mi: &syn::Meta) -> Result<()>25 fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> { 26 self.base.parse_nested(mi) 27 } 28 } 29 30 impl ParseData for FromMetaOptions { parse_variant(&mut self, variant: &syn::Variant) -> Result<()>31 fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> { 32 self.base.parse_variant(variant) 33 } 34 parse_field(&mut self, field: &syn::Field) -> Result<()>35 fn parse_field(&mut self, field: &syn::Field) -> Result<()> { 36 self.base.parse_field(field) 37 } 38 validate_body(&self, errors: &mut Accumulator)39 fn validate_body(&self, errors: &mut Accumulator) { 40 self.base.validate_body(errors); 41 42 if let Data::Enum(ref data) = self.base.data { 43 // Adds errors for duplicate `#[darling(word)]` annotations across all variants. 44 let word_variants: Vec<_> = data 45 .iter() 46 .filter_map(|variant| variant.word.as_ref()) 47 .collect(); 48 if word_variants.len() > 1 { 49 for word in word_variants { 50 errors.push( 51 Error::custom("`#[darling(word)]` can only be applied to one variant") 52 .with_span(&word.span()), 53 ); 54 } 55 } 56 } 57 } 58 } 59 60 impl<'a> From<&'a FromMetaOptions> for FromMetaImpl<'a> { from(v: &'a FromMetaOptions) -> Self61 fn from(v: &'a FromMetaOptions) -> Self { 62 FromMetaImpl { 63 base: (&v.base).into(), 64 } 65 } 66 } 67 68 impl ToTokens for FromMetaOptions { to_tokens(&self, tokens: &mut TokenStream)69 fn to_tokens(&self, tokens: &mut TokenStream) { 70 FromMetaImpl::from(self).to_tokens(tokens) 71 } 72 } 73