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