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