1 use super::*;
2 use crate::punctuated::Punctuated;
3 
4 ast_struct! {
5     /// An enum variant.
6     ///
7     /// *This type is available if Syn is built with the `"derive"` or `"full"`
8     /// feature.*
9     pub struct Variant {
10         /// Attributes tagged on the variant.
11         pub attrs: Vec<Attribute>,
12 
13         /// Name of the variant.
14         pub ident: Ident,
15 
16         /// Content stored in the variant.
17         pub fields: Fields,
18 
19         /// Explicit discriminant: `Variant = 1`
20         pub discriminant: Option<(Token![=], Expr)>,
21     }
22 }
23 
24 ast_enum_of_structs! {
25     /// Data stored within an enum variant or struct.
26     ///
27     /// *This type is available if Syn is built with the `"derive"` or `"full"`
28     /// feature.*
29     ///
30     /// # Syntax tree enum
31     ///
32     /// This type is a [syntax tree enum].
33     ///
34     /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
35     //
36     // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
37     // blocked on https://github.com/rust-lang/rust/issues/62833
38     pub enum Fields {
39         /// Named fields of a struct or struct variant such as `Point { x: f64,
40         /// y: f64 }`.
41         Named(FieldsNamed),
42 
43         /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
44         Unnamed(FieldsUnnamed),
45 
46         /// Unit struct or unit variant such as `None`.
47         Unit,
48     }
49 }
50 
51 ast_struct! {
52     /// Named fields of a struct or struct variant such as `Point { x: f64,
53     /// y: f64 }`.
54     ///
55     /// *This type is available if Syn is built with the `"derive"` or
56     /// `"full"` feature.*
57     pub struct FieldsNamed {
58         pub brace_token: token::Brace,
59         pub named: Punctuated<Field, Token![,]>,
60     }
61 }
62 
63 ast_struct! {
64     /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
65     ///
66     /// *This type is available if Syn is built with the `"derive"` or
67     /// `"full"` feature.*
68     pub struct FieldsUnnamed {
69         pub paren_token: token::Paren,
70         pub unnamed: Punctuated<Field, Token![,]>,
71     }
72 }
73 
74 impl Fields {
75     /// Get an iterator over the borrowed [`Field`] items in this object. This
76     /// iterator can be used to iterate over a named or unnamed struct or
77     /// variant's fields uniformly.
iter(&self) -> punctuated::Iter<Field>78     pub fn iter(&self) -> punctuated::Iter<Field> {
79         match self {
80             Fields::Unit => crate::punctuated::empty_punctuated_iter(),
81             Fields::Named(f) => f.named.iter(),
82             Fields::Unnamed(f) => f.unnamed.iter(),
83         }
84     }
85 
86     /// Get an iterator over the mutably borrowed [`Field`] items in this
87     /// object. This iterator can be used to iterate over a named or unnamed
88     /// struct or variant's fields uniformly.
iter_mut(&mut self) -> punctuated::IterMut<Field>89     pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
90         match self {
91             Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
92             Fields::Named(f) => f.named.iter_mut(),
93             Fields::Unnamed(f) => f.unnamed.iter_mut(),
94         }
95     }
96 }
97 
98 impl IntoIterator for Fields {
99     type Item = Field;
100     type IntoIter = punctuated::IntoIter<Field>;
101 
into_iter(self) -> Self::IntoIter102     fn into_iter(self) -> Self::IntoIter {
103         match self {
104             Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
105             Fields::Named(f) => f.named.into_iter(),
106             Fields::Unnamed(f) => f.unnamed.into_iter(),
107         }
108     }
109 }
110 
111 impl<'a> IntoIterator for &'a Fields {
112     type Item = &'a Field;
113     type IntoIter = punctuated::Iter<'a, Field>;
114 
into_iter(self) -> Self::IntoIter115     fn into_iter(self) -> Self::IntoIter {
116         self.iter()
117     }
118 }
119 
120 impl<'a> IntoIterator for &'a mut Fields {
121     type Item = &'a mut Field;
122     type IntoIter = punctuated::IterMut<'a, Field>;
123 
into_iter(self) -> Self::IntoIter124     fn into_iter(self) -> Self::IntoIter {
125         self.iter_mut()
126     }
127 }
128 
129 ast_struct! {
130     /// A field of a struct or enum variant.
131     ///
132     /// *This type is available if Syn is built with the `"derive"` or `"full"`
133     /// feature.*
134     pub struct Field {
135         /// Attributes tagged on the field.
136         pub attrs: Vec<Attribute>,
137 
138         /// Visibility of the field.
139         pub vis: Visibility,
140 
141         /// Name of the field, if any.
142         ///
143         /// Fields of tuple structs have no names.
144         pub ident: Option<Ident>,
145 
146         pub colon_token: Option<Token![:]>,
147 
148         /// Type of the field.
149         pub ty: Type,
150     }
151 }
152 
153 ast_enum_of_structs! {
154     /// The visibility level of an item: inherited or `pub` or
155     /// `pub(restricted)`.
156     ///
157     /// *This type is available if Syn is built with the `"derive"` or `"full"`
158     /// feature.*
159     ///
160     /// # Syntax tree enum
161     ///
162     /// This type is a [syntax tree enum].
163     ///
164     /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
165     //
166     // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
167     // blocked on https://github.com/rust-lang/rust/issues/62833
168     pub enum Visibility {
169         /// A public visibility level: `pub`.
170         Public(VisPublic),
171 
172         /// A crate-level visibility: `crate`.
173         Crate(VisCrate),
174 
175         /// A visibility level restricted to some path: `pub(self)` or
176         /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
177         Restricted(VisRestricted),
178 
179         /// An inherited visibility, which usually means private.
180         Inherited,
181     }
182 }
183 
184 ast_struct! {
185     /// A public visibility level: `pub`.
186     ///
187     /// *This type is available if Syn is built with the `"derive"` or
188     /// `"full"` feature.*
189     pub struct VisPublic {
190         pub pub_token: Token![pub],
191     }
192 }
193 
194 ast_struct! {
195     /// A crate-level visibility: `crate`.
196     ///
197     /// *This type is available if Syn is built with the `"derive"` or
198     /// `"full"` feature.*
199     pub struct VisCrate {
200         pub crate_token: Token![crate],
201     }
202 }
203 
204 ast_struct! {
205     /// A visibility level restricted to some path: `pub(self)` or
206     /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
207     ///
208     /// *This type is available if Syn is built with the `"derive"` or
209     /// `"full"` feature.*
210     pub struct VisRestricted {
211         pub pub_token: Token![pub],
212         pub paren_token: token::Paren,
213         pub in_token: Option<Token![in]>,
214         pub path: Box<Path>,
215     }
216 }
217 
218 #[cfg(feature = "parsing")]
219 pub mod parsing {
220     use super::*;
221 
222     use crate::ext::IdentExt;
223     use crate::parse::{Parse, ParseStream, Result};
224 
225     impl Parse for Variant {
parse(input: ParseStream) -> Result<Self>226         fn parse(input: ParseStream) -> Result<Self> {
227             Ok(Variant {
228                 attrs: input.call(Attribute::parse_outer)?,
229                 ident: input.parse()?,
230                 fields: {
231                     if input.peek(token::Brace) {
232                         Fields::Named(input.parse()?)
233                     } else if input.peek(token::Paren) {
234                         Fields::Unnamed(input.parse()?)
235                     } else {
236                         Fields::Unit
237                     }
238                 },
239                 discriminant: {
240                     if input.peek(Token![=]) {
241                         let eq_token: Token![=] = input.parse()?;
242                         let discriminant: Expr = input.parse()?;
243                         Some((eq_token, discriminant))
244                     } else {
245                         None
246                     }
247                 },
248             })
249         }
250     }
251 
252     impl Parse for FieldsNamed {
parse(input: ParseStream) -> Result<Self>253         fn parse(input: ParseStream) -> Result<Self> {
254             let content;
255             Ok(FieldsNamed {
256                 brace_token: braced!(content in input),
257                 named: content.parse_terminated(Field::parse_named)?,
258             })
259         }
260     }
261 
262     impl Parse for FieldsUnnamed {
parse(input: ParseStream) -> Result<Self>263         fn parse(input: ParseStream) -> Result<Self> {
264             let content;
265             Ok(FieldsUnnamed {
266                 paren_token: parenthesized!(content in input),
267                 unnamed: content.parse_terminated(Field::parse_unnamed)?,
268             })
269         }
270     }
271 
272     impl Field {
273         /// Parses a named (braced struct) field.
parse_named(input: ParseStream) -> Result<Self>274         pub fn parse_named(input: ParseStream) -> Result<Self> {
275             Ok(Field {
276                 attrs: input.call(Attribute::parse_outer)?,
277                 vis: input.parse()?,
278                 ident: Some(input.parse()?),
279                 colon_token: Some(input.parse()?),
280                 ty: input.parse()?,
281             })
282         }
283 
284         /// Parses an unnamed (tuple struct) field.
parse_unnamed(input: ParseStream) -> Result<Self>285         pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
286             Ok(Field {
287                 attrs: input.call(Attribute::parse_outer)?,
288                 vis: input.parse()?,
289                 ident: None,
290                 colon_token: None,
291                 ty: input.parse()?,
292             })
293         }
294     }
295 
296     impl Parse for Visibility {
parse(input: ParseStream) -> Result<Self>297         fn parse(input: ParseStream) -> Result<Self> {
298             if input.peek(Token![pub]) {
299                 Self::parse_pub(input)
300             } else if input.peek(Token![crate]) {
301                 Self::parse_crate(input)
302             } else {
303                 Ok(Visibility::Inherited)
304             }
305         }
306     }
307 
308     impl Visibility {
parse_pub(input: ParseStream) -> Result<Self>309         fn parse_pub(input: ParseStream) -> Result<Self> {
310             let pub_token = input.parse::<Token![pub]>()?;
311 
312             if input.peek(token::Paren) {
313                 // TODO: optimize using advance_to
314                 let ahead = input.fork();
315                 let mut content;
316                 parenthesized!(content in ahead);
317 
318                 if content.peek(Token![crate])
319                     || content.peek(Token![self])
320                     || content.peek(Token![super])
321                 {
322                     return Ok(Visibility::Restricted(VisRestricted {
323                         pub_token,
324                         paren_token: parenthesized!(content in input),
325                         in_token: None,
326                         path: Box::new(Path::from(content.call(Ident::parse_any)?)),
327                     }));
328                 } else if content.peek(Token![in]) {
329                     return Ok(Visibility::Restricted(VisRestricted {
330                         pub_token,
331                         paren_token: parenthesized!(content in input),
332                         in_token: Some(content.parse()?),
333                         path: Box::new(content.call(Path::parse_mod_style)?),
334                     }));
335                 }
336             }
337 
338             Ok(Visibility::Public(VisPublic { pub_token }))
339         }
340 
parse_crate(input: ParseStream) -> Result<Self>341         fn parse_crate(input: ParseStream) -> Result<Self> {
342             if input.peek2(Token![::]) {
343                 Ok(Visibility::Inherited)
344             } else {
345                 Ok(Visibility::Crate(VisCrate {
346                     crate_token: input.parse()?,
347                 }))
348             }
349         }
350     }
351 }
352 
353 #[cfg(feature = "printing")]
354 mod printing {
355     use super::*;
356 
357     use proc_macro2::TokenStream;
358     use quote::{ToTokens, TokenStreamExt};
359 
360     use crate::print::TokensOrDefault;
361 
362     impl ToTokens for Variant {
to_tokens(&self, tokens: &mut TokenStream)363         fn to_tokens(&self, tokens: &mut TokenStream) {
364             tokens.append_all(&self.attrs);
365             self.ident.to_tokens(tokens);
366             self.fields.to_tokens(tokens);
367             if let Some((eq_token, disc)) = &self.discriminant {
368                 eq_token.to_tokens(tokens);
369                 disc.to_tokens(tokens);
370             }
371         }
372     }
373 
374     impl ToTokens for FieldsNamed {
to_tokens(&self, tokens: &mut TokenStream)375         fn to_tokens(&self, tokens: &mut TokenStream) {
376             self.brace_token.surround(tokens, |tokens| {
377                 self.named.to_tokens(tokens);
378             });
379         }
380     }
381 
382     impl ToTokens for FieldsUnnamed {
to_tokens(&self, tokens: &mut TokenStream)383         fn to_tokens(&self, tokens: &mut TokenStream) {
384             self.paren_token.surround(tokens, |tokens| {
385                 self.unnamed.to_tokens(tokens);
386             });
387         }
388     }
389 
390     impl ToTokens for Field {
to_tokens(&self, tokens: &mut TokenStream)391         fn to_tokens(&self, tokens: &mut TokenStream) {
392             tokens.append_all(&self.attrs);
393             self.vis.to_tokens(tokens);
394             if let Some(ident) = &self.ident {
395                 ident.to_tokens(tokens);
396                 TokensOrDefault(&self.colon_token).to_tokens(tokens);
397             }
398             self.ty.to_tokens(tokens);
399         }
400     }
401 
402     impl ToTokens for VisPublic {
to_tokens(&self, tokens: &mut TokenStream)403         fn to_tokens(&self, tokens: &mut TokenStream) {
404             self.pub_token.to_tokens(tokens)
405         }
406     }
407 
408     impl ToTokens for VisCrate {
to_tokens(&self, tokens: &mut TokenStream)409         fn to_tokens(&self, tokens: &mut TokenStream) {
410             self.crate_token.to_tokens(tokens);
411         }
412     }
413 
414     impl ToTokens for VisRestricted {
to_tokens(&self, tokens: &mut TokenStream)415         fn to_tokens(&self, tokens: &mut TokenStream) {
416             self.pub_token.to_tokens(tokens);
417             self.paren_token.surround(tokens, |tokens| {
418                 // TODO: If we have a path which is not "self" or "super" or
419                 // "crate", automatically add the "in" token.
420                 self.in_token.to_tokens(tokens);
421                 self.path.to_tokens(tokens);
422             });
423         }
424     }
425 }
426