1 use ident_case::RenameRule;
2 
3 use crate::ast::{Data, Fields, Style};
4 use crate::codegen;
5 use crate::codegen::PostfixTransform;
6 use crate::error::Accumulator;
7 use crate::options::{DefaultExpression, InputField, InputVariant, ParseAttribute, ParseData};
8 use crate::{Error, FromMeta, Result};
9 
10 /// A struct or enum which should have `FromMeta` or `FromDeriveInput` implementations
11 /// generated.
12 #[derive(Debug, Clone)]
13 pub struct Core {
14     /// The type identifier.
15     pub ident: syn::Ident,
16 
17     /// The type's generics. If the type does not use any generics, this will
18     /// be an empty instance.
19     pub generics: syn::Generics,
20 
21     /// Controls whether missing properties should cause errors or should be filled by
22     /// the result of a function call. This can be overridden at the field level.
23     pub default: Option<DefaultExpression>,
24 
25     /// The rule that should be used to rename all fields/variants in the container.
26     pub rename_rule: RenameRule,
27 
28     /// A transform which will be called on `darling::Result<Self>`. It must either be
29     /// an `FnOnce(T) -> T` when `map` is used, or `FnOnce(T) -> darling::Result<T>` when
30     /// `and_then` is used.
31     ///
32     /// `map` and `and_then` are mutually-exclusive to avoid confusion about the order in
33     /// which the two are applied.
34     pub post_transform: Option<codegen::PostfixTransform>,
35 
36     /// The body of the _deriving_ type.
37     pub data: Data<InputVariant, InputField>,
38 
39     /// The custom bound to apply to the generated impl
40     pub bound: Option<Vec<syn::WherePredicate>>,
41 
42     /// Whether or not unknown fields should produce an error at compilation time.
43     pub allow_unknown_fields: Option<bool>,
44 }
45 
46 impl Core {
47     /// Partially initializes `Core` by reading the identity, generics, and body shape.
start(di: &syn::DeriveInput) -> Result<Self>48     pub fn start(di: &syn::DeriveInput) -> Result<Self> {
49         Ok(Core {
50             ident: di.ident.clone(),
51             generics: di.generics.clone(),
52             data: Data::try_empty_from(&di.data)?,
53             default: Default::default(),
54             // See https://github.com/TedDriggs/darling/issues/10: We default to snake_case
55             // for enums to help authors produce more idiomatic APIs.
56             rename_rule: if let syn::Data::Enum(_) = di.data {
57                 RenameRule::SnakeCase
58             } else {
59                 Default::default()
60             },
61             post_transform: Default::default(),
62             bound: Default::default(),
63             allow_unknown_fields: Default::default(),
64         })
65     }
66 
as_codegen_default(&self) -> Option<codegen::DefaultExpression<'_>>67     fn as_codegen_default(&self) -> Option<codegen::DefaultExpression<'_>> {
68         self.default.as_ref().map(|expr| match *expr {
69             DefaultExpression::Explicit(ref path) => codegen::DefaultExpression::Explicit(path),
70             DefaultExpression::Inherit => {
71                 // It should be impossible for any input to get here,
72                 // so panic rather than returning an error or pretending
73                 // everything is fine.
74                 panic!("DefaultExpression::Inherit is not valid at container level")
75             }
76             DefaultExpression::Trait { span } => codegen::DefaultExpression::Trait { span },
77         })
78     }
79 }
80 
81 impl ParseAttribute for Core {
parse_nested(&mut self, mi: &syn::Meta) -> Result<()>82     fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()> {
83         let path = mi.path();
84 
85         if path.is_ident("default") {
86             if self.default.is_some() {
87                 return Err(Error::duplicate_field("default").with_span(mi));
88             }
89 
90             self.default = FromMeta::from_meta(mi)?;
91         } else if path.is_ident("rename_all") {
92             // WARNING: This may have been set based on body shape previously,
93             // so an overwrite may be permissible.
94             self.rename_rule = FromMeta::from_meta(mi)?;
95         } else if path.is_ident("map") || path.is_ident("and_then") {
96             // This unwrap is safe because we just called is_ident above
97             let transformer = path.get_ident().unwrap().clone();
98 
99             if let Some(post_transform) = &self.post_transform {
100                 if transformer == post_transform.transformer {
101                     return Err(Error::duplicate_field(&transformer.to_string()).with_span(mi));
102                 } else {
103                     return Err(Error::custom(format!(
104                         "Options `{}` and `{}` are mutually exclusive",
105                         transformer, post_transform.transformer
106                     ))
107                     .with_span(mi));
108                 }
109             }
110 
111             self.post_transform =
112                 Some(PostfixTransform::new(transformer, FromMeta::from_meta(mi)?));
113         } else if path.is_ident("bound") {
114             self.bound = FromMeta::from_meta(mi)?;
115         } else if path.is_ident("allow_unknown_fields") {
116             if self.allow_unknown_fields.is_some() {
117                 return Err(Error::duplicate_field("allow_unknown_fields").with_span(mi));
118             }
119 
120             self.allow_unknown_fields = FromMeta::from_meta(mi)?;
121         } else {
122             return Err(Error::unknown_field_path(path).with_span(mi));
123         }
124 
125         Ok(())
126     }
127 }
128 
129 impl ParseData for Core {
parse_variant(&mut self, variant: &syn::Variant) -> Result<()>130     fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
131         let v = InputVariant::from_variant(variant, Some(self))?;
132 
133         match self.data {
134             Data::Enum(ref mut variants) => {
135                 variants.push(v);
136                 Ok(())
137             }
138             Data::Struct(_) => panic!("Core::parse_variant should never be called for a struct"),
139         }
140     }
141 
parse_field(&mut self, field: &syn::Field) -> Result<()>142     fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
143         let f = InputField::from_field(field, Some(self))?;
144 
145         match self.data {
146             Data::Struct(Fields {
147                 style: Style::Unit, ..
148             }) => panic!("Core::parse_field should not be called on unit"),
149             Data::Struct(Fields { ref mut fields, .. }) => {
150                 fields.push(f);
151                 Ok(())
152             }
153             Data::Enum(_) => panic!("Core::parse_field should never be called for an enum"),
154         }
155     }
156 
validate_body(&self, errors: &mut Accumulator)157     fn validate_body(&self, errors: &mut Accumulator) {
158         if let Data::Struct(fields) = &self.data {
159             let flatten_targets: Vec<_> = fields
160                 .iter()
161                 .filter_map(|field| {
162                     if field.flatten.is_present() {
163                         Some(field.flatten)
164                     } else {
165                         None
166                     }
167                 })
168                 .collect();
169 
170             if flatten_targets.len() > 1 {
171                 for flatten in flatten_targets {
172                     errors.push(
173                         Error::custom("`#[darling(flatten)]` can only be applied to one field")
174                             .with_span(&flatten.span()),
175                     );
176                 }
177             }
178         }
179     }
180 }
181 
182 impl<'a> From<&'a Core> for codegen::TraitImpl<'a> {
from(v: &'a Core) -> Self183     fn from(v: &'a Core) -> Self {
184         codegen::TraitImpl {
185             ident: &v.ident,
186             generics: &v.generics,
187             data: v
188                 .data
189                 .as_ref()
190                 .map_struct_fields(InputField::as_codegen_field)
191                 .map_enum_variants(|variant| variant.as_codegen_variant(&v.ident)),
192             default: v.as_codegen_default(),
193             post_transform: v.post_transform.as_ref(),
194             allow_unknown_fields: v.allow_unknown_fields.unwrap_or_default(),
195         }
196     }
197 }
198