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