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 {
parse(input: ParseStream) -> Result<Self>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 
data_struct( input: ParseStream, ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)>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 
data_enum( input: ParseStream, ) -> Result<( Option<WhereClause>, token::Brace, Punctuated<Variant, Token![,]>, )>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 
data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)>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 {
to_tokens(&self, tokens: &mut TokenStream)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