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