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> { |
46 | pub fn from_syn(node: &'a DeriveInput) -> Result<Self> { |
47 | match &node.data { |
48 | Data::Struct(data: &DataStruct) => Struct::from_syn(node, data).map(op:Input::Struct), |
49 | Data::Enum(data: &DataEnum) => Enum::from_syn(node, data).map(op:Input::Enum), |
50 | Data::Union(_) => Err(Error::new_spanned( |
51 | tokens:node, |
52 | message:"union as errors are not supported" , |
53 | )), |
54 | } |
55 | } |
56 | } |
57 | |
58 | impl<'a> Struct<'a> { |
59 | fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self> { |
60 | let mut attrs: Attrs<'_> = attr::get(&node.attrs)?; |
61 | let scope: ParamsInScope<'_> = ParamsInScope::new(&node.generics); |
62 | let span: Span = attrs.span().unwrap_or_else(Span::call_site); |
63 | let fields: Vec> = Field::multiple_from_syn(&data.fields, &scope, span)?; |
64 | if let Some(display: &mut 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> { |
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> { |
109 | fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>, span: Span) -> Result<Self> { |
110 | let attrs: Attrs<'_> = attr::get(&node.attrs)?; |
111 | let span: Span = attrs.span().unwrap_or(default: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> { |
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 | |
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<'_> { |
156 | pub fn span(&self) -> Option<Span> { |
157 | if let Some(display: &Display<'_>) = &self.display { |
158 | Some(display.fmt.span()) |
159 | } else if let Some(transparent: &Transparent<'_>) = &self.transparent { |
160 | Some(transparent.span) |
161 | } else { |
162 | None |
163 | } |
164 | } |
165 | } |
166 | |