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