1 use crate::attr::{self, Attrs}; 2 use crate::generics::ParamsInScope; 3 use proc_macro2::Span; 4 use syn::{ 5 Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Member, Result, 6 Type, 7 }; 8 9 pub enum Input<'a> { 10 Struct(Struct<'a>), 11 Enum(Enum<'a>), 12 } 13 14 pub struct Struct<'a> { 15 pub original: &'a DeriveInput, 16 pub attrs: Attrs<'a>, 17 pub ident: Ident, 18 pub generics: &'a Generics, 19 pub fields: Vec<Field<'a>>, 20 } 21 22 pub struct Enum<'a> { 23 pub original: &'a DeriveInput, 24 pub attrs: Attrs<'a>, 25 pub ident: Ident, 26 pub generics: &'a Generics, 27 pub variants: Vec<Variant<'a>>, 28 } 29 30 pub struct Variant<'a> { 31 pub original: &'a syn::Variant, 32 pub attrs: Attrs<'a>, 33 pub ident: Ident, 34 pub fields: Vec<Field<'a>>, 35 } 36 37 pub struct Field<'a> { 38 pub original: &'a syn::Field, 39 pub attrs: Attrs<'a>, 40 pub member: Member, 41 pub ty: &'a Type, 42 pub contains_generic: bool, 43 } 44 45 impl<'a> Input<'a> { from_syn(node: &'a DeriveInput) -> Result<Self>46 pub fn from_syn(node: &'a DeriveInput) -> Result<Self> { 47 match &node.data { 48 Data::Struct(data) => Struct::from_syn(node, data).map(Input::Struct), 49 Data::Enum(data) => Enum::from_syn(node, data).map(Input::Enum), 50 Data::Union(_) => Err(Error::new_spanned( 51 node, 52 "union as errors are not supported", 53 )), 54 } 55 } 56 } 57 58 impl<'a> Struct<'a> { from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self>59 fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self> { 60 let mut attrs = attr::get(&node.attrs)?; 61 let scope = ParamsInScope::new(&node.generics); 62 let span = attrs.span().unwrap_or_else(Span::call_site); 63 let fields = Field::multiple_from_syn(&data.fields, &scope, span)?; 64 if let Some(display) = &mut attrs.display { 65 display.expand_shorthand(&fields); 66 } 67 Ok(Struct { 68 original: node, 69 attrs, 70 ident: node.ident.clone(), 71 generics: &node.generics, 72 fields, 73 }) 74 } 75 } 76 77 impl<'a> Enum<'a> { from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self>78 fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self> { 79 let attrs = attr::get(&node.attrs)?; 80 let scope = ParamsInScope::new(&node.generics); 81 let span = attrs.span().unwrap_or_else(Span::call_site); 82 let variants = data 83 .variants 84 .iter() 85 .map(|node| { 86 let mut variant = Variant::from_syn(node, &scope, span)?; 87 if let display @ None = &mut variant.attrs.display { 88 *display = attrs.display.clone(); 89 } 90 if let Some(display) = &mut variant.attrs.display { 91 display.expand_shorthand(&variant.fields); 92 } else if variant.attrs.transparent.is_none() { 93 variant.attrs.transparent = attrs.transparent; 94 } 95 Ok(variant) 96 }) 97 .collect::<Result<_>>()?; 98 Ok(Enum { 99 original: node, 100 attrs, 101 ident: node.ident.clone(), 102 generics: &node.generics, 103 variants, 104 }) 105 } 106 } 107 108 impl<'a> Variant<'a> { from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>, span: Span) -> Result<Self>109 fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>, span: Span) -> Result<Self> { 110 let attrs = attr::get(&node.attrs)?; 111 let span = attrs.span().unwrap_or(span); 112 Ok(Variant { 113 original: node, 114 attrs, 115 ident: node.ident.clone(), 116 fields: Field::multiple_from_syn(&node.fields, scope, span)?, 117 }) 118 } 119 } 120 121 impl<'a> Field<'a> { multiple_from_syn( fields: &'a Fields, scope: &ParamsInScope<'a>, span: Span, ) -> Result<Vec<Self>>122 fn multiple_from_syn( 123 fields: &'a Fields, 124 scope: &ParamsInScope<'a>, 125 span: Span, 126 ) -> Result<Vec<Self>> { 127 fields 128 .iter() 129 .enumerate() 130 .map(|(i, field)| Field::from_syn(i, field, scope, span)) 131 .collect() 132 } 133 from_syn( i: usize, node: &'a syn::Field, scope: &ParamsInScope<'a>, span: Span, ) -> Result<Self>134 fn from_syn( 135 i: usize, 136 node: &'a syn::Field, 137 scope: &ParamsInScope<'a>, 138 span: Span, 139 ) -> Result<Self> { 140 Ok(Field { 141 original: node, 142 attrs: attr::get(&node.attrs)?, 143 member: node.ident.clone().map(Member::Named).unwrap_or_else(|| { 144 Member::Unnamed(Index { 145 index: i as u32, 146 span, 147 }) 148 }), 149 ty: &node.ty, 150 contains_generic: scope.intersects(&node.ty), 151 }) 152 } 153 } 154 155 impl Attrs<'_> { span(&self) -> Option<Span>156 pub fn span(&self) -> Option<Span> { 157 if let Some(display) = &self.display { 158 Some(display.fmt.span()) 159 } else if let Some(transparent) = &self.transparent { 160 Some(transparent.span) 161 } else { 162 None 163 } 164 } 165 } 166