blob: f54f5b9afe3cac367728289c74ebd170069e1e4d [file] [log] [blame]
David Tolnayf38cdf62016-09-23 19:07:09 -07001use super::*;
David Tolnayf2cfd722017-12-31 18:02:51 -05002use punctuated::Punctuated;
David Tolnayf38cdf62016-09-23 19:07:09 -07003
Alex Crichton62a0a592017-05-22 13:58:53 -07004ast_struct! {
5 /// An enum variant.
David Tolnay461d98e2018-01-07 11:07:19 -08006 ///
7 /// *This type is available if Syn is built with the `"derive"` or `"full"`
8 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -07009 pub struct Variant {
Alex Crichton62a0a592017-05-22 13:58:53 -070010 /// Attributes tagged on the variant.
11 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050012
David Tolnay4a3f59a2017-12-28 21:21:12 -050013 /// Name of the variant.
14 pub ident: Ident,
15
David Tolnaye3d41b72017-12-31 15:24:00 -050016 /// Content stored in the variant.
17 pub fields: Fields,
Clar Charrd22b5702017-03-10 15:24:56 -050018
David Tolnay05658502018-01-07 09:56:37 -080019 /// Explicit discriminant: `Variant = 1`
David Tolnaye67902a2017-12-28 22:12:00 -050020 pub discriminant: Option<(Token![=], Expr)>,
Alex Crichton62a0a592017-05-22 13:58:53 -070021 }
David Tolnayf38cdf62016-09-23 19:07:09 -070022}
23
David Tolnaye3d41b72017-12-31 15:24:00 -050024ast_enum_of_structs! {
Alex Crichton62a0a592017-05-22 13:58:53 -070025 /// Data stored within an enum variant or struct.
David Tolnay614a0142018-01-07 10:25:43 -080026 ///
David Tolnay461d98e2018-01-07 11:07:19 -080027 /// *This type is available if Syn is built with the `"derive"` or `"full"`
28 /// feature.*
29 ///
David Tolnay614a0142018-01-07 10:25:43 -080030 /// # Syntax tree enum
31 ///
32 /// This type is a [syntax tree enum].
33 ///
34 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
David Tolnaye3d41b72017-12-31 15:24:00 -050035 pub enum Fields {
36 /// Named fields of a struct or struct variant such as `Point { x: f64,
37 /// y: f64 }`.
David Tolnay461d98e2018-01-07 11:07:19 -080038 ///
39 /// *This type is available if Syn is built with the `"derive"` or
40 /// `"full"` feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050041 pub Named(FieldsNamed {
42 pub brace_token: token::Brace,
David Tolnaybdafb102018-01-01 19:39:10 -080043 pub named: Punctuated<Field, Token![,]>,
David Tolnaye3d41b72017-12-31 15:24:00 -050044 }),
Clar Charrd22b5702017-03-10 15:24:56 -050045
David Tolnaye3d41b72017-12-31 15:24:00 -050046 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
David Tolnay461d98e2018-01-07 11:07:19 -080047 ///
48 /// *This type is available if Syn is built with the `"derive"` or
49 /// `"full"` feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050050 pub Unnamed(FieldsUnnamed {
51 pub paren_token: token::Paren,
David Tolnaybdafb102018-01-01 19:39:10 -080052 pub unnamed: Punctuated<Field, Token![,]>,
David Tolnaye3d41b72017-12-31 15:24:00 -050053 }),
Clar Charrd22b5702017-03-10 15:24:56 -050054
David Tolnaye3d41b72017-12-31 15:24:00 -050055 /// Unit struct or unit variant such as `None`.
56 pub Unit,
Alex Crichton62a0a592017-05-22 13:58:53 -070057 }
David Tolnayf38cdf62016-09-23 19:07:09 -070058}
59
Nika Layzell5680dcc2018-01-16 15:14:27 -050060impl Fields {
Michael Bradshaw0b13ae62018-08-02 23:43:15 -060061 /// Get an iterator over the borrowed [`Field`] items in this object. This
62 /// iterator can be used to iterate over a named or unnamed struct or
63 /// variant's fields uniformly.
Nika Layzell5680dcc2018-01-16 15:14:27 -050064 ///
65 /// [`Field`]: struct.Field.html
David Tolnay8095c302018-03-31 19:34:17 +020066 pub fn iter(&self) -> punctuated::Iter<Field> {
Nika Layzell5680dcc2018-01-16 15:14:27 -050067 match *self {
David Tolnay10951d52018-08-31 10:27:39 -070068 Fields::Unit => private::empty_punctuated_iter(),
David Tolnay96a09d92018-01-16 22:24:03 -080069 Fields::Named(ref f) => f.named.iter(),
70 Fields::Unnamed(ref f) => f.unnamed.iter(),
Nika Layzell5680dcc2018-01-16 15:14:27 -050071 }
72 }
Michael Bradshaw0b13ae62018-08-02 23:43:15 -060073
74 /// Get an iterator over the mutably borrowed [`Field`] items in this
75 /// object. This iterator can be used to iterate over a named or unnamed
76 /// struct or variant's fields uniformly.
77 ///
78 /// [`Field`]: struct.Field.html
79 pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
80 match *self {
David Tolnay10951d52018-08-31 10:27:39 -070081 Fields::Unit => private::empty_punctuated_iter_mut(),
Michael Bradshaw0b13ae62018-08-02 23:43:15 -060082 Fields::Named(ref mut f) => f.named.iter_mut(),
83 Fields::Unnamed(ref mut f) => f.unnamed.iter_mut(),
84 }
85 }
Nika Layzell5680dcc2018-01-16 15:14:27 -050086}
87
88impl<'a> IntoIterator for &'a Fields {
89 type Item = &'a Field;
David Tolnay8095c302018-03-31 19:34:17 +020090 type IntoIter = punctuated::Iter<'a, Field>;
Nika Layzell5680dcc2018-01-16 15:14:27 -050091
92 fn into_iter(self) -> Self::IntoIter {
93 self.iter()
94 }
95}
96
Michael Bradshaw0b13ae62018-08-02 23:43:15 -060097impl<'a> IntoIterator for &'a mut Fields {
98 type Item = &'a mut Field;
99 type IntoIter = punctuated::IterMut<'a, Field>;
100
101 fn into_iter(self) -> Self::IntoIter {
102 self.iter_mut()
103 }
104}
105
Alex Crichton62a0a592017-05-22 13:58:53 -0700106ast_struct! {
107 /// A field of a struct or enum variant.
David Tolnay461d98e2018-01-07 11:07:19 -0800108 ///
109 /// *This type is available if Syn is built with the `"derive"` or `"full"`
110 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700111 pub struct Field {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500112 /// Attributes tagged on the field.
113 pub attrs: Vec<Attribute>,
114
115 /// Visibility of the field.
116 pub vis: Visibility,
117
Alex Crichton62a0a592017-05-22 13:58:53 -0700118 /// Name of the field, if any.
119 ///
120 /// Fields of tuple structs have no names.
121 pub ident: Option<Ident>,
Clar Charrd22b5702017-03-10 15:24:56 -0500122
David Tolnay4a3f59a2017-12-28 21:21:12 -0500123 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500124
Alex Crichton62a0a592017-05-22 13:58:53 -0700125 /// Type of the field.
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800126 pub ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700127 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700128}
129
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700130ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800131 /// The visibility level of an item: inherited or `pub` or
132 /// `pub(restricted)`.
David Tolnay614a0142018-01-07 10:25:43 -0800133 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800134 /// *This type is available if Syn is built with the `"derive"` or `"full"`
135 /// feature.*
136 ///
David Tolnay614a0142018-01-07 10:25:43 -0800137 /// # Syntax tree enum
138 ///
139 /// This type is a [syntax tree enum].
140 ///
141 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700142 pub enum Visibility {
David Tolnay05658502018-01-07 09:56:37 -0800143 /// A public visibility level: `pub`.
David Tolnay461d98e2018-01-07 11:07:19 -0800144 ///
145 /// *This type is available if Syn is built with the `"derive"` or
146 /// `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700147 pub Public(VisPublic {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800148 pub pub_token: Token![pub],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700149 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500150
David Tolnayc8ecb362018-04-01 11:01:09 +0200151 /// A crate-level visibility: `crate`.
David Tolnay461d98e2018-01-07 11:07:19 -0800152 ///
153 /// *This type is available if Syn is built with the `"derive"` or
154 /// `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700155 pub Crate(VisCrate {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800156 pub crate_token: Token![crate],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnay05658502018-01-07 09:56:37 -0800159 /// A visibility level restricted to some path: `pub(self)` or
David Tolnayc8ecb362018-04-01 11:01:09 +0200160 /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800161 ///
162 /// *This type is available if Syn is built with the `"derive"` or
163 /// `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700164 pub Restricted(VisRestricted {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800165 pub pub_token: Token![pub],
David Tolnay32954ef2017-12-26 22:43:16 -0500166 pub paren_token: token::Paren,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800167 pub in_token: Option<Token![in]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700168 pub path: Box<Path>,
169 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500170
David Tolnay05658502018-01-07 09:56:37 -0800171 /// An inherited visibility, which usually means private.
David Tolnayfcfb9002017-12-28 22:04:29 -0500172 pub Inherited,
Alex Crichton62a0a592017-05-22 13:58:53 -0700173 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700174}
175
David Tolnayf38cdf62016-09-23 19:07:09 -0700176#[cfg(feature = "parsing")]
177pub mod parsing {
178 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -0700179
David Tolnay94d304f2018-08-30 23:43:53 -0700180 use ext::IdentExt;
David Tolnay898bb742018-08-25 16:40:11 -0400181 use parse::{Parse, ParseStream, Result};
David Tolnayf38cdf62016-09-23 19:07:09 -0700182
David Tolnay3a515a02018-08-25 21:08:27 -0400183 impl Parse for Variant {
184 fn parse(input: ParseStream) -> Result<Self> {
185 Ok(Variant {
David Tolnayf8106f82018-08-25 21:17:45 -0400186 attrs: input.call(Attribute::parse_outer)?,
David Tolnay3a515a02018-08-25 21:08:27 -0400187 ident: input.parse()?,
188 fields: {
189 if input.peek(token::Brace) {
David Tolnay577d0332018-08-25 21:45:24 -0400190 Fields::Named(input.parse()?)
David Tolnay3a515a02018-08-25 21:08:27 -0400191 } else if input.peek(token::Paren) {
David Tolnay577d0332018-08-25 21:45:24 -0400192 Fields::Unnamed(input.parse()?)
David Tolnay3a515a02018-08-25 21:08:27 -0400193 } else {
194 Fields::Unit
195 }
196 },
197 discriminant: {
198 if input.peek(Token![=]) {
David Tolnay9389c382018-08-27 09:13:37 -0700199 let eq_token: Token![=] = input.parse()?;
200 let discriminant: Expr = input.parse()?;
201 Some((eq_token, discriminant))
David Tolnay3a515a02018-08-25 21:08:27 -0400202 } else {
203 None
204 }
205 },
David Tolnaye3d41b72017-12-31 15:24:00 -0500206 })
David Tolnaye3d41b72017-12-31 15:24:00 -0500207 }
208 }
209
David Tolnay577d0332018-08-25 21:45:24 -0400210 impl Parse for FieldsNamed {
211 fn parse(input: ParseStream) -> Result<Self> {
212 let content;
213 Ok(FieldsNamed {
214 brace_token: braced!(content in input),
215 named: content.parse_terminated(Field::parse_named)?,
216 })
David Tolnay79777332018-01-07 10:04:42 -0800217 }
David Tolnaye3d41b72017-12-31 15:24:00 -0500218 }
219
David Tolnay577d0332018-08-25 21:45:24 -0400220 impl Parse for FieldsUnnamed {
221 fn parse(input: ParseStream) -> Result<Self> {
222 let content;
223 Ok(FieldsUnnamed {
224 paren_token: parenthesized!(content in input),
225 unnamed: content.parse_terminated(Field::parse_unnamed)?,
226 })
David Tolnay79777332018-01-07 10:04:42 -0800227 }
David Tolnaye3d41b72017-12-31 15:24:00 -0500228 }
229
Alex Crichton954046c2017-05-30 21:49:42 -0700230 impl Field {
David Tolnay860de442018-09-01 17:42:57 -0700231 /// Parses a named (braced struct) field.
232 pub fn parse_named(input: ParseStream) -> Result<Self> {
David Tolnay577d0332018-08-25 21:45:24 -0400233 Ok(Field {
234 attrs: input.call(Attribute::parse_outer)?,
235 vis: input.parse()?,
236 ident: Some(input.parse()?),
237 colon_token: Some(input.parse()?),
David Tolnaya7d69fc2018-08-26 13:30:24 -0400238 ty: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -0400239 })
David Tolnay577d0332018-08-25 21:45:24 -0400240 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700241
David Tolnay860de442018-09-01 17:42:57 -0700242 /// Parses an unnamed (tuple struct) field.
243 pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
David Tolnay577d0332018-08-25 21:45:24 -0400244 Ok(Field {
245 attrs: input.call(Attribute::parse_outer)?,
246 vis: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -0400247 ident: None,
248 colon_token: None,
David Tolnaya7d69fc2018-08-26 13:30:24 -0400249 ty: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -0400250 })
David Tolnay577d0332018-08-25 21:45:24 -0400251 }
Michael Layzell416724e2017-05-24 21:12:34 -0400252 }
253
David Tolnay898bb742018-08-25 16:40:11 -0400254 impl Parse for Visibility {
255 fn parse(input: ParseStream) -> Result<Self> {
256 if input.peek(Token![pub]) {
257 Self::parse_pub(input)
258 } else if input.peek(Token![crate]) {
259 Self::parse_crate(input)
260 } else {
261 Ok(Visibility::Inherited)
262 }
263 }
264 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800265
David Tolnay898bb742018-08-25 16:40:11 -0400266 impl Visibility {
267 fn parse_pub(input: ParseStream) -> Result<Self> {
268 let pub_token = input.parse::<Token![pub]>()?;
269
270 if input.peek(token::Paren) {
271 let ahead = input.fork();
272 let mut content;
273 parenthesized!(content in ahead);
274
275 if content.peek(Token![crate])
276 || content.peek(Token![self])
277 || content.peek(Token![super])
278 {
279 return Ok(Visibility::Restricted(VisRestricted {
280 pub_token: pub_token,
281 paren_token: parenthesized!(content in input),
282 in_token: None,
David Tolnay0dea1b92018-08-30 17:47:29 -0700283 path: Box::new(Path::from(content.call(Ident::parse_any)?)),
David Tolnay898bb742018-08-25 16:40:11 -0400284 }));
285 } else if content.peek(Token![in]) {
286 return Ok(Visibility::Restricted(VisRestricted {
287 pub_token: pub_token,
288 paren_token: parenthesized!(content in input),
289 in_token: Some(content.parse()?),
David Tolnay248a4e12018-08-30 17:13:46 -0700290 path: Box::new(content.call(Path::parse_mod_style)?),
David Tolnay898bb742018-08-25 16:40:11 -0400291 }));
292 }
293 }
294
295 Ok(Visibility::Public(VisPublic {
296 pub_token: pub_token,
297 }))
298 }
299
300 fn parse_crate(input: ParseStream) -> Result<Self> {
David Tolnay4fb71232018-08-25 23:14:50 -0400301 if input.peek2(Token![::]) {
David Tolnay898bb742018-08-25 16:40:11 -0400302 Ok(Visibility::Inherited)
303 } else {
304 Ok(Visibility::Crate(VisCrate {
305 crate_token: input.parse()?,
306 }))
307 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800308 }
Alex Crichton954046c2017-05-30 21:49:42 -0700309 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700310}
311
312#[cfg(feature = "printing")]
313mod printing {
314 use super::*;
David Tolnay64023912018-08-31 09:51:12 -0700315
Alex Crichtona74a1c82018-05-16 10:20:44 -0700316 use proc_macro2::TokenStream;
317 use quote::{ToTokens, TokenStreamExt};
David Tolnayf38cdf62016-09-23 19:07:09 -0700318
David Tolnay64023912018-08-31 09:51:12 -0700319 use print::TokensOrDefault;
320
David Tolnayf38cdf62016-09-23 19:07:09 -0700321 impl ToTokens for Variant {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700322 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700323 tokens.append_all(&self.attrs);
David Tolnayf38cdf62016-09-23 19:07:09 -0700324 self.ident.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500325 self.fields.to_tokens(tokens);
David Tolnaye67902a2017-12-28 22:12:00 -0500326 if let Some((ref eq_token, ref disc)) = self.discriminant {
327 eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400328 disc.to_tokens(tokens);
329 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700330 }
331 }
332
David Tolnaye3d41b72017-12-31 15:24:00 -0500333 impl ToTokens for FieldsNamed {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700334 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye3d41b72017-12-31 15:24:00 -0500335 self.brace_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800336 self.named.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500337 });
338 }
339 }
340
341 impl ToTokens for FieldsUnnamed {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700342 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye3d41b72017-12-31 15:24:00 -0500343 self.paren_token.surround(tokens, |tokens| {
David Tolnaybdafb102018-01-01 19:39:10 -0800344 self.unnamed.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500345 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700346 }
347 }
348
349 impl ToTokens for Field {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700350 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700351 tokens.append_all(&self.attrs);
David Tolnay47a877c2016-10-01 16:50:55 -0700352 self.vis.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400353 if let Some(ref ident) = self.ident {
354 ident.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700355 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400356 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700357 self.ty.to_tokens(tokens);
358 }
359 }
360
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700361 impl ToTokens for VisPublic {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700362 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700363 self.pub_token.to_tokens(tokens)
364 }
365 }
Arnaviond32b2942017-04-29 17:18:02 -0700366
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700367 impl ToTokens for VisCrate {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700368 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayfe58b5a2018-03-31 18:20:40 +0200369 self.crate_token.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700370 }
371 }
Arnaviond32b2942017-04-29 17:18:02 -0700372
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700373 impl ToTokens for VisRestricted {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700374 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700375 self.pub_token.to_tokens(tokens);
376 self.paren_token.surround(tokens, |tokens| {
David Tolnay38a6d842018-09-01 10:54:07 -0700377 // TODO: If we have a path which is not "self" or "super" or
David Tolnayfe58b5a2018-03-31 18:20:40 +0200378 // "crate", automatically add the "in" token.
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700379 self.in_token.to_tokens(tokens);
380 self.path.to_tokens(tokens);
381 });
382 }
383 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700384}