1 use crate::attr::{self, Attrs}; 2 use crate::generics::ParamsInScope; 3 use crate::unraw::{IdentUnraw, MemberUnraw}; 4 use proc_macro2::Span; 5 use std::fmt::{self, Display}; 6 use syn::{ 7 Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Result, Type, 8 }; 9 10 pub enum Input<'a> { 11 Struct(Struct<'a>), 12 Enum(Enum<'a>), 13 } 14 15 pub struct Struct<'a> { 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 attrs: Attrs<'a>, 24 pub ident: Ident, 25 pub generics: &'a Generics, 26 pub variants: Vec<Variant<'a>>, 27 } 28 29 pub struct Variant<'a> { 30 pub original: &'a syn::Variant, 31 pub attrs: Attrs<'a>, 32 pub ident: Ident, 33 pub fields: Vec<Field<'a>>, 34 } 35 36 pub struct Field<'a> { 37 pub original: &'a syn::Field, 38 pub attrs: Attrs<'a>, 39 pub member: MemberUnraw, 40 pub ty: &'a Type, 41 pub contains_generic: bool, 42 } 43 44 #[derive(Copy, Clone)] 45 pub enum ContainerKind { 46 Struct, 47 TupleStruct, 48 UnitStruct, 49 StructVariant, 50 TupleVariant, 51 UnitVariant, 52 } 53 54 impl<'a> Input<'a> { from_syn(node: &'a DeriveInput) -> Result<Self>55 pub fn from_syn(node: &'a DeriveInput) -> Result<Self> { 56 match &node.data { 57 Data::Struct(data) => Struct::from_syn(node, data).map(Input::Struct), 58 Data::Enum(data) => Enum::from_syn(node, data).map(Input::Enum), 59 Data::Union(_) => Err(Error::new_spanned( 60 node, 61 "union as errors are not supported", 62 )), 63 } 64 } 65 } 66 67 impl<'a> Struct<'a> { from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self>68 fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self> { 69 let mut attrs = attr::get(&node.attrs)?; 70 let scope = ParamsInScope::new(&node.generics); 71 let fields = Field::multiple_from_syn(&data.fields, &scope)?; 72 if let Some(display) = &mut attrs.display { 73 let container = ContainerKind::from_struct(data); 74 display.expand_shorthand(&fields, container)?; 75 } 76 Ok(Struct { 77 attrs, 78 ident: node.ident.clone(), 79 generics: &node.generics, 80 fields, 81 }) 82 } 83 } 84 85 impl<'a> Enum<'a> { from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self>86 fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self> { 87 let attrs = attr::get(&node.attrs)?; 88 let scope = ParamsInScope::new(&node.generics); 89 let variants = data 90 .variants 91 .iter() 92 .map(|node| { 93 let mut variant = Variant::from_syn(node, &scope)?; 94 if variant.attrs.display.is_none() 95 && variant.attrs.transparent.is_none() 96 && variant.attrs.fmt.is_none() 97 { 98 variant.attrs.display.clone_from(&attrs.display); 99 variant.attrs.transparent = attrs.transparent; 100 variant.attrs.fmt.clone_from(&attrs.fmt); 101 } 102 if let Some(display) = &mut variant.attrs.display { 103 let container = ContainerKind::from_variant(node); 104 display.expand_shorthand(&variant.fields, container)?; 105 } 106 Ok(variant) 107 }) 108 .collect::<Result<_>>()?; 109 Ok(Enum { 110 attrs, 111 ident: node.ident.clone(), 112 generics: &node.generics, 113 variants, 114 }) 115 } 116 } 117 118 impl<'a> Variant<'a> { from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>) -> Result<Self>119 fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>) -> Result<Self> { 120 let attrs = attr::get(&node.attrs)?; 121 Ok(Variant { 122 original: node, 123 attrs, 124 ident: node.ident.clone(), 125 fields: Field::multiple_from_syn(&node.fields, scope)?, 126 }) 127 } 128 } 129 130 impl<'a> Field<'a> { multiple_from_syn(fields: &'a Fields, scope: &ParamsInScope<'a>) -> Result<Vec<Self>>131 fn multiple_from_syn(fields: &'a Fields, scope: &ParamsInScope<'a>) -> Result<Vec<Self>> { 132 fields 133 .iter() 134 .enumerate() 135 .map(|(i, field)| Field::from_syn(i, field, scope)) 136 .collect() 137 } 138 from_syn(i: usize, node: &'a syn::Field, scope: &ParamsInScope<'a>) -> Result<Self>139 fn from_syn(i: usize, node: &'a syn::Field, scope: &ParamsInScope<'a>) -> Result<Self> { 140 Ok(Field { 141 original: node, 142 attrs: attr::get(&node.attrs)?, 143 member: match &node.ident { 144 Some(name) => MemberUnraw::Named(IdentUnraw::new(name.clone())), 145 None => MemberUnraw::Unnamed(Index { 146 index: i as u32, 147 span: Span::call_site(), 148 }), 149 }, 150 ty: &node.ty, 151 contains_generic: scope.intersects(&node.ty), 152 }) 153 } 154 } 155 156 impl ContainerKind { from_struct(node: &DataStruct) -> Self157 fn from_struct(node: &DataStruct) -> Self { 158 match node.fields { 159 Fields::Named(_) => ContainerKind::Struct, 160 Fields::Unnamed(_) => ContainerKind::TupleStruct, 161 Fields::Unit => ContainerKind::UnitStruct, 162 } 163 } 164 from_variant(node: &syn::Variant) -> Self165 fn from_variant(node: &syn::Variant) -> Self { 166 match node.fields { 167 Fields::Named(_) => ContainerKind::StructVariant, 168 Fields::Unnamed(_) => ContainerKind::TupleVariant, 169 Fields::Unit => ContainerKind::UnitVariant, 170 } 171 } 172 } 173 174 impl Display for ContainerKind { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result175 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 176 formatter.write_str(match self { 177 ContainerKind::Struct => "struct", 178 ContainerKind::TupleStruct => "tuple struct", 179 ContainerKind::UnitStruct => "unit struct", 180 ContainerKind::StructVariant => "struct variant", 181 ContainerKind::TupleVariant => "tuple variant", 182 ContainerKind::UnitVariant => "unit variant", 183 }) 184 } 185 } 186