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