blob: b6199a7b0179bda138ee815c8fe9308cf144346b [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.
David Tolnay461d98e2018-01-07 11:07:19 -080014 ///
15 /// *This type is available if Syn is built with the `"derive"` or `"full"`
16 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -070017 pub struct Variant {
Alex Crichton62a0a592017-05-22 13:58:53 -070018 /// Attributes tagged on the variant.
19 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050020
David Tolnay4a3f59a2017-12-28 21:21:12 -050021 /// Name of the variant.
22 pub ident: Ident,
23
David Tolnaye3d41b72017-12-31 15:24:00 -050024 /// Content stored in the variant.
25 pub fields: Fields,
Clar Charrd22b5702017-03-10 15:24:56 -050026
David Tolnay05658502018-01-07 09:56:37 -080027 /// Explicit discriminant: `Variant = 1`
David Tolnaye67902a2017-12-28 22:12:00 -050028 pub discriminant: Option<(Token![=], Expr)>,
Alex Crichton62a0a592017-05-22 13:58:53 -070029 }
David Tolnayf38cdf62016-09-23 19:07:09 -070030}
31
David Tolnaye3d41b72017-12-31 15:24:00 -050032ast_enum_of_structs! {
Alex Crichton62a0a592017-05-22 13:58:53 -070033 /// Data stored within an enum variant or struct.
David Tolnay614a0142018-01-07 10:25:43 -080034 ///
David Tolnay461d98e2018-01-07 11:07:19 -080035 /// *This type is available if Syn is built with the `"derive"` or `"full"`
36 /// feature.*
37 ///
David Tolnay614a0142018-01-07 10:25:43 -080038 /// # Syntax tree enum
39 ///
40 /// This type is a [syntax tree enum].
41 ///
42 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
David Tolnaye3d41b72017-12-31 15:24:00 -050043 pub enum Fields {
44 /// Named fields of a struct or struct variant such as `Point { x: f64,
45 /// y: f64 }`.
David Tolnay461d98e2018-01-07 11:07:19 -080046 ///
47 /// *This type is available if Syn is built with the `"derive"` or
48 /// `"full"` feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050049 pub Named(FieldsNamed {
50 pub brace_token: token::Brace,
David Tolnaybdafb102018-01-01 19:39:10 -080051 pub named: Punctuated<Field, Token![,]>,
David Tolnaye3d41b72017-12-31 15:24:00 -050052 }),
Clar Charrd22b5702017-03-10 15:24:56 -050053
David Tolnaye3d41b72017-12-31 15:24:00 -050054 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
David Tolnay461d98e2018-01-07 11:07:19 -080055 ///
56 /// *This type is available if Syn is built with the `"derive"` or
57 /// `"full"` feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050058 pub Unnamed(FieldsUnnamed {
59 pub paren_token: token::Paren,
David Tolnaybdafb102018-01-01 19:39:10 -080060 pub unnamed: Punctuated<Field, Token![,]>,
David Tolnaye3d41b72017-12-31 15:24:00 -050061 }),
Clar Charrd22b5702017-03-10 15:24:56 -050062
David Tolnaye3d41b72017-12-31 15:24:00 -050063 /// Unit struct or unit variant such as `None`.
64 pub Unit,
Alex Crichton62a0a592017-05-22 13:58:53 -070065 }
David Tolnayf38cdf62016-09-23 19:07:09 -070066}
67
Nika Layzell5680dcc2018-01-16 15:14:27 -050068/// The `Iterator` type returned by [`Fields::iter`].
69///
70/// [`Fields::iter`]: struct.Fields.html#method.iter
71///
72/// *This type is available if Syn is build with the `"derive"` or `"full"`
73/// feature.*
74pub struct FieldsIter<'a>(Option<punctuated::Iter<'a, Field, Token![,]>>);
75
76impl<'a> Iterator for FieldsIter<'a> {
77 type Item = &'a Field;
78 fn next(&mut self) -> Option<&'a Field> {
79 match self.0 {
80 Some(ref mut i) => i.next(),
81 None => None,
82 }
83 }
84}
85
86impl Fields {
87 /// Get an iterator over the [`Field`] items in this object. This iterator
88 /// can be used to iterate over a named or unnamed struct or variant's
89 /// fields uniformly.
90 ///
91 /// [`Field`]: struct.Field.html
92 pub fn iter(&self) -> FieldsIter {
93 match *self {
94 Fields::Unit => FieldsIter(None),
95 Fields::Named(ref f) => FieldsIter(Some(f.named.iter())),
96 Fields::Unnamed(ref f) => FieldsIter(Some(f.unnamed.iter())),
97 }
98 }
99}
100
101impl<'a> IntoIterator for &'a Fields {
102 type Item = &'a Field;
103 type IntoIter = FieldsIter<'a>;
104
105 fn into_iter(self) -> Self::IntoIter {
106 self.iter()
107 }
108}
109
Alex Crichton62a0a592017-05-22 13:58:53 -0700110ast_struct! {
111 /// A field of a struct or enum variant.
David Tolnay461d98e2018-01-07 11:07:19 -0800112 ///
113 /// *This type is available if Syn is built with the `"derive"` or `"full"`
114 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700115 pub struct Field {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500116 /// Attributes tagged on the field.
117 pub attrs: Vec<Attribute>,
118
119 /// Visibility of the field.
120 pub vis: Visibility,
121
Alex Crichton62a0a592017-05-22 13:58:53 -0700122 /// Name of the field, if any.
123 ///
124 /// Fields of tuple structs have no names.
125 pub ident: Option<Ident>,
Clar Charrd22b5702017-03-10 15:24:56 -0500126
David Tolnay4a3f59a2017-12-28 21:21:12 -0500127 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500128
Alex Crichton62a0a592017-05-22 13:58:53 -0700129 /// Type of the field.
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800130 pub ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700131 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700132}
133
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700134ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800135 /// The visibility level of an item: inherited or `pub` or
136 /// `pub(restricted)`.
David Tolnay614a0142018-01-07 10:25:43 -0800137 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800138 /// *This type is available if Syn is built with the `"derive"` or `"full"`
139 /// feature.*
140 ///
David Tolnay614a0142018-01-07 10:25:43 -0800141 /// # Syntax tree enum
142 ///
143 /// This type is a [syntax tree enum].
144 ///
145 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700146 pub enum Visibility {
David Tolnay05658502018-01-07 09:56:37 -0800147 /// A public visibility level: `pub`.
David Tolnay461d98e2018-01-07 11:07:19 -0800148 ///
149 /// *This type is available if Syn is built with the `"derive"` or
150 /// `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700151 pub Public(VisPublic {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800152 pub pub_token: Token![pub],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700153 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500154
David Tolnay05658502018-01-07 09:56:37 -0800155 /// A crate-level visibility: `pub(crate)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800156 ///
157 /// *This type is available if Syn is built with the `"derive"` or
158 /// `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700159 pub Crate(VisCrate {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800160 pub pub_token: Token![pub],
David Tolnay32954ef2017-12-26 22:43:16 -0500161 pub paren_token: token::Paren,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800162 pub crate_token: Token![crate],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700163 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500164
David Tolnay05658502018-01-07 09:56:37 -0800165 /// A visibility level restricted to some path: `pub(self)` or
166 /// `pub(super)` or `pub(in some::module)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800167 ///
168 /// *This type is available if Syn is built with the `"derive"` or
169 /// `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700170 pub Restricted(VisRestricted {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800171 pub pub_token: Token![pub],
David Tolnay32954ef2017-12-26 22:43:16 -0500172 pub paren_token: token::Paren,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800173 pub in_token: Option<Token![in]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700174 pub path: Box<Path>,
175 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500176
David Tolnay05658502018-01-07 09:56:37 -0800177 /// An inherited visibility, which usually means private.
David Tolnayfcfb9002017-12-28 22:04:29 -0500178 pub Inherited,
Alex Crichton62a0a592017-05-22 13:58:53 -0700179 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700180}
181
David Tolnayf38cdf62016-09-23 19:07:09 -0700182#[cfg(feature = "parsing")]
183pub mod parsing {
184 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -0700185
Michael Layzell92639a52017-06-01 00:07:44 -0400186 use synom::Synom;
David Tolnayf38cdf62016-09-23 19:07:09 -0700187
David Tolnaye3d41b72017-12-31 15:24:00 -0500188 impl Synom for Variant {
189 named!(parse -> Self, do_parse!(
190 attrs: many0!(Attribute::parse_outer) >>
191 id: syn!(Ident) >>
192 fields: alt!(
193 syn!(FieldsNamed) => { Fields::Named }
194 |
195 syn!(FieldsUnnamed) => { Fields::Unnamed }
196 |
197 epsilon!() => { |_| Fields::Unit }
198 ) >>
199 disr: option!(tuple!(punct!(=), syn!(Expr))) >>
200 (Variant {
201 ident: id,
202 attrs: attrs,
203 fields: fields,
204 discriminant: disr,
205 })
206 ));
207
208 fn description() -> Option<&'static str> {
209 Some("enum variant")
210 }
211 }
212
213 impl Synom for FieldsNamed {
214 named!(parse -> Self, map!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500215 braces!(call!(Punctuated::parse_terminated_with, Field::parse_named)),
David Tolnaye3d41b72017-12-31 15:24:00 -0500216 |(brace, fields)| FieldsNamed {
217 brace_token: brace,
David Tolnaybdafb102018-01-01 19:39:10 -0800218 named: fields,
David Tolnaye3d41b72017-12-31 15:24:00 -0500219 }
220 ));
David Tolnay79777332018-01-07 10:04:42 -0800221
222 fn description() -> Option<&'static str> {
223 Some("named fields in a struct or struct variant")
224 }
David Tolnaye3d41b72017-12-31 15:24:00 -0500225 }
226
227 impl Synom for FieldsUnnamed {
228 named!(parse -> Self, map!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500229 parens!(call!(Punctuated::parse_terminated_with, Field::parse_unnamed)),
David Tolnaye3d41b72017-12-31 15:24:00 -0500230 |(paren, fields)| FieldsUnnamed {
231 paren_token: paren,
David Tolnaybdafb102018-01-01 19:39:10 -0800232 unnamed: fields,
David Tolnaye3d41b72017-12-31 15:24:00 -0500233 }
234 ));
David Tolnay79777332018-01-07 10:04:42 -0800235
236 fn description() -> Option<&'static str> {
237 Some("unnamed fields in a tuple struct or tuple variant")
238 }
David Tolnaye3d41b72017-12-31 15:24:00 -0500239 }
240
Alex Crichton954046c2017-05-30 21:49:42 -0700241 impl Field {
David Tolnaye3d41b72017-12-31 15:24:00 -0500242 named!(pub parse_named -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500243 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400244 vis: syn!(Visibility) >>
245 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800246 colon: punct!(:) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800247 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400248 (Field {
249 ident: Some(id),
250 vis: vis,
251 attrs: attrs,
252 ty: ty,
253 colon_token: Some(colon),
254 })
255 ));
David Tolnayf38cdf62016-09-23 19:07:09 -0700256
David Tolnaye3d41b72017-12-31 15:24:00 -0500257 named!(pub parse_unnamed -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500258 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400259 vis: syn!(Visibility) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800260 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400261 (Field {
262 ident: None,
263 colon_token: None,
264 vis: vis,
265 attrs: attrs,
266 ty: ty,
267 })
268 ));
Michael Layzell416724e2017-05-24 21:12:34 -0400269 }
270
Alex Crichton954046c2017-05-30 21:49:42 -0700271 impl Synom for Visibility {
Michael Layzell92639a52017-06-01 00:07:44 -0400272 named!(parse -> Self, alt!(
273 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800274 pub_token: keyword!(pub) >>
275 other: parens!(keyword!(crate)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400276 (Visibility::Crate(VisCrate {
Michael Layzell92639a52017-06-01 00:07:44 -0400277 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500278 paren_token: other.0,
279 crate_token: other.1,
Michael Layzell92639a52017-06-01 00:07:44 -0400280 }))
281 )
282 |
283 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800284 pub_token: keyword!(pub) >>
285 other: parens!(keyword!(self)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400286 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400287 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500288 paren_token: other.0,
289 in_token: None,
290 path: Box::new(other.1.into()),
Michael Layzell92639a52017-06-01 00:07:44 -0400291 }))
292 )
293 |
294 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800295 pub_token: keyword!(pub) >>
296 other: parens!(keyword!(super)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400297 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400298 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500299 paren_token: other.0,
300 in_token: None,
301 path: Box::new(other.1.into()),
Michael Layzell92639a52017-06-01 00:07:44 -0400302 }))
303 )
304 |
305 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800306 pub_token: keyword!(pub) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400307 other: parens!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800308 in_tok: keyword!(in) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400309 restricted: call!(Path::parse_mod_style) >>
310 (in_tok, restricted)
311 )) >>
312 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400313 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500314 paren_token: other.0,
315 in_token: Some((other.1).0),
316 path: Box::new((other.1).1),
Michael Layzell92639a52017-06-01 00:07:44 -0400317 }))
318 )
319 |
David Tolnayf8db7ba2017-11-11 22:52:16 -0800320 keyword!(pub) => { |tok| {
Michael Layzell92639a52017-06-01 00:07:44 -0400321 Visibility::Public(VisPublic {
322 pub_token: tok,
323 })
324 } }
325 |
David Tolnayfcfb9002017-12-28 22:04:29 -0500326 epsilon!() => { |_| Visibility::Inherited }
Michael Layzell92639a52017-06-01 00:07:44 -0400327 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800328
329 fn description() -> Option<&'static str> {
David Tolnay05658502018-01-07 09:56:37 -0800330 Some("visibility qualifier such as `pub`")
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800331 }
Alex Crichton954046c2017-05-30 21:49:42 -0700332 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700333}
334
335#[cfg(feature = "printing")]
336mod printing {
337 use super::*;
David Tolnay51382052017-12-27 13:46:21 -0500338 use quote::{ToTokens, Tokens};
David Tolnayf38cdf62016-09-23 19:07:09 -0700339
340 impl ToTokens for Variant {
341 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700342 tokens.append_all(&self.attrs);
David Tolnayf38cdf62016-09-23 19:07:09 -0700343 self.ident.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500344 self.fields.to_tokens(tokens);
David Tolnaye67902a2017-12-28 22:12:00 -0500345 if let Some((ref eq_token, ref disc)) = self.discriminant {
346 eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400347 disc.to_tokens(tokens);
348 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700349 }
350 }
351
David Tolnaye3d41b72017-12-31 15:24:00 -0500352 impl ToTokens for FieldsNamed {
David Tolnayf38cdf62016-09-23 19:07:09 -0700353 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye3d41b72017-12-31 15:24:00 -0500354 self.brace_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800355 self.named.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500356 });
357 }
358 }
359
360 impl ToTokens for FieldsUnnamed {
361 fn to_tokens(&self, tokens: &mut Tokens) {
362 self.paren_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800363 self.unnamed.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500364 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700365 }
366 }
367
368 impl ToTokens for Field {
369 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700370 tokens.append_all(&self.attrs);
David Tolnay47a877c2016-10-01 16:50:55 -0700371 self.vis.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400372 if let Some(ref ident) = self.ident {
373 ident.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700374 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400375 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700376 self.ty.to_tokens(tokens);
377 }
378 }
379
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700380 impl ToTokens for VisPublic {
David Tolnay47a877c2016-10-01 16:50:55 -0700381 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700382 self.pub_token.to_tokens(tokens)
383 }
384 }
Arnaviond32b2942017-04-29 17:18:02 -0700385
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700386 impl ToTokens for VisCrate {
387 fn to_tokens(&self, tokens: &mut Tokens) {
388 self.pub_token.to_tokens(tokens);
389 self.paren_token.surround(tokens, |tokens| {
390 self.crate_token.to_tokens(tokens);
391 })
392 }
393 }
Arnaviond32b2942017-04-29 17:18:02 -0700394
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700395 impl ToTokens for VisRestricted {
396 fn to_tokens(&self, tokens: &mut Tokens) {
397 self.pub_token.to_tokens(tokens);
398 self.paren_token.surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400399 // XXX: If we have a path which is not "self" or "super",
400 // automatically add the "in" token.
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700401 self.in_token.to_tokens(tokens);
402 self.path.to_tokens(tokens);
403 });
404 }
405 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700406}