blob: 93a66a1a095a9a84ab6581ed6fc16b193f98f6c3 [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
Alex Crichtona74a1c82018-05-16 10:20:44 -07009use proc_macro2::Ident;
10
David Tolnayf38cdf62016-09-23 19:07:09 -070011use super::*;
David Tolnayf2cfd722017-12-31 18:02:51 -050012use punctuated::Punctuated;
David Tolnayf38cdf62016-09-23 19:07:09 -070013
Alex Crichton62a0a592017-05-22 13:58:53 -070014ast_struct! {
15 /// An enum variant.
David Tolnay461d98e2018-01-07 11:07:19 -080016 ///
17 /// *This type is available if Syn is built with the `"derive"` or `"full"`
18 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -070019 pub struct Variant {
Alex Crichton62a0a592017-05-22 13:58:53 -070020 /// Attributes tagged on the variant.
21 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050022
David Tolnay4a3f59a2017-12-28 21:21:12 -050023 /// Name of the variant.
24 pub ident: Ident,
25
David Tolnaye3d41b72017-12-31 15:24:00 -050026 /// Content stored in the variant.
27 pub fields: Fields,
Clar Charrd22b5702017-03-10 15:24:56 -050028
David Tolnay05658502018-01-07 09:56:37 -080029 /// Explicit discriminant: `Variant = 1`
David Tolnaye67902a2017-12-28 22:12:00 -050030 pub discriminant: Option<(Token![=], Expr)>,
Alex Crichton62a0a592017-05-22 13:58:53 -070031 }
David Tolnayf38cdf62016-09-23 19:07:09 -070032}
33
David Tolnaye3d41b72017-12-31 15:24:00 -050034ast_enum_of_structs! {
Alex Crichton62a0a592017-05-22 13:58:53 -070035 /// Data stored within an enum variant or struct.
David Tolnay614a0142018-01-07 10:25:43 -080036 ///
David Tolnay461d98e2018-01-07 11:07:19 -080037 /// *This type is available if Syn is built with the `"derive"` or `"full"`
38 /// feature.*
39 ///
David Tolnay614a0142018-01-07 10:25:43 -080040 /// # Syntax tree enum
41 ///
42 /// This type is a [syntax tree enum].
43 ///
44 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
David Tolnaye3d41b72017-12-31 15:24:00 -050045 pub enum Fields {
46 /// Named fields of a struct or struct variant such as `Point { x: f64,
47 /// y: f64 }`.
David Tolnay461d98e2018-01-07 11:07:19 -080048 ///
49 /// *This type is available if Syn is built with the `"derive"` or
50 /// `"full"` feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050051 pub Named(FieldsNamed {
52 pub brace_token: token::Brace,
David Tolnaybdafb102018-01-01 19:39:10 -080053 pub named: Punctuated<Field, Token![,]>,
David Tolnaye3d41b72017-12-31 15:24:00 -050054 }),
Clar Charrd22b5702017-03-10 15:24:56 -050055
David Tolnaye3d41b72017-12-31 15:24:00 -050056 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
David Tolnay461d98e2018-01-07 11:07:19 -080057 ///
58 /// *This type is available if Syn is built with the `"derive"` or
59 /// `"full"` feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050060 pub Unnamed(FieldsUnnamed {
61 pub paren_token: token::Paren,
David Tolnaybdafb102018-01-01 19:39:10 -080062 pub unnamed: Punctuated<Field, Token![,]>,
David Tolnaye3d41b72017-12-31 15:24:00 -050063 }),
Clar Charrd22b5702017-03-10 15:24:56 -050064
David Tolnaye3d41b72017-12-31 15:24:00 -050065 /// Unit struct or unit variant such as `None`.
66 pub Unit,
Alex Crichton62a0a592017-05-22 13:58:53 -070067 }
David Tolnayf38cdf62016-09-23 19:07:09 -070068}
69
Nika Layzell5680dcc2018-01-16 15:14:27 -050070impl Fields {
71 /// Get an iterator over the [`Field`] items in this object. This iterator
72 /// can be used to iterate over a named or unnamed struct or variant's
73 /// fields uniformly.
74 ///
75 /// [`Field`]: struct.Field.html
David Tolnay8095c302018-03-31 19:34:17 +020076 pub fn iter(&self) -> punctuated::Iter<Field> {
Nika Layzell5680dcc2018-01-16 15:14:27 -050077 match *self {
David Tolnay96a09d92018-01-16 22:24:03 -080078 Fields::Unit => punctuated::Iter::private_empty(),
79 Fields::Named(ref f) => f.named.iter(),
80 Fields::Unnamed(ref f) => f.unnamed.iter(),
Nika Layzell5680dcc2018-01-16 15:14:27 -050081 }
82 }
83}
84
85impl<'a> IntoIterator for &'a Fields {
86 type Item = &'a Field;
David Tolnay8095c302018-03-31 19:34:17 +020087 type IntoIter = punctuated::Iter<'a, Field>;
Nika Layzell5680dcc2018-01-16 15:14:27 -050088
89 fn into_iter(self) -> Self::IntoIter {
90 self.iter()
91 }
92}
93
Alex Crichton62a0a592017-05-22 13:58:53 -070094ast_struct! {
95 /// A field of a struct or enum variant.
David Tolnay461d98e2018-01-07 11:07:19 -080096 ///
97 /// *This type is available if Syn is built with the `"derive"` or `"full"`
98 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -070099 pub struct Field {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500100 /// Attributes tagged on the field.
101 pub attrs: Vec<Attribute>,
102
103 /// Visibility of the field.
104 pub vis: Visibility,
105
Alex Crichton62a0a592017-05-22 13:58:53 -0700106 /// Name of the field, if any.
107 ///
108 /// Fields of tuple structs have no names.
109 pub ident: Option<Ident>,
Clar Charrd22b5702017-03-10 15:24:56 -0500110
David Tolnay4a3f59a2017-12-28 21:21:12 -0500111 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500112
Alex Crichton62a0a592017-05-22 13:58:53 -0700113 /// Type of the field.
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800114 pub ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700115 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700116}
117
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700118ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800119 /// The visibility level of an item: inherited or `pub` or
120 /// `pub(restricted)`.
David Tolnay614a0142018-01-07 10:25:43 -0800121 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800122 /// *This type is available if Syn is built with the `"derive"` or `"full"`
123 /// feature.*
124 ///
David Tolnay614a0142018-01-07 10:25:43 -0800125 /// # Syntax tree enum
126 ///
127 /// This type is a [syntax tree enum].
128 ///
129 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700130 pub enum Visibility {
David Tolnay05658502018-01-07 09:56:37 -0800131 /// A public visibility level: `pub`.
David Tolnay461d98e2018-01-07 11:07:19 -0800132 ///
133 /// *This type is available if Syn is built with the `"derive"` or
134 /// `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700135 pub Public(VisPublic {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800136 pub pub_token: Token![pub],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700137 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500138
David Tolnayc8ecb362018-04-01 11:01:09 +0200139 /// A crate-level visibility: `crate`.
David Tolnay461d98e2018-01-07 11:07:19 -0800140 ///
141 /// *This type is available if Syn is built with the `"derive"` or
142 /// `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700143 pub Crate(VisCrate {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800144 pub crate_token: Token![crate],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700145 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500146
David Tolnay05658502018-01-07 09:56:37 -0800147 /// A visibility level restricted to some path: `pub(self)` or
David Tolnayc8ecb362018-04-01 11:01:09 +0200148 /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800149 ///
150 /// *This type is available if Syn is built with the `"derive"` or
151 /// `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700152 pub Restricted(VisRestricted {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800153 pub pub_token: Token![pub],
David Tolnay32954ef2017-12-26 22:43:16 -0500154 pub paren_token: token::Paren,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800155 pub in_token: Option<Token![in]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700156 pub path: Box<Path>,
157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnay05658502018-01-07 09:56:37 -0800159 /// An inherited visibility, which usually means private.
David Tolnayfcfb9002017-12-28 22:04:29 -0500160 pub Inherited,
Alex Crichton62a0a592017-05-22 13:58:53 -0700161 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700162}
163
David Tolnayf38cdf62016-09-23 19:07:09 -0700164#[cfg(feature = "parsing")]
165pub mod parsing {
166 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -0700167
Michael Layzell92639a52017-06-01 00:07:44 -0400168 use synom::Synom;
David Tolnayf38cdf62016-09-23 19:07:09 -0700169
David Tolnaye3d41b72017-12-31 15:24:00 -0500170 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!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500197 braces!(call!(Punctuated::parse_terminated_with, Field::parse_named)),
David Tolnaye3d41b72017-12-31 15:24:00 -0500198 |(brace, fields)| FieldsNamed {
199 brace_token: brace,
David Tolnaybdafb102018-01-01 19:39:10 -0800200 named: fields,
David Tolnaye3d41b72017-12-31 15:24:00 -0500201 }
202 ));
David Tolnay79777332018-01-07 10:04:42 -0800203
204 fn description() -> Option<&'static str> {
205 Some("named fields in a struct or struct variant")
206 }
David Tolnaye3d41b72017-12-31 15:24:00 -0500207 }
208
209 impl Synom for FieldsUnnamed {
210 named!(parse -> Self, map!(
David Tolnayf2cfd722017-12-31 18:02:51 -0500211 parens!(call!(Punctuated::parse_terminated_with, Field::parse_unnamed)),
David Tolnaye3d41b72017-12-31 15:24:00 -0500212 |(paren, fields)| FieldsUnnamed {
213 paren_token: paren,
David Tolnaybdafb102018-01-01 19:39:10 -0800214 unnamed: fields,
David Tolnaye3d41b72017-12-31 15:24:00 -0500215 }
216 ));
David Tolnay79777332018-01-07 10:04:42 -0800217
218 fn description() -> Option<&'static str> {
219 Some("unnamed fields in a tuple struct or tuple variant")
220 }
David Tolnaye3d41b72017-12-31 15:24:00 -0500221 }
222
Alex Crichton954046c2017-05-30 21:49:42 -0700223 impl Field {
David Tolnaye3d41b72017-12-31 15:24:00 -0500224 named!(pub parse_named -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500225 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400226 vis: syn!(Visibility) >>
227 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800228 colon: punct!(:) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800229 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400230 (Field {
231 ident: Some(id),
232 vis: vis,
233 attrs: attrs,
234 ty: ty,
235 colon_token: Some(colon),
236 })
237 ));
David Tolnayf38cdf62016-09-23 19:07:09 -0700238
David Tolnaye3d41b72017-12-31 15:24:00 -0500239 named!(pub parse_unnamed -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500240 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400241 vis: syn!(Visibility) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800242 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400243 (Field {
244 ident: None,
245 colon_token: None,
246 vis: vis,
247 attrs: attrs,
248 ty: ty,
249 })
250 ));
Michael Layzell416724e2017-05-24 21:12:34 -0400251 }
252
Alex Crichton954046c2017-05-30 21:49:42 -0700253 impl Synom for Visibility {
Michael Layzell92639a52017-06-01 00:07:44 -0400254 named!(parse -> Self, alt!(
255 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800256 pub_token: keyword!(pub) >>
257 other: parens!(keyword!(crate)) >>
David Tolnayfe58b5a2018-03-31 18:20:40 +0200258 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400259 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500260 paren_token: other.0,
David Tolnayfe58b5a2018-03-31 18:20:40 +0200261 in_token: None,
262 path: Box::new(other.1.into()),
Michael Layzell92639a52017-06-01 00:07:44 -0400263 }))
264 )
265 |
David Tolnay36175562018-03-28 13:51:02 +0200266 keyword!(crate) => { |tok| {
267 Visibility::Crate(VisCrate {
David Tolnay36175562018-03-28 13:51:02 +0200268 crate_token: tok,
269 })
270 } }
271 |
Michael Layzell92639a52017-06-01 00:07:44 -0400272 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800273 pub_token: keyword!(pub) >>
274 other: parens!(keyword!(self)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400275 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400276 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500277 paren_token: other.0,
278 in_token: None,
279 path: Box::new(other.1.into()),
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!(super)) >>
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) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400296 other: parens!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800297 in_tok: keyword!(in) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400298 restricted: call!(Path::parse_mod_style) >>
299 (in_tok, restricted)
300 )) >>
301 (Visibility::Restricted(VisRestricted {
Michael Layzell92639a52017-06-01 00:07:44 -0400302 pub_token: pub_token,
David Tolnay8875fca2017-12-31 13:52:37 -0500303 paren_token: other.0,
304 in_token: Some((other.1).0),
305 path: Box::new((other.1).1),
Michael Layzell92639a52017-06-01 00:07:44 -0400306 }))
307 )
308 |
David Tolnayf8db7ba2017-11-11 22:52:16 -0800309 keyword!(pub) => { |tok| {
Michael Layzell92639a52017-06-01 00:07:44 -0400310 Visibility::Public(VisPublic {
311 pub_token: tok,
312 })
313 } }
314 |
David Tolnayfcfb9002017-12-28 22:04:29 -0500315 epsilon!() => { |_| Visibility::Inherited }
Michael Layzell92639a52017-06-01 00:07:44 -0400316 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800317
318 fn description() -> Option<&'static str> {
David Tolnay05658502018-01-07 09:56:37 -0800319 Some("visibility qualifier such as `pub`")
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800320 }
Alex Crichton954046c2017-05-30 21:49:42 -0700321 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700322}
323
324#[cfg(feature = "printing")]
325mod printing {
326 use super::*;
Alex Crichtona74a1c82018-05-16 10:20:44 -0700327 use proc_macro2::TokenStream;
328 use quote::{ToTokens, TokenStreamExt};
David Tolnayf38cdf62016-09-23 19:07:09 -0700329
330 impl ToTokens for Variant {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700331 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700332 tokens.append_all(&self.attrs);
David Tolnayf38cdf62016-09-23 19:07:09 -0700333 self.ident.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500334 self.fields.to_tokens(tokens);
David Tolnaye67902a2017-12-28 22:12:00 -0500335 if let Some((ref eq_token, ref disc)) = self.discriminant {
336 eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400337 disc.to_tokens(tokens);
338 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700339 }
340 }
341
David Tolnaye3d41b72017-12-31 15:24:00 -0500342 impl ToTokens for FieldsNamed {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700343 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye3d41b72017-12-31 15:24:00 -0500344 self.brace_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800345 self.named.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500346 });
347 }
348 }
349
350 impl ToTokens for FieldsUnnamed {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700351 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye3d41b72017-12-31 15:24:00 -0500352 self.paren_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800353 self.unnamed.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500354 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700355 }
356 }
357
358 impl ToTokens for Field {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700359 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700360 tokens.append_all(&self.attrs);
David Tolnay47a877c2016-10-01 16:50:55 -0700361 self.vis.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400362 if let Some(ref ident) = self.ident {
363 ident.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700364 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400365 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700366 self.ty.to_tokens(tokens);
367 }
368 }
369
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700370 impl ToTokens for VisPublic {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700371 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700372 self.pub_token.to_tokens(tokens)
373 }
374 }
Arnaviond32b2942017-04-29 17:18:02 -0700375
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700376 impl ToTokens for VisCrate {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700377 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayfe58b5a2018-03-31 18:20:40 +0200378 self.crate_token.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700379 }
380 }
Arnaviond32b2942017-04-29 17:18:02 -0700381
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700382 impl ToTokens for VisRestricted {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700383 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700384 self.pub_token.to_tokens(tokens);
385 self.paren_token.surround(tokens, |tokens| {
David Tolnayfe58b5a2018-03-31 18:20:40 +0200386 // XXX: If we have a path which is not "self" or "super" or
387 // "crate", automatically add the "in" token.
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700388 self.in_token.to_tokens(tokens);
389 self.path.to_tokens(tokens);
390 });
391 }
392 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700393}