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