standalone_syn/
data.rs

1// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use super::*;
10use punctuated::Punctuated;
11
12ast_struct! {
13    /// An enum variant.
14    ///
15    /// *This type is available if Syn is built with the `"derive"` or `"full"`
16    /// feature.*
17    pub struct Variant {
18        /// Attributes tagged on the variant.
19        pub attrs: Vec<Attribute>,
20
21        /// Name of the variant.
22        pub ident: Ident,
23
24        /// Content stored in the variant.
25        pub fields: Fields,
26
27        /// Explicit discriminant: `Variant = 1`
28        pub discriminant: Option<(Token![=], Expr)>,
29    }
30}
31
32ast_enum_of_structs! {
33    /// Data stored within an enum variant or struct.
34    ///
35    /// *This type is available if Syn is built with the `"derive"` or `"full"`
36    /// feature.*
37    ///
38    /// # Syntax tree enum
39    ///
40    /// This type is a [syntax tree enum].
41    ///
42    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
43    pub enum Fields {
44        /// Named fields of a struct or struct variant such as `Point { x: f64,
45        /// y: f64 }`.
46        ///
47        /// *This type is available if Syn is built with the `"derive"` or
48        /// `"full"` feature.*
49        pub Named(FieldsNamed {
50            pub brace_token: token::Brace,
51            pub named: Punctuated<Field, Token![,]>,
52        }),
53
54        /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
55        ///
56        /// *This type is available if Syn is built with the `"derive"` or
57        /// `"full"` feature.*
58        pub Unnamed(FieldsUnnamed {
59            pub paren_token: token::Paren,
60            pub unnamed: Punctuated<Field, Token![,]>,
61        }),
62
63        /// Unit struct or unit variant such as `None`.
64        pub Unit,
65    }
66}
67
68impl Fields {
69    /// Get an iterator over the [`Field`] items in this object. This iterator
70    /// can be used to iterate over a named or unnamed struct or variant's
71    /// fields uniformly.
72    ///
73    /// [`Field`]: struct.Field.html
74    pub fn iter(&self) -> punctuated::Iter<Field, Token![,]> {
75        match *self {
76            Fields::Unit => punctuated::Iter::private_empty(),
77            Fields::Named(ref f) => f.named.iter(),
78            Fields::Unnamed(ref f) => f.unnamed.iter(),
79        }
80    }
81}
82
83impl<'a> IntoIterator for &'a Fields {
84    type Item = &'a Field;
85    type IntoIter = punctuated::Iter<'a, Field, Token![,]>;
86
87    fn into_iter(self) -> Self::IntoIter {
88        self.iter()
89    }
90}
91
92ast_struct! {
93    /// A field of a struct or enum variant.
94    ///
95    /// *This type is available if Syn is built with the `"derive"` or `"full"`
96    /// feature.*
97    pub struct Field {
98        /// Attributes tagged on the field.
99        pub attrs: Vec<Attribute>,
100
101        /// Visibility of the field.
102        pub vis: Visibility,
103
104        /// Name of the field, if any.
105        ///
106        /// Fields of tuple structs have no names.
107        pub ident: Option<Ident>,
108
109        pub colon_token: Option<Token![:]>,
110
111        /// Type of the field.
112        pub ty: Type,
113    }
114}
115
116ast_enum_of_structs! {
117    /// The visibility level of an item: inherited or `pub` or
118    /// `pub(restricted)`.
119    ///
120    /// *This type is available if Syn is built with the `"derive"` or `"full"`
121    /// feature.*
122    ///
123    /// # Syntax tree enum
124    ///
125    /// This type is a [syntax tree enum].
126    ///
127    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
128    pub enum Visibility {
129        /// A public visibility level: `pub`.
130        ///
131        /// *This type is available if Syn is built with the `"derive"` or
132        /// `"full"` feature.*
133        pub Public(VisPublic {
134            pub pub_token: Token![pub],
135        }),
136
137        /// A crate-level visibility: `pub(crate)`.
138        ///
139        /// *This type is available if Syn is built with the `"derive"` or
140        /// `"full"` feature.*
141        pub Crate(VisCrate {
142            pub pub_token: Token![pub],
143            pub paren_token: token::Paren,
144            pub crate_token: Token![crate],
145        }),
146
147        /// A visibility level restricted to some path: `pub(self)` or
148        /// `pub(super)` or `pub(in some::module)`.
149        ///
150        /// *This type is available if Syn is built with the `"derive"` or
151        /// `"full"` feature.*
152        pub Restricted(VisRestricted {
153            pub pub_token: Token![pub],
154            pub paren_token: token::Paren,
155            pub in_token: Option<Token![in]>,
156            pub path: Box<Path>,
157        }),
158
159        /// An inherited visibility, which usually means private.
160        pub Inherited,
161    }
162}
163
164#[cfg(feature = "parsing")]
165pub mod parsing {
166    use super::*;
167
168    use synom::Synom;
169
170    impl Synom for Variant {
171        named!(parse -> Self, do_parse!(
172            attrs: many0!(Attribute::parse_outer) >>
173            id: syn!(Ident) >>
174            fields: alt!(
175                syn!(FieldsNamed) => { Fields::Named }
176                |
177                syn!(FieldsUnnamed) => { Fields::Unnamed }
178                |
179                epsilon!() => { |_| Fields::Unit }
180            ) >>
181            disr: option!(tuple!(punct!(=), syn!(Expr))) >>
182            (Variant {
183                ident: id,
184                attrs: attrs,
185                fields: fields,
186                discriminant: disr,
187            })
188        ));
189
190        fn description() -> Option<&'static str> {
191            Some("enum variant")
192        }
193    }
194
195    impl Synom for FieldsNamed {
196        named!(parse -> Self, map!(
197            braces!(call!(Punctuated::parse_terminated_with, Field::parse_named)),
198            |(brace, fields)| FieldsNamed {
199                brace_token: brace,
200                named: fields,
201            }
202        ));
203
204        fn description() -> Option<&'static str> {
205            Some("named fields in a struct or struct variant")
206        }
207    }
208
209    impl Synom for FieldsUnnamed {
210        named!(parse -> Self, map!(
211            parens!(call!(Punctuated::parse_terminated_with, Field::parse_unnamed)),
212            |(paren, fields)| FieldsUnnamed {
213                paren_token: paren,
214                unnamed: fields,
215            }
216        ));
217
218        fn description() -> Option<&'static str> {
219            Some("unnamed fields in a tuple struct or tuple variant")
220        }
221    }
222
223    impl Field {
224        named!(pub parse_named -> Self, do_parse!(
225            attrs: many0!(Attribute::parse_outer) >>
226            vis: syn!(Visibility) >>
227            id: syn!(Ident) >>
228            colon: punct!(:) >>
229            ty: syn!(Type) >>
230            (Field {
231                ident: Some(id),
232                vis: vis,
233                attrs: attrs,
234                ty: ty,
235                colon_token: Some(colon),
236            })
237        ));
238
239        named!(pub parse_unnamed -> Self, do_parse!(
240            attrs: many0!(Attribute::parse_outer) >>
241            vis: syn!(Visibility) >>
242            ty: syn!(Type) >>
243            (Field {
244                ident: None,
245                colon_token: None,
246                vis: vis,
247                attrs: attrs,
248                ty: ty,
249            })
250        ));
251    }
252
253    impl Synom for Visibility {
254        named!(parse -> Self, alt!(
255            do_parse!(
256                pub_token: keyword!(pub) >>
257                other: parens!(keyword!(crate)) >>
258                (Visibility::Crate(VisCrate {
259                    pub_token: pub_token,
260                    paren_token: other.0,
261                    crate_token: other.1,
262                }))
263            )
264            |
265            do_parse!(
266                pub_token: keyword!(pub) >>
267                other: parens!(keyword!(self)) >>
268                (Visibility::Restricted(VisRestricted {
269                    pub_token: pub_token,
270                    paren_token: other.0,
271                    in_token: None,
272                    path: Box::new(other.1.into()),
273                }))
274            )
275            |
276            do_parse!(
277                pub_token: keyword!(pub) >>
278                other: parens!(keyword!(super)) >>
279                (Visibility::Restricted(VisRestricted {
280                    pub_token: pub_token,
281                    paren_token: other.0,
282                    in_token: None,
283                    path: Box::new(other.1.into()),
284                }))
285            )
286            |
287            do_parse!(
288                pub_token: keyword!(pub) >>
289                other: parens!(do_parse!(
290                    in_tok: keyword!(in) >>
291                    restricted: call!(Path::parse_mod_style) >>
292                    (in_tok, restricted)
293                )) >>
294                (Visibility::Restricted(VisRestricted {
295                    pub_token: pub_token,
296                    paren_token: other.0,
297                    in_token: Some((other.1).0),
298                    path: Box::new((other.1).1),
299                }))
300            )
301            |
302            keyword!(pub) => { |tok| {
303                Visibility::Public(VisPublic {
304                    pub_token: tok,
305                })
306            } }
307            |
308            epsilon!() => { |_| Visibility::Inherited }
309        ));
310
311        fn description() -> Option<&'static str> {
312            Some("visibility qualifier such as `pub`")
313        }
314    }
315}
316
317#[cfg(feature = "printing")]
318mod printing {
319    use super::*;
320    use quote::{ToTokens, Tokens};
321
322    impl ToTokens for Variant {
323        fn to_tokens(&self, tokens: &mut Tokens) {
324            tokens.append_all(&self.attrs);
325            self.ident.to_tokens(tokens);
326            self.fields.to_tokens(tokens);
327            if let Some((ref eq_token, ref disc)) = self.discriminant {
328                eq_token.to_tokens(tokens);
329                disc.to_tokens(tokens);
330            }
331        }
332    }
333
334    impl ToTokens for FieldsNamed {
335        fn to_tokens(&self, tokens: &mut Tokens) {
336            self.brace_token.surround(tokens, |tokens| {
337                self.named.to_tokens(tokens);
338            });
339        }
340    }
341
342    impl ToTokens for FieldsUnnamed {
343        fn to_tokens(&self, tokens: &mut Tokens) {
344            self.paren_token.surround(tokens, |tokens| {
345                self.unnamed.to_tokens(tokens);
346            });
347        }
348    }
349
350    impl ToTokens for Field {
351        fn to_tokens(&self, tokens: &mut Tokens) {
352            tokens.append_all(&self.attrs);
353            self.vis.to_tokens(tokens);
354            if let Some(ref ident) = self.ident {
355                ident.to_tokens(tokens);
356                TokensOrDefault(&self.colon_token).to_tokens(tokens);
357            }
358            self.ty.to_tokens(tokens);
359        }
360    }
361
362    impl ToTokens for VisPublic {
363        fn to_tokens(&self, tokens: &mut Tokens) {
364            self.pub_token.to_tokens(tokens)
365        }
366    }
367
368    impl ToTokens for VisCrate {
369        fn to_tokens(&self, tokens: &mut Tokens) {
370            self.pub_token.to_tokens(tokens);
371            self.paren_token.surround(tokens, |tokens| {
372                self.crate_token.to_tokens(tokens);
373            })
374        }
375    }
376
377    impl ToTokens for VisRestricted {
378        fn to_tokens(&self, tokens: &mut Tokens) {
379            self.pub_token.to_tokens(tokens);
380            self.paren_token.surround(tokens, |tokens| {
381                // XXX: If we have a path which is not "self" or "super",
382                // automatically add the "in" token.
383                self.in_token.to_tokens(tokens);
384                self.path.to_tokens(tokens);
385            });
386        }
387    }
388}