blob: 08fd1e32406ec12fc20ee91e30d31aa201ee4703 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// 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
David Tolnayf38cdf62016-09-23 19:07:09 -07009use super::*;
David Tolnayf2cfd722017-12-31 18:02:51 -050010use punctuated::Punctuated;
David Tolnayf38cdf62016-09-23 19:07:09 -070011
Alex Crichton62a0a592017-05-22 13:58:53 -070012ast_struct! {
13 /// An enum variant.
14 pub struct Variant {
Alex Crichton62a0a592017-05-22 13:58:53 -070015 /// Attributes tagged on the variant.
16 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050017
David Tolnay4a3f59a2017-12-28 21:21:12 -050018 /// Name of the variant.
19 pub ident: Ident,
20
David Tolnaye3d41b72017-12-31 15:24:00 -050021 /// Content stored in the variant.
22 pub fields: Fields,
Clar Charrd22b5702017-03-10 15:24:56 -050023
Alex Crichton62a0a592017-05-22 13:58:53 -070024 /// Explicit discriminant, e.g. `Foo = 1`
David Tolnaye67902a2017-12-28 22:12:00 -050025 pub discriminant: Option<(Token![=], Expr)>,
Alex Crichton62a0a592017-05-22 13:58:53 -070026 }
David Tolnayf38cdf62016-09-23 19:07:09 -070027}
28
David Tolnaye3d41b72017-12-31 15:24:00 -050029ast_enum_of_structs! {
Alex Crichton62a0a592017-05-22 13:58:53 -070030 /// Data stored within an enum variant or struct.
David Tolnaye3d41b72017-12-31 15:24:00 -050031 pub enum Fields {
32 /// Named fields of a struct or struct variant such as `Point { x: f64,
33 /// y: f64 }`.
34 pub Named(FieldsNamed {
35 pub brace_token: token::Brace,
David Tolnaybdafb102018-01-01 19:39:10 -080036 pub named: Punctuated<Field, Token![,]>,
David Tolnaye3d41b72017-12-31 15:24:00 -050037 }),
Clar Charrd22b5702017-03-10 15:24:56 -050038
David Tolnaye3d41b72017-12-31 15:24:00 -050039 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
40 pub Unnamed(FieldsUnnamed {
41 pub paren_token: token::Paren,
David Tolnaybdafb102018-01-01 19:39:10 -080042 pub unnamed: Punctuated<Field, Token![,]>,
David Tolnaye3d41b72017-12-31 15:24:00 -050043 }),
Clar Charrd22b5702017-03-10 15:24:56 -050044
David Tolnaye3d41b72017-12-31 15:24:00 -050045 /// Unit struct or unit variant such as `None`.
46 pub Unit,
Alex Crichton62a0a592017-05-22 13:58:53 -070047 }
David Tolnayf38cdf62016-09-23 19:07:09 -070048}
49
Alex Crichton62a0a592017-05-22 13:58:53 -070050ast_struct! {
51 /// A field of a struct or enum variant.
52 pub struct Field {
David Tolnay4a3f59a2017-12-28 21:21:12 -050053 /// Attributes tagged on the field.
54 pub attrs: Vec<Attribute>,
55
56 /// Visibility of the field.
57 pub vis: Visibility,
58
Alex Crichton62a0a592017-05-22 13:58:53 -070059 /// Name of the field, if any.
60 ///
61 /// Fields of tuple structs have no names.
62 pub ident: Option<Ident>,
Clar Charrd22b5702017-03-10 15:24:56 -050063
David Tolnay4a3f59a2017-12-28 21:21:12 -050064 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -050065
Alex Crichton62a0a592017-05-22 13:58:53 -070066 /// Type of the field.
David Tolnayfd6bf5c2017-11-12 09:41:14 -080067 pub ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -070068 }
David Tolnayf38cdf62016-09-23 19:07:09 -070069}
70
Alex Crichtonccbb45d2017-05-23 10:58:24 -070071ast_enum_of_structs! {
Alex Crichton62a0a592017-05-22 13:58:53 -070072 /// Visibility level of an item.
73 pub enum Visibility {
74 /// Public, i.e. `pub`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070075 pub Public(VisPublic {
David Tolnayf8db7ba2017-11-11 22:52:16 -080076 pub pub_token: Token![pub],
Alex Crichtonccbb45d2017-05-23 10:58:24 -070077 }),
Clar Charrd22b5702017-03-10 15:24:56 -050078
Alex Crichton62a0a592017-05-22 13:58:53 -070079 /// Crate-visible, i.e. `pub(crate)`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070080 pub Crate(VisCrate {
David Tolnayf8db7ba2017-11-11 22:52:16 -080081 pub pub_token: Token![pub],
David Tolnay32954ef2017-12-26 22:43:16 -050082 pub paren_token: token::Paren,
David Tolnayf8db7ba2017-11-11 22:52:16 -080083 pub crate_token: Token![crate],
Alex Crichtonccbb45d2017-05-23 10:58:24 -070084 }),
Clar Charrd22b5702017-03-10 15:24:56 -050085
Alex Crichton62a0a592017-05-22 13:58:53 -070086 /// Restricted, e.g. `pub(self)` or `pub(super)` or `pub(in some::module)`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070087 pub Restricted(VisRestricted {
David Tolnayf8db7ba2017-11-11 22:52:16 -080088 pub pub_token: Token![pub],
David Tolnay32954ef2017-12-26 22:43:16 -050089 pub paren_token: token::Paren,
David Tolnayf8db7ba2017-11-11 22:52:16 -080090 pub in_token: Option<Token![in]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070091 pub path: Box<Path>,
92 }),
Clar Charrd22b5702017-03-10 15:24:56 -050093
Alex Crichton62a0a592017-05-22 13:58:53 -070094 /// Inherited, i.e. private.
David Tolnayfcfb9002017-12-28 22:04:29 -050095 pub Inherited,
Alex Crichton62a0a592017-05-22 13:58:53 -070096 }
David Tolnayf38cdf62016-09-23 19:07:09 -070097}
98
David Tolnayf38cdf62016-09-23 19:07:09 -070099#[cfg(feature = "parsing")]
100pub mod parsing {
101 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -0700102
Michael Layzell92639a52017-06-01 00:07:44 -0400103 use synom::Synom;
David Tolnayf38cdf62016-09-23 19:07:09 -0700104
David Tolnaye3d41b72017-12-31 15:24:00 -0500105 impl Synom for Variant {
106 named!(parse -> Self, do_parse!(
107 attrs: many0!(Attribute::parse_outer) >>
108 id: syn!(Ident) >>
109 fields: alt!(
110 syn!(FieldsNamed) => { Fields::Named }
111 |
112 syn!(FieldsUnnamed) => { Fields::Unnamed }
113 |
114 epsilon!() => { |_| Fields::Unit }
115 ) >>
116 disr: option!(tuple!(punct!(=), syn!(Expr))) >>
117 (Variant {
118 ident: id,
119 attrs: attrs,
120 fields: fields,
121 discriminant: disr,
122 })
123 ));
124
125 fn description() -> Option<&'static str> {
126 Some("enum variant")
127 }
128 }
129
130 impl Synom for FieldsNamed {
131 named!(parse -> Self, map!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500132 braces!(call!(Punctuated::parse_terminated_with, Field::parse_named)),
David Tolnaye3d41b72017-12-31 15:24:00 -0500133 |(brace, fields)| FieldsNamed {
134 brace_token: brace,
David Tolnaybdafb102018-01-01 19:39:10 -0800135 named: fields,
David Tolnaye3d41b72017-12-31 15:24:00 -0500136 }
137 ));
138 }
139
140 impl Synom for FieldsUnnamed {
141 named!(parse -> Self, map!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500142 parens!(call!(Punctuated::parse_terminated_with, Field::parse_unnamed)),
David Tolnaye3d41b72017-12-31 15:24:00 -0500143 |(paren, fields)| FieldsUnnamed {
144 paren_token: paren,
David Tolnaybdafb102018-01-01 19:39:10 -0800145 unnamed: fields,
David Tolnaye3d41b72017-12-31 15:24:00 -0500146 }
147 ));
148 }
149
Alex Crichton954046c2017-05-30 21:49:42 -0700150 impl Field {
David Tolnaye3d41b72017-12-31 15:24:00 -0500151 named!(pub parse_named -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500152 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400153 vis: syn!(Visibility) >>
154 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800155 colon: punct!(:) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800156 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400157 (Field {
158 ident: Some(id),
159 vis: vis,
160 attrs: attrs,
161 ty: ty,
162 colon_token: Some(colon),
163 })
164 ));
David Tolnayf38cdf62016-09-23 19:07:09 -0700165
David Tolnaye3d41b72017-12-31 15:24:00 -0500166 named!(pub parse_unnamed -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500167 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400168 vis: syn!(Visibility) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800169 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400170 (Field {
171 ident: None,
172 colon_token: None,
173 vis: vis,
174 attrs: attrs,
175 ty: ty,
176 })
177 ));
Michael Layzell416724e2017-05-24 21:12:34 -0400178 }
179
Alex Crichton954046c2017-05-30 21:49:42 -0700180 impl Synom for Visibility {
Michael Layzell92639a52017-06-01 00:07:44 -0400181 named!(parse -> Self, alt!(
182 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800183 pub_token: keyword!(pub) >>
184 other: parens!(keyword!(crate)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400185 (Visibility::Crate(VisCrate {
Michael Layzell92639a52017-06-01 00:07:44 -0400186 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500187 paren_token: other.0,
188 crate_token: other.1,
Michael Layzell92639a52017-06-01 00:07:44 -0400189 }))
190 )
191 |
192 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800193 pub_token: keyword!(pub) >>
194 other: parens!(keyword!(self)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400195 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400196 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500197 paren_token: other.0,
198 in_token: None,
199 path: Box::new(other.1.into()),
Michael Layzell92639a52017-06-01 00:07:44 -0400200 }))
201 )
202 |
203 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800204 pub_token: keyword!(pub) >>
205 other: parens!(keyword!(super)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400206 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400207 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500208 paren_token: other.0,
209 in_token: None,
210 path: Box::new(other.1.into()),
Michael Layzell92639a52017-06-01 00:07:44 -0400211 }))
212 )
213 |
214 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800215 pub_token: keyword!(pub) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400216 other: parens!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800217 in_tok: keyword!(in) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400218 restricted: call!(Path::parse_mod_style) >>
219 (in_tok, restricted)
220 )) >>
221 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400222 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500223 paren_token: other.0,
224 in_token: Some((other.1).0),
225 path: Box::new((other.1).1),
Michael Layzell92639a52017-06-01 00:07:44 -0400226 }))
227 )
228 |
David Tolnayf8db7ba2017-11-11 22:52:16 -0800229 keyword!(pub) => { |tok| {
Michael Layzell92639a52017-06-01 00:07:44 -0400230 Visibility::Public(VisPublic {
231 pub_token: tok,
232 })
233 } }
234 |
David Tolnayfcfb9002017-12-28 22:04:29 -0500235 epsilon!() => { |_| Visibility::Inherited }
Michael Layzell92639a52017-06-01 00:07:44 -0400236 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800237
238 fn description() -> Option<&'static str> {
239 Some("visibility qualifier, e.g. `pub`")
240 }
Alex Crichton954046c2017-05-30 21:49:42 -0700241 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700242}
243
244#[cfg(feature = "printing")]
245mod printing {
246 use super::*;
David Tolnay51382052017-12-27 13:46:21 -0500247 use quote::{ToTokens, Tokens};
David Tolnayf38cdf62016-09-23 19:07:09 -0700248
249 impl ToTokens for Variant {
250 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700251 tokens.append_all(&self.attrs);
David Tolnayf38cdf62016-09-23 19:07:09 -0700252 self.ident.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500253 self.fields.to_tokens(tokens);
David Tolnaye67902a2017-12-28 22:12:00 -0500254 if let Some((ref eq_token, ref disc)) = self.discriminant {
255 eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400256 disc.to_tokens(tokens);
257 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700258 }
259 }
260
David Tolnaye3d41b72017-12-31 15:24:00 -0500261 impl ToTokens for FieldsNamed {
David Tolnayf38cdf62016-09-23 19:07:09 -0700262 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye3d41b72017-12-31 15:24:00 -0500263 self.brace_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800264 self.named.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500265 });
266 }
267 }
268
269 impl ToTokens for FieldsUnnamed {
270 fn to_tokens(&self, tokens: &mut Tokens) {
271 self.paren_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800272 self.unnamed.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500273 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700274 }
275 }
276
277 impl ToTokens for Field {
278 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700279 tokens.append_all(&self.attrs);
David Tolnay47a877c2016-10-01 16:50:55 -0700280 self.vis.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400281 if let Some(ref ident) = self.ident {
282 ident.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700283 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400284 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700285 self.ty.to_tokens(tokens);
286 }
287 }
288
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700289 impl ToTokens for VisPublic {
David Tolnay47a877c2016-10-01 16:50:55 -0700290 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700291 self.pub_token.to_tokens(tokens)
292 }
293 }
Arnaviond32b2942017-04-29 17:18:02 -0700294
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700295 impl ToTokens for VisCrate {
296 fn to_tokens(&self, tokens: &mut Tokens) {
297 self.pub_token.to_tokens(tokens);
298 self.paren_token.surround(tokens, |tokens| {
299 self.crate_token.to_tokens(tokens);
300 })
301 }
302 }
Arnaviond32b2942017-04-29 17:18:02 -0700303
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700304 impl ToTokens for VisRestricted {
305 fn to_tokens(&self, tokens: &mut Tokens) {
306 self.pub_token.to_tokens(tokens);
307 self.paren_token.surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400308 // XXX: If we have a path which is not "self" or "super",
309 // automatically add the "in" token.
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700310 self.in_token.to_tokens(tokens);
311 self.path.to_tokens(tokens);
312 });
313 }
314 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700315}