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