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