• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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