1 | use crate::attr::Attribute; |
2 | use crate::data::{Fields, FieldsNamed, Variant}; |
3 | use crate::generics::Generics; |
4 | use crate::ident::Ident; |
5 | use crate::punctuated::Punctuated; |
6 | use crate::restriction::Visibility; |
7 | use crate::token; |
8 | |
9 | ast_struct! { |
10 | /// Data structure sent to a `proc_macro_derive` macro. |
11 | #[cfg_attr (doc_cfg, doc(cfg(feature = "derive" )))] |
12 | pub struct DeriveInput { |
13 | pub attrs: Vec<Attribute>, |
14 | pub vis: Visibility, |
15 | pub ident: Ident, |
16 | pub generics: Generics, |
17 | pub data: Data, |
18 | } |
19 | } |
20 | |
21 | ast_enum! { |
22 | /// The storage of a struct, enum or union data structure. |
23 | /// |
24 | /// # Syntax tree enum |
25 | /// |
26 | /// This type is a [syntax tree enum]. |
27 | /// |
28 | /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums |
29 | #[cfg_attr (doc_cfg, doc(cfg(feature = "derive" )))] |
30 | pub enum Data { |
31 | Struct(DataStruct), |
32 | Enum(DataEnum), |
33 | Union(DataUnion), |
34 | } |
35 | } |
36 | |
37 | ast_struct! { |
38 | /// A struct input to a `proc_macro_derive` macro. |
39 | #[cfg_attr (doc_cfg, doc(cfg(feature = "derive" )))] |
40 | pub struct DataStruct { |
41 | pub struct_token: Token![struct], |
42 | pub fields: Fields, |
43 | pub semi_token: Option<Token![;]>, |
44 | } |
45 | } |
46 | |
47 | ast_struct! { |
48 | /// An enum input to a `proc_macro_derive` macro. |
49 | #[cfg_attr (doc_cfg, doc(cfg(feature = "derive" )))] |
50 | pub struct DataEnum { |
51 | pub enum_token: Token![enum], |
52 | pub brace_token: token::Brace, |
53 | pub variants: Punctuated<Variant, Token![,]>, |
54 | } |
55 | } |
56 | |
57 | ast_struct! { |
58 | /// An untagged union input to a `proc_macro_derive` macro. |
59 | #[cfg_attr (doc_cfg, doc(cfg(feature = "derive" )))] |
60 | pub struct DataUnion { |
61 | pub union_token: Token![union], |
62 | pub fields: FieldsNamed, |
63 | } |
64 | } |
65 | |
66 | #[cfg (feature = "parsing" )] |
67 | pub(crate) mod parsing { |
68 | use crate::attr::Attribute; |
69 | use crate::data::{Fields, FieldsNamed, Variant}; |
70 | use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput}; |
71 | use crate::error::Result; |
72 | use crate::generics::{Generics, WhereClause}; |
73 | use crate::ident::Ident; |
74 | use crate::parse::{Parse, ParseStream}; |
75 | use crate::punctuated::Punctuated; |
76 | use crate::restriction::Visibility; |
77 | use crate::token; |
78 | |
79 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
80 | impl Parse for DeriveInput { |
81 | fn parse(input: ParseStream) -> Result<Self> { |
82 | let attrs = input.call(Attribute::parse_outer)?; |
83 | let vis = input.parse::<Visibility>()?; |
84 | |
85 | let lookahead = input.lookahead1(); |
86 | if lookahead.peek(Token![struct]) { |
87 | let struct_token = input.parse::<Token![struct]>()?; |
88 | let ident = input.parse::<Ident>()?; |
89 | let generics = input.parse::<Generics>()?; |
90 | let (where_clause, fields, semi) = data_struct(input)?; |
91 | Ok(DeriveInput { |
92 | attrs, |
93 | vis, |
94 | ident, |
95 | generics: Generics { |
96 | where_clause, |
97 | ..generics |
98 | }, |
99 | data: Data::Struct(DataStruct { |
100 | struct_token, |
101 | fields, |
102 | semi_token: semi, |
103 | }), |
104 | }) |
105 | } else if lookahead.peek(Token![enum]) { |
106 | let enum_token = input.parse::<Token![enum]>()?; |
107 | let ident = input.parse::<Ident>()?; |
108 | let generics = input.parse::<Generics>()?; |
109 | let (where_clause, brace, variants) = data_enum(input)?; |
110 | Ok(DeriveInput { |
111 | attrs, |
112 | vis, |
113 | ident, |
114 | generics: Generics { |
115 | where_clause, |
116 | ..generics |
117 | }, |
118 | data: Data::Enum(DataEnum { |
119 | enum_token, |
120 | brace_token: brace, |
121 | variants, |
122 | }), |
123 | }) |
124 | } else if lookahead.peek(Token![union]) { |
125 | let union_token = input.parse::<Token![union]>()?; |
126 | let ident = input.parse::<Ident>()?; |
127 | let generics = input.parse::<Generics>()?; |
128 | let (where_clause, fields) = data_union(input)?; |
129 | Ok(DeriveInput { |
130 | attrs, |
131 | vis, |
132 | ident, |
133 | generics: Generics { |
134 | where_clause, |
135 | ..generics |
136 | }, |
137 | data: Data::Union(DataUnion { |
138 | union_token, |
139 | fields, |
140 | }), |
141 | }) |
142 | } else { |
143 | Err(lookahead.error()) |
144 | } |
145 | } |
146 | } |
147 | |
148 | pub(crate) fn data_struct( |
149 | input: ParseStream, |
150 | ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> { |
151 | let mut lookahead = input.lookahead1(); |
152 | let mut where_clause = None; |
153 | if lookahead.peek(Token![where]) { |
154 | where_clause = Some(input.parse()?); |
155 | lookahead = input.lookahead1(); |
156 | } |
157 | |
158 | if where_clause.is_none() && lookahead.peek(token::Paren) { |
159 | let fields = input.parse()?; |
160 | |
161 | lookahead = input.lookahead1(); |
162 | if lookahead.peek(Token![where]) { |
163 | where_clause = Some(input.parse()?); |
164 | lookahead = input.lookahead1(); |
165 | } |
166 | |
167 | if lookahead.peek(Token![;]) { |
168 | let semi = input.parse()?; |
169 | Ok((where_clause, Fields::Unnamed(fields), Some(semi))) |
170 | } else { |
171 | Err(lookahead.error()) |
172 | } |
173 | } else if lookahead.peek(token::Brace) { |
174 | let fields = input.parse()?; |
175 | Ok((where_clause, Fields::Named(fields), None)) |
176 | } else if lookahead.peek(Token![;]) { |
177 | let semi = input.parse()?; |
178 | Ok((where_clause, Fields::Unit, Some(semi))) |
179 | } else { |
180 | Err(lookahead.error()) |
181 | } |
182 | } |
183 | |
184 | pub(crate) fn data_enum( |
185 | input: ParseStream, |
186 | ) -> Result<( |
187 | Option<WhereClause>, |
188 | token::Brace, |
189 | Punctuated<Variant, Token![,]>, |
190 | )> { |
191 | let where_clause = input.parse()?; |
192 | |
193 | let content; |
194 | let brace = braced!(content in input); |
195 | let variants = content.parse_terminated(Variant::parse, Token![,])?; |
196 | |
197 | Ok((where_clause, brace, variants)) |
198 | } |
199 | |
200 | pub(crate) fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> { |
201 | let where_clause = input.parse()?; |
202 | let fields = input.parse()?; |
203 | Ok((where_clause, fields)) |
204 | } |
205 | } |
206 | |
207 | #[cfg (feature = "printing" )] |
208 | mod printing { |
209 | use crate::attr::FilterAttrs; |
210 | use crate::data::Fields; |
211 | use crate::derive::{Data, DeriveInput}; |
212 | use crate::print::TokensOrDefault; |
213 | use proc_macro2::TokenStream; |
214 | use quote::ToTokens; |
215 | |
216 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
217 | impl ToTokens for DeriveInput { |
218 | fn to_tokens(&self, tokens: &mut TokenStream) { |
219 | for attr in self.attrs.outer() { |
220 | attr.to_tokens(tokens); |
221 | } |
222 | self.vis.to_tokens(tokens); |
223 | match &self.data { |
224 | Data::Struct(d) => d.struct_token.to_tokens(tokens), |
225 | Data::Enum(d) => d.enum_token.to_tokens(tokens), |
226 | Data::Union(d) => d.union_token.to_tokens(tokens), |
227 | } |
228 | self.ident.to_tokens(tokens); |
229 | self.generics.to_tokens(tokens); |
230 | match &self.data { |
231 | Data::Struct(data) => match &data.fields { |
232 | Fields::Named(fields) => { |
233 | self.generics.where_clause.to_tokens(tokens); |
234 | fields.to_tokens(tokens); |
235 | } |
236 | Fields::Unnamed(fields) => { |
237 | fields.to_tokens(tokens); |
238 | self.generics.where_clause.to_tokens(tokens); |
239 | TokensOrDefault(&data.semi_token).to_tokens(tokens); |
240 | } |
241 | Fields::Unit => { |
242 | self.generics.where_clause.to_tokens(tokens); |
243 | TokensOrDefault(&data.semi_token).to_tokens(tokens); |
244 | } |
245 | }, |
246 | Data::Enum(data) => { |
247 | self.generics.where_clause.to_tokens(tokens); |
248 | data.brace_token.surround(tokens, |tokens| { |
249 | data.variants.to_tokens(tokens); |
250 | }); |
251 | } |
252 | Data::Union(data) => { |
253 | self.generics.where_clause.to_tokens(tokens); |
254 | data.fields.to_tokens(tokens); |
255 | } |
256 | } |
257 | } |
258 | } |
259 | } |
260 | |