]>
Commit | Line | Data |
---|---|---|
e74abb32 XL |
1 | use super::*; |
2 | use crate::punctuated::Punctuated; | |
3 | ||
4 | ast_struct! { | |
5 | /// Data structure sent to a `proc_macro_derive` macro. | |
6 | /// | |
f035d41b | 7 | /// *This type is available only if Syn is built with the `"derive"` feature.* |
5869c6ff | 8 | #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] |
e74abb32 XL |
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 | /// | |
f035d41b | 30 | /// *This type is available only if Syn is built with the `"derive"` feature.* |
e74abb32 XL |
31 | /// |
32 | /// # Syntax tree enum | |
33 | /// | |
34 | /// This type is a [syntax tree enum]. | |
35 | /// | |
5869c6ff XL |
36 | /// [syntax tree enum]: Expr#syntax-tree-enums |
37 | #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] | |
e74abb32 XL |
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 | /// | |
f035d41b | 55 | /// *This type is available only if Syn is built with the `"derive"` |
e74abb32 | 56 | /// feature.* |
5869c6ff | 57 | #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] |
e74abb32 XL |
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 | /// | |
f035d41b | 68 | /// *This type is available only if Syn is built with the `"derive"` |
e74abb32 | 69 | /// feature.* |
5869c6ff | 70 | #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] |
e74abb32 XL |
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 | /// | |
f035d41b | 81 | /// *This type is available only if Syn is built with the `"derive"` |
e74abb32 | 82 | /// feature.* |
5869c6ff | 83 | #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] |
e74abb32 XL |
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::*; | |
e74abb32 XL |
93 | use crate::parse::{Parse, ParseStream, Result}; |
94 | ||
5869c6ff | 95 | #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] |
e74abb32 XL |
96 | impl Parse for DeriveInput { |
97 | fn parse(input: ParseStream) -> Result<Self> { | |
cdc7bbd5 | 98 | let mut attrs = input.call(Attribute::parse_outer)?; |
e74abb32 XL |
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>()?; | |
cdc7bbd5 | 106 | let (where_clause, fields, semi) = data_struct(input, &mut attrs)?; |
e74abb32 XL |
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>()?; | |
cdc7bbd5 | 125 | let (where_clause, brace, variants) = data_enum(input, &mut attrs)?; |
e74abb32 XL |
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>()?; | |
cdc7bbd5 | 144 | let (where_clause, fields) = data_union(input, &mut attrs)?; |
e74abb32 XL |
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 | ||
164 | pub fn data_struct( | |
165 | input: ParseStream, | |
cdc7bbd5 | 166 | attrs: &mut Vec<Attribute>, |
e74abb32 XL |
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) { | |
cdc7bbd5 | 191 | let fields = data::parsing::parse_braced(input, attrs)?; |
e74abb32 XL |
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 | ||
201 | pub fn data_enum( | |
202 | input: ParseStream, | |
cdc7bbd5 | 203 | attrs: &mut Vec<Attribute>, |
e74abb32 XL |
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); | |
cdc7bbd5 | 213 | attr::parsing::parse_inner(&content, attrs)?; |
e74abb32 XL |
214 | let variants = content.parse_terminated(Variant::parse)?; |
215 | ||
216 | Ok((where_clause, brace, variants)) | |
217 | } | |
218 | ||
cdc7bbd5 XL |
219 | pub fn data_union( |
220 | input: ParseStream, | |
221 | attrs: &mut Vec<Attribute>, | |
222 | ) -> Result<(Option<WhereClause>, FieldsNamed)> { | |
e74abb32 | 223 | let where_clause = input.parse()?; |
cdc7bbd5 | 224 | let fields = data::parsing::parse_braced(input, attrs)?; |
e74abb32 XL |
225 | Ok((where_clause, fields)) |
226 | } | |
227 | } | |
228 | ||
229 | #[cfg(feature = "printing")] | |
230 | mod printing { | |
231 | use super::*; | |
e74abb32 XL |
232 | use crate::attr::FilterAttrs; |
233 | use crate::print::TokensOrDefault; | |
29967ef6 XL |
234 | use proc_macro2::TokenStream; |
235 | use quote::ToTokens; | |
e74abb32 | 236 | |
5869c6ff | 237 | #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] |
e74abb32 XL |
238 | impl ToTokens for DeriveInput { |
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 | } |