xref: /linux/rust/syn/data.rs (revision 784faa8eca8270671e0ed6d9d21f04bbb80fc5f7)
1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2 
3 use crate::attr::Attribute;
4 use crate::expr::{Expr, Index, Member};
5 use crate::ident::Ident;
6 use crate::punctuated::{self, Punctuated};
7 use crate::restriction::{FieldMutability, Visibility};
8 use crate::token;
9 use crate::ty::Type;
10 
11 ast_struct! {
12     /// An enum variant.
13     #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
14     pub struct Variant {
15         pub attrs: Vec<Attribute>,
16 
17         /// Name of the variant.
18         pub ident: Ident,
19 
20         /// Content stored in the variant.
21         pub fields: Fields,
22 
23         /// Explicit discriminant: `Variant = 1`
24         pub discriminant: Option<(Token![=], Expr)>,
25     }
26 }
27 
28 ast_enum_of_structs! {
29     /// Data stored within an enum variant or struct.
30     ///
31     /// # Syntax tree enum
32     ///
33     /// This type is a [syntax tree enum].
34     ///
35     /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
36     #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
37     pub enum Fields {
38         /// Named fields of a struct or struct variant such as `Point { x: f64,
39         /// y: f64 }`.
40         Named(FieldsNamed),
41 
42         /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
43         Unnamed(FieldsUnnamed),
44 
45         /// Unit struct or unit variant such as `None`.
46         Unit,
47     }
48 }
49 
50 ast_struct! {
51     /// Named fields of a struct or struct variant such as `Point { x: f64,
52     /// y: f64 }`.
53     #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
54     pub struct FieldsNamed {
55         pub brace_token: token::Brace,
56         pub named: Punctuated<Field, Token![,]>,
57     }
58 }
59 
60 ast_struct! {
61     /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
62     #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
63     pub struct FieldsUnnamed {
64         pub paren_token: token::Paren,
65         pub unnamed: Punctuated<Field, Token![,]>,
66     }
67 }
68 
69 impl Fields {
70     /// Get an iterator over the borrowed [`Field`] items in this object. This
71     /// iterator can be used to iterate over a named or unnamed struct or
72     /// variant's fields uniformly.
iter(&self) -> punctuated::Iter<Field>73     pub fn iter(&self) -> punctuated::Iter<Field> {
74         match self {
75             Fields::Unit => crate::punctuated::empty_punctuated_iter(),
76             Fields::Named(f) => f.named.iter(),
77             Fields::Unnamed(f) => f.unnamed.iter(),
78         }
79     }
80 
81     /// Get an iterator over the mutably borrowed [`Field`] items in this
82     /// object. This iterator can be used to iterate over a named or unnamed
83     /// struct or variant's fields uniformly.
iter_mut(&mut self) -> punctuated::IterMut<Field>84     pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
85         match self {
86             Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
87             Fields::Named(f) => f.named.iter_mut(),
88             Fields::Unnamed(f) => f.unnamed.iter_mut(),
89         }
90     }
91 
92     /// Returns the number of fields.
len(&self) -> usize93     pub fn len(&self) -> usize {
94         match self {
95             Fields::Unit => 0,
96             Fields::Named(f) => f.named.len(),
97             Fields::Unnamed(f) => f.unnamed.len(),
98         }
99     }
100 
101     /// Returns `true` if there are zero fields.
is_empty(&self) -> bool102     pub fn is_empty(&self) -> bool {
103         match self {
104             Fields::Unit => true,
105             Fields::Named(f) => f.named.is_empty(),
106             Fields::Unnamed(f) => f.unnamed.is_empty(),
107         }
108     }
109 
110     return_impl_trait! {
111         /// Get an iterator over the fields of a struct or variant as [`Member`]s.
112         /// This iterator can be used to iterate over a named or unnamed struct or
113         /// variant's fields uniformly.
114         ///
115         /// # Example
116         ///
117         /// The following is a simplistic [`Clone`] derive for structs. (A more
118         /// complete implementation would additionally want to infer trait bounds on
119         /// the generic type parameters.)
120         ///
121         /// ```
122         /// # use quote::quote;
123         /// #
124         /// fn derive_clone(input: &syn::ItemStruct) -> proc_macro2::TokenStream {
125         ///     let ident = &input.ident;
126         ///     let members = input.fields.members();
127         ///     let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
128         ///     quote! {
129         ///         impl #impl_generics Clone for #ident #ty_generics #where_clause {
130         ///             fn clone(&self) -> Self {
131         ///                 Self {
132         ///                     #(#members: self.#members.clone()),*
133         ///                 }
134         ///             }
135         ///         }
136         ///     }
137         /// }
138         /// ```
139         ///
140         /// For structs with named fields, it produces an expression like `Self { a:
141         /// self.a.clone() }`. For structs with unnamed fields, `Self { 0:
142         /// self.0.clone() }`. And for unit structs, `Self {}`.
143         pub fn members(&self) -> impl Iterator<Item = Member> + Clone + '_ [Members] {
144             Members {
145                 fields: self.iter(),
146                 index: 0,
147             }
148         }
149     }
150 }
151 
152 impl IntoIterator for Fields {
153     type Item = Field;
154     type IntoIter = punctuated::IntoIter<Field>;
155 
into_iter(self) -> Self::IntoIter156     fn into_iter(self) -> Self::IntoIter {
157         match self {
158             Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
159             Fields::Named(f) => f.named.into_iter(),
160             Fields::Unnamed(f) => f.unnamed.into_iter(),
161         }
162     }
163 }
164 
165 impl<'a> IntoIterator for &'a Fields {
166     type Item = &'a Field;
167     type IntoIter = punctuated::Iter<'a, Field>;
168 
into_iter(self) -> Self::IntoIter169     fn into_iter(self) -> Self::IntoIter {
170         self.iter()
171     }
172 }
173 
174 impl<'a> IntoIterator for &'a mut Fields {
175     type Item = &'a mut Field;
176     type IntoIter = punctuated::IterMut<'a, Field>;
177 
into_iter(self) -> Self::IntoIter178     fn into_iter(self) -> Self::IntoIter {
179         self.iter_mut()
180     }
181 }
182 
183 ast_struct! {
184     /// A field of a struct or enum variant.
185     #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
186     pub struct Field {
187         pub attrs: Vec<Attribute>,
188 
189         pub vis: Visibility,
190 
191         pub mutability: FieldMutability,
192 
193         /// Name of the field, if any.
194         ///
195         /// Fields of tuple structs have no names.
196         pub ident: Option<Ident>,
197 
198         pub colon_token: Option<Token![:]>,
199 
200         pub ty: Type,
201     }
202 }
203 
204 pub struct Members<'a> {
205     fields: punctuated::Iter<'a, Field>,
206     index: u32,
207 }
208 
209 impl<'a> Iterator for Members<'a> {
210     type Item = Member;
211 
next(&mut self) -> Option<Self::Item>212     fn next(&mut self) -> Option<Self::Item> {
213         let field = self.fields.next()?;
214         let member = match &field.ident {
215             Some(ident) => Member::Named(ident.clone()),
216             None => {
217                 #[cfg(all(feature = "parsing", feature = "printing"))]
218                 let span = crate::spanned::Spanned::span(&field.ty);
219                 #[cfg(not(all(feature = "parsing", feature = "printing")))]
220                 let span = proc_macro2::Span::call_site();
221                 Member::Unnamed(Index {
222                     index: self.index,
223                     span,
224                 })
225             }
226         };
227         self.index += 1;
228         Some(member)
229     }
230 }
231 
232 impl<'a> Clone for Members<'a> {
clone(&self) -> Self233     fn clone(&self) -> Self {
234         Members {
235             fields: self.fields.clone(),
236             index: self.index,
237         }
238     }
239 }
240 
241 #[cfg(feature = "parsing")]
242 pub(crate) mod parsing {
243     use crate::attr::Attribute;
244     use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant};
245     use crate::error::Result;
246     use crate::expr::Expr;
247     use crate::ext::IdentExt as _;
248     use crate::ident::Ident;
249     #[cfg(not(feature = "full"))]
250     use crate::parse::discouraged::Speculative as _;
251     use crate::parse::{Parse, ParseStream};
252     use crate::restriction::{FieldMutability, Visibility};
253     #[cfg(not(feature = "full"))]
254     use crate::scan_expr::scan_expr;
255     use crate::token;
256     use crate::ty::Type;
257     use crate::verbatim;
258 
259     #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
260     impl Parse for Variant {
parse(input: ParseStream) -> Result<Self>261         fn parse(input: ParseStream) -> Result<Self> {
262             let attrs = input.call(Attribute::parse_outer)?;
263             let _visibility: Visibility = input.parse()?;
264             let ident: Ident = input.parse()?;
265             let fields = if input.peek(token::Brace) {
266                 Fields::Named(input.parse()?)
267             } else if input.peek(token::Paren) {
268                 Fields::Unnamed(input.parse()?)
269             } else {
270                 Fields::Unit
271             };
272             let discriminant = if input.peek(Token![=]) {
273                 let eq_token: Token![=] = input.parse()?;
274                 #[cfg(feature = "full")]
275                 let discriminant: Expr = input.parse()?;
276                 #[cfg(not(feature = "full"))]
277                 let discriminant = {
278                     let begin = input.fork();
279                     let ahead = input.fork();
280                     let mut discriminant: Result<Expr> = ahead.parse();
281                     if discriminant.is_ok() {
282                         input.advance_to(&ahead);
283                     } else if scan_expr(input).is_ok() {
284                         discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input)));
285                     }
286                     discriminant?
287                 };
288                 Some((eq_token, discriminant))
289             } else {
290                 None
291             };
292             Ok(Variant {
293                 attrs,
294                 ident,
295                 fields,
296                 discriminant,
297             })
298         }
299     }
300 
301     #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
302     impl Parse for FieldsNamed {
parse(input: ParseStream) -> Result<Self>303         fn parse(input: ParseStream) -> Result<Self> {
304             let content;
305             Ok(FieldsNamed {
306                 brace_token: braced!(content in input),
307                 named: content.parse_terminated(Field::parse_named, Token![,])?,
308             })
309         }
310     }
311 
312     #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
313     impl Parse for FieldsUnnamed {
parse(input: ParseStream) -> Result<Self>314         fn parse(input: ParseStream) -> Result<Self> {
315             let content;
316             Ok(FieldsUnnamed {
317                 paren_token: parenthesized!(content in input),
318                 unnamed: content.parse_terminated(Field::parse_unnamed, Token![,])?,
319             })
320         }
321     }
322 
323     impl Field {
324         /// Parses a named (braced struct) field.
325         #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
parse_named(input: ParseStream) -> Result<Self>326         pub fn parse_named(input: ParseStream) -> Result<Self> {
327             let attrs = input.call(Attribute::parse_outer)?;
328             let vis: Visibility = input.parse()?;
329 
330             let unnamed_field = cfg!(feature = "full") && input.peek(Token![_]);
331             let ident = if unnamed_field {
332                 input.call(Ident::parse_any)
333             } else {
334                 input.parse()
335             }?;
336 
337             let colon_token: Token![:] = input.parse()?;
338 
339             let ty: Type = if unnamed_field
340                 && (input.peek(Token![struct])
341                     || input.peek(Token![union]) && input.peek2(token::Brace))
342             {
343                 let begin = input.fork();
344                 input.call(Ident::parse_any)?;
345                 input.parse::<FieldsNamed>()?;
346                 Type::Verbatim(verbatim::between(&begin, input))
347             } else {
348                 input.parse()?
349             };
350 
351             Ok(Field {
352                 attrs,
353                 vis,
354                 mutability: FieldMutability::None,
355                 ident: Some(ident),
356                 colon_token: Some(colon_token),
357                 ty,
358             })
359         }
360 
361         /// Parses an unnamed (tuple struct) field.
362         #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
parse_unnamed(input: ParseStream) -> Result<Self>363         pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
364             Ok(Field {
365                 attrs: input.call(Attribute::parse_outer)?,
366                 vis: input.parse()?,
367                 mutability: FieldMutability::None,
368                 ident: None,
369                 colon_token: None,
370                 ty: input.parse()?,
371             })
372         }
373     }
374 }
375 
376 #[cfg(feature = "printing")]
377 mod printing {
378     use crate::data::{Field, FieldsNamed, FieldsUnnamed, Variant};
379     use crate::print::TokensOrDefault;
380     use proc_macro2::TokenStream;
381     use quote::{ToTokens, TokenStreamExt};
382 
383     #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
384     impl ToTokens for Variant {
to_tokens(&self, tokens: &mut TokenStream)385         fn to_tokens(&self, tokens: &mut TokenStream) {
386             tokens.append_all(&self.attrs);
387             self.ident.to_tokens(tokens);
388             self.fields.to_tokens(tokens);
389             if let Some((eq_token, disc)) = &self.discriminant {
390                 eq_token.to_tokens(tokens);
391                 disc.to_tokens(tokens);
392             }
393         }
394     }
395 
396     #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
397     impl ToTokens for FieldsNamed {
to_tokens(&self, tokens: &mut TokenStream)398         fn to_tokens(&self, tokens: &mut TokenStream) {
399             self.brace_token.surround(tokens, |tokens| {
400                 self.named.to_tokens(tokens);
401             });
402         }
403     }
404 
405     #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
406     impl ToTokens for FieldsUnnamed {
to_tokens(&self, tokens: &mut TokenStream)407         fn to_tokens(&self, tokens: &mut TokenStream) {
408             self.paren_token.surround(tokens, |tokens| {
409                 self.unnamed.to_tokens(tokens);
410             });
411         }
412     }
413 
414     #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
415     impl ToTokens for Field {
to_tokens(&self, tokens: &mut TokenStream)416         fn to_tokens(&self, tokens: &mut TokenStream) {
417             tokens.append_all(&self.attrs);
418             self.vis.to_tokens(tokens);
419             if let Some(ident) = &self.ident {
420                 ident.to_tokens(tokens);
421                 TokensOrDefault(&self.colon_token).to_tokens(tokens);
422             }
423             self.ty.to_tokens(tokens);
424         }
425     }
426 }
427