blob: f9152f2178edebc67d9595fd918f4a3c29ca6ece [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
David Tolnay05658502018-01-07 09:56:37 -080024 /// Explicit discriminant: `Variant = 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! {
David Tolnay05658502018-01-07 09:56:37 -080072 /// The visibility level of an item: inherited or `pub` or
73 /// `pub(restricted)`.
Alex Crichton62a0a592017-05-22 13:58:53 -070074 pub enum Visibility {
David Tolnay05658502018-01-07 09:56:37 -080075 /// A public visibility level: `pub`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070076 pub Public(VisPublic {
David Tolnayf8db7ba2017-11-11 22:52:16 -080077 pub pub_token: Token![pub],
Alex Crichtonccbb45d2017-05-23 10:58:24 -070078 }),
Clar Charrd22b5702017-03-10 15:24:56 -050079
David Tolnay05658502018-01-07 09:56:37 -080080 /// A crate-level visibility: `pub(crate)`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070081 pub Crate(VisCrate {
David Tolnayf8db7ba2017-11-11 22:52:16 -080082 pub pub_token: Token![pub],
David Tolnay32954ef2017-12-26 22:43:16 -050083 pub paren_token: token::Paren,
David Tolnayf8db7ba2017-11-11 22:52:16 -080084 pub crate_token: Token![crate],
Alex Crichtonccbb45d2017-05-23 10:58:24 -070085 }),
Clar Charrd22b5702017-03-10 15:24:56 -050086
David Tolnay05658502018-01-07 09:56:37 -080087 /// A visibility level restricted to some path: `pub(self)` or
88 /// `pub(super)` or `pub(in some::module)`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070089 pub Restricted(VisRestricted {
David Tolnayf8db7ba2017-11-11 22:52:16 -080090 pub pub_token: Token![pub],
David Tolnay32954ef2017-12-26 22:43:16 -050091 pub paren_token: token::Paren,
David Tolnayf8db7ba2017-11-11 22:52:16 -080092 pub in_token: Option<Token![in]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070093 pub path: Box<Path>,
94 }),
Clar Charrd22b5702017-03-10 15:24:56 -050095
David Tolnay05658502018-01-07 09:56:37 -080096 /// An inherited visibility, which usually means private.
David Tolnayfcfb9002017-12-28 22:04:29 -050097 pub Inherited,
Alex Crichton62a0a592017-05-22 13:58:53 -070098 }
David Tolnayf38cdf62016-09-23 19:07:09 -070099}
100
David Tolnayf38cdf62016-09-23 19:07:09 -0700101#[cfg(feature = "parsing")]
102pub mod parsing {
103 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -0700104
Michael Layzell92639a52017-06-01 00:07:44 -0400105 use synom::Synom;
David Tolnayf38cdf62016-09-23 19:07:09 -0700106
David Tolnaye3d41b72017-12-31 15:24:00 -0500107 impl Synom for Variant {
108 named!(parse -> Self, do_parse!(
109 attrs: many0!(Attribute::parse_outer) >>
110 id: syn!(Ident) >>
111 fields: alt!(
112 syn!(FieldsNamed) => { Fields::Named }
113 |
114 syn!(FieldsUnnamed) => { Fields::Unnamed }
115 |
116 epsilon!() => { |_| Fields::Unit }
117 ) >>
118 disr: option!(tuple!(punct!(=), syn!(Expr))) >>
119 (Variant {
120 ident: id,
121 attrs: attrs,
122 fields: fields,
123 discriminant: disr,
124 })
125 ));
126
127 fn description() -> Option<&'static str> {
128 Some("enum variant")
129 }
130 }
131
132 impl Synom for FieldsNamed {
133 named!(parse -> Self, map!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500134 braces!(call!(Punctuated::parse_terminated_with, Field::parse_named)),
David Tolnaye3d41b72017-12-31 15:24:00 -0500135 |(brace, fields)| FieldsNamed {
136 brace_token: brace,
David Tolnaybdafb102018-01-01 19:39:10 -0800137 named: fields,
David Tolnaye3d41b72017-12-31 15:24:00 -0500138 }
139 ));
140 }
141
142 impl Synom for FieldsUnnamed {
143 named!(parse -> Self, map!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500144 parens!(call!(Punctuated::parse_terminated_with, Field::parse_unnamed)),
David Tolnaye3d41b72017-12-31 15:24:00 -0500145 |(paren, fields)| FieldsUnnamed {
146 paren_token: paren,
David Tolnaybdafb102018-01-01 19:39:10 -0800147 unnamed: fields,
David Tolnaye3d41b72017-12-31 15:24:00 -0500148 }
149 ));
150 }
151
Alex Crichton954046c2017-05-30 21:49:42 -0700152 impl Field {
David Tolnaye3d41b72017-12-31 15:24:00 -0500153 named!(pub parse_named -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500154 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400155 vis: syn!(Visibility) >>
156 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800157 colon: punct!(:) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800158 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400159 (Field {
160 ident: Some(id),
161 vis: vis,
162 attrs: attrs,
163 ty: ty,
164 colon_token: Some(colon),
165 })
166 ));
David Tolnayf38cdf62016-09-23 19:07:09 -0700167
David Tolnaye3d41b72017-12-31 15:24:00 -0500168 named!(pub parse_unnamed -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500169 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400170 vis: syn!(Visibility) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800171 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400172 (Field {
173 ident: None,
174 colon_token: None,
175 vis: vis,
176 attrs: attrs,
177 ty: ty,
178 })
179 ));
Michael Layzell416724e2017-05-24 21:12:34 -0400180 }
181
Alex Crichton954046c2017-05-30 21:49:42 -0700182 impl Synom for Visibility {
Michael Layzell92639a52017-06-01 00:07:44 -0400183 named!(parse -> Self, alt!(
184 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800185 pub_token: keyword!(pub) >>
186 other: parens!(keyword!(crate)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400187 (Visibility::Crate(VisCrate {
Michael Layzell92639a52017-06-01 00:07:44 -0400188 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500189 paren_token: other.0,
190 crate_token: other.1,
Michael Layzell92639a52017-06-01 00:07:44 -0400191 }))
192 )
193 |
194 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800195 pub_token: keyword!(pub) >>
196 other: parens!(keyword!(self)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400197 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400198 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500199 paren_token: other.0,
200 in_token: None,
201 path: Box::new(other.1.into()),
Michael Layzell92639a52017-06-01 00:07:44 -0400202 }))
203 )
204 |
205 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800206 pub_token: keyword!(pub) >>
207 other: parens!(keyword!(super)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400208 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400209 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500210 paren_token: other.0,
211 in_token: None,
212 path: Box::new(other.1.into()),
Michael Layzell92639a52017-06-01 00:07:44 -0400213 }))
214 )
215 |
216 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800217 pub_token: keyword!(pub) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400218 other: parens!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800219 in_tok: keyword!(in) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400220 restricted: call!(Path::parse_mod_style) >>
221 (in_tok, restricted)
222 )) >>
223 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400224 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500225 paren_token: other.0,
226 in_token: Some((other.1).0),
227 path: Box::new((other.1).1),
Michael Layzell92639a52017-06-01 00:07:44 -0400228 }))
229 )
230 |
David Tolnayf8db7ba2017-11-11 22:52:16 -0800231 keyword!(pub) => { |tok| {
Michael Layzell92639a52017-06-01 00:07:44 -0400232 Visibility::Public(VisPublic {
233 pub_token: tok,
234 })
235 } }
236 |
David Tolnayfcfb9002017-12-28 22:04:29 -0500237 epsilon!() => { |_| Visibility::Inherited }
Michael Layzell92639a52017-06-01 00:07:44 -0400238 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800239
240 fn description() -> Option<&'static str> {
David Tolnay05658502018-01-07 09:56:37 -0800241 Some("visibility qualifier such as `pub`")
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800242 }
Alex Crichton954046c2017-05-30 21:49:42 -0700243 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700244}
245
246#[cfg(feature = "printing")]
247mod printing {
248 use super::*;
David Tolnay51382052017-12-27 13:46:21 -0500249 use quote::{ToTokens, Tokens};
David Tolnayf38cdf62016-09-23 19:07:09 -0700250
251 impl ToTokens for Variant {
252 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700253 tokens.append_all(&self.attrs);
David Tolnayf38cdf62016-09-23 19:07:09 -0700254 self.ident.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500255 self.fields.to_tokens(tokens);
David Tolnaye67902a2017-12-28 22:12:00 -0500256 if let Some((ref eq_token, ref disc)) = self.discriminant {
257 eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400258 disc.to_tokens(tokens);
259 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700260 }
261 }
262
David Tolnaye3d41b72017-12-31 15:24:00 -0500263 impl ToTokens for FieldsNamed {
David Tolnayf38cdf62016-09-23 19:07:09 -0700264 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye3d41b72017-12-31 15:24:00 -0500265 self.brace_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800266 self.named.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500267 });
268 }
269 }
270
271 impl ToTokens for FieldsUnnamed {
272 fn to_tokens(&self, tokens: &mut Tokens) {
273 self.paren_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800274 self.unnamed.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500275 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700276 }
277 }
278
279 impl ToTokens for Field {
280 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700281 tokens.append_all(&self.attrs);
David Tolnay47a877c2016-10-01 16:50:55 -0700282 self.vis.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400283 if let Some(ref ident) = self.ident {
284 ident.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700285 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400286 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700287 self.ty.to_tokens(tokens);
288 }
289 }
290
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700291 impl ToTokens for VisPublic {
David Tolnay47a877c2016-10-01 16:50:55 -0700292 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700293 self.pub_token.to_tokens(tokens)
294 }
295 }
Arnaviond32b2942017-04-29 17:18:02 -0700296
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700297 impl ToTokens for VisCrate {
298 fn to_tokens(&self, tokens: &mut Tokens) {
299 self.pub_token.to_tokens(tokens);
300 self.paren_token.surround(tokens, |tokens| {
301 self.crate_token.to_tokens(tokens);
302 })
303 }
304 }
Arnaviond32b2942017-04-29 17:18:02 -0700305
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700306 impl ToTokens for VisRestricted {
307 fn to_tokens(&self, tokens: &mut Tokens) {
308 self.pub_token.to_tokens(tokens);
309 self.paren_token.surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400310 // XXX: If we have a path which is not "self" or "super",
311 // automatically add the "in" token.
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700312 self.in_token.to_tokens(tokens);
313 self.path.to_tokens(tokens);
314 });
315 }
316 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700317}