blob: d01d9e5a2f8a6bfe0f06c192c36044dc4a9ad5dd [file] [log] [blame]
David Tolnayf38cdf62016-09-23 19:07:09 -07001use super::*;
2
Alex Crichton62a0a592017-05-22 13:58:53 -07003ast_struct! {
4 /// An enum variant.
5 pub struct Variant {
6 /// Name of the variant.
7 pub ident: Ident,
Clar Charrd22b5702017-03-10 15:24:56 -05008
Alex Crichton62a0a592017-05-22 13:58:53 -07009 /// Attributes tagged on the variant.
10 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050011
Alex Crichton62a0a592017-05-22 13:58:53 -070012 /// Type of variant.
13 pub data: VariantData,
Clar Charrd22b5702017-03-10 15:24:56 -050014
Alex Crichton62a0a592017-05-22 13:58:53 -070015 /// Explicit discriminant, e.g. `Foo = 1`
16 pub discriminant: Option<ConstExpr>,
17 }
David Tolnayf38cdf62016-09-23 19:07:09 -070018}
19
Alex Crichton62a0a592017-05-22 13:58:53 -070020ast_enum! {
21 /// Data stored within an enum variant or struct.
22 pub enum VariantData {
23 /// Struct variant, e.g. `Point { x: f64, y: f64 }`.
24 Struct(Vec<Field>),
Clar Charrd22b5702017-03-10 15:24:56 -050025
Alex Crichton62a0a592017-05-22 13:58:53 -070026 /// Tuple variant, e.g. `Some(T)`.
27 Tuple(Vec<Field>),
Clar Charrd22b5702017-03-10 15:24:56 -050028
Alex Crichton62a0a592017-05-22 13:58:53 -070029 /// Unit variant, e.g. `None`.
30 Unit,
31 }
David Tolnayf38cdf62016-09-23 19:07:09 -070032}
33
34impl VariantData {
Clar Charrd22b5702017-03-10 15:24:56 -050035 /// Slice containing the fields stored in the variant.
David Tolnayf38cdf62016-09-23 19:07:09 -070036 pub fn fields(&self) -> &[Field] {
37 match *self {
38 VariantData::Struct(ref fields) |
39 VariantData::Tuple(ref fields) => fields,
40 VariantData::Unit => &[],
41 }
42 }
Sean Griffin15085c42016-10-03 11:40:31 -040043
Clar Charrd22b5702017-03-10 15:24:56 -050044 /// Mutable slice containing the fields stored in the variant.
Sean Griffin15085c42016-10-03 11:40:31 -040045 pub fn fields_mut(&mut self) -> &mut [Field] {
46 match *self {
47 VariantData::Struct(ref mut fields) |
48 VariantData::Tuple(ref mut fields) => fields,
49 VariantData::Unit => &mut [],
50 }
51 }
David Tolnayf38cdf62016-09-23 19:07:09 -070052}
53
Alex Crichton62a0a592017-05-22 13:58:53 -070054ast_struct! {
55 /// A field of a struct or enum variant.
56 pub struct Field {
57 /// Name of the field, if any.
58 ///
59 /// Fields of tuple structs have no names.
60 pub ident: Option<Ident>,
Clar Charrd22b5702017-03-10 15:24:56 -050061
Alex Crichton62a0a592017-05-22 13:58:53 -070062 /// Visibility of the field.
63 pub vis: Visibility,
Clar Charrd22b5702017-03-10 15:24:56 -050064
Alex Crichton62a0a592017-05-22 13:58:53 -070065 /// Attributes tagged on the field.
66 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050067
Alex Crichton62a0a592017-05-22 13:58:53 -070068 /// Type of the field.
69 pub ty: Ty,
70 }
David Tolnayf38cdf62016-09-23 19:07:09 -070071}
72
Alex Crichton62a0a592017-05-22 13:58:53 -070073ast_enum! {
74 /// Visibility level of an item.
75 pub enum Visibility {
76 /// Public, i.e. `pub`.
77 Public,
Clar Charrd22b5702017-03-10 15:24:56 -050078
Alex Crichton62a0a592017-05-22 13:58:53 -070079 /// Crate-visible, i.e. `pub(crate)`.
80 Crate,
Clar Charrd22b5702017-03-10 15:24:56 -050081
Alex Crichton62a0a592017-05-22 13:58:53 -070082 /// Restricted, e.g. `pub(self)` or `pub(super)` or `pub(in some::module)`.
83 Restricted(Box<Path>),
Clar Charrd22b5702017-03-10 15:24:56 -050084
Alex Crichton62a0a592017-05-22 13:58:53 -070085 /// Inherited, i.e. private.
86 Inherited,
87 }
David Tolnayf38cdf62016-09-23 19:07:09 -070088}
89
David Tolnayf38cdf62016-09-23 19:07:09 -070090#[cfg(feature = "parsing")]
91pub mod parsing {
92 use super::*;
David Tolnay28c1db62016-10-27 22:48:18 -070093 use WhereClause;
David Tolnay514f1292017-02-27 12:30:57 -080094 #[cfg(feature = "full")]
95 use ConstExpr;
David Tolnay4a51dc72016-10-01 00:40:31 -070096 use attr::parsing::outer_attr;
David Tolnayf945fb52017-02-27 12:53:54 -080097 #[cfg(feature = "full")]
David Tolnay3cb23a92016-10-07 23:02:21 -070098 use constant::parsing::const_expr;
David Tolnay514f1292017-02-27 12:30:57 -080099 #[cfg(feature = "full")]
100 use expr::parsing::expr;
David Tolnay28c1db62016-10-27 22:48:18 -0700101 use generics::parsing::where_clause;
David Tolnayf38cdf62016-09-23 19:07:09 -0700102 use ident::parsing::ident;
Arnaviond32b2942017-04-29 17:18:02 -0700103 use ty::parsing::{mod_style_path, ty};
David Tolnayf38cdf62016-09-23 19:07:09 -0700104
David Tolnay28c1db62016-10-27 22:48:18 -0700105 named!(pub struct_body -> (WhereClause, VariantData), alt!(
106 do_parse!(
107 wh: where_clause >>
108 body: struct_like_body >>
109 (wh, VariantData::Struct(body))
110 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700111 |
David Tolnay28c1db62016-10-27 22:48:18 -0700112 do_parse!(
113 body: tuple_like_body >>
114 wh: where_clause >>
115 punct!(";") >>
116 (wh, VariantData::Tuple(body))
117 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700118 |
David Tolnay28c1db62016-10-27 22:48:18 -0700119 do_parse!(
120 wh: where_clause >>
121 punct!(";") >>
122 (wh, VariantData::Unit)
123 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700124 ));
125
David Tolnay28c1db62016-10-27 22:48:18 -0700126 named!(pub enum_body -> (WhereClause, Vec<Variant>), do_parse!(
127 wh: where_clause >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700128 punct!("{") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700129 variants: terminated_list!(punct!(","), variant) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700130 punct!("}") >>
David Tolnay28c1db62016-10-27 22:48:18 -0700131 (wh, variants)
David Tolnayf38cdf62016-09-23 19:07:09 -0700132 ));
133
134 named!(variant -> Variant, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700135 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700136 id: ident >>
137 data: alt!(
138 struct_like_body => { VariantData::Struct }
139 |
140 tuple_like_body => { VariantData::Tuple }
141 |
142 epsilon!() => { |_| VariantData::Unit }
143 ) >>
David Tolnay514f1292017-02-27 12:30:57 -0800144 disr: option!(preceded!(punct!("="), discriminant)) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700145 (Variant {
146 ident: id,
147 attrs: attrs,
148 data: data,
149 discriminant: disr,
150 })
151 ));
152
David Tolnay514f1292017-02-27 12:30:57 -0800153 #[cfg(not(feature = "full"))]
David Tolnayf945fb52017-02-27 12:53:54 -0800154 use constant::parsing::const_expr as discriminant;
David Tolnay514f1292017-02-27 12:30:57 -0800155
156 #[cfg(feature = "full")]
157 named!(discriminant -> ConstExpr, alt!(
158 terminated!(const_expr, after_discriminant)
159 |
160 terminated!(expr, after_discriminant) => { ConstExpr::Other }
161 ));
162
163 #[cfg(feature = "full")]
164 named!(after_discriminant -> &str, peek!(alt!(punct!(",") | punct!("}"))));
165
David Tolnay2f9fa632016-10-03 22:08:48 -0700166 named!(pub struct_like_body -> Vec<Field>, do_parse!(
David Tolnayf38cdf62016-09-23 19:07:09 -0700167 punct!("{") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700168 fields: terminated_list!(punct!(","), struct_field) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700169 punct!("}") >>
170 (fields)
171 ));
172
173 named!(tuple_like_body -> Vec<Field>, do_parse!(
174 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700175 fields: terminated_list!(punct!(","), tuple_field) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700176 punct!(")") >>
177 (fields)
178 ));
179
180 named!(struct_field -> Field, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700181 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700182 vis: visibility >>
183 id: ident >>
184 punct!(":") >>
185 ty: ty >>
186 (Field {
187 ident: Some(id),
188 vis: vis,
189 attrs: attrs,
190 ty: ty,
191 })
192 ));
193
194 named!(tuple_field -> Field, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700195 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700196 vis: visibility >>
197 ty: ty >>
198 (Field {
199 ident: None,
200 vis: vis,
201 attrs: attrs,
202 ty: ty,
203 })
204 ));
205
206 named!(pub visibility -> Visibility, alt!(
David Tolnaye07f9e02016-10-30 17:05:55 -0700207 do_parse!(
208 keyword!("pub") >>
209 punct!("(") >>
210 keyword!("crate") >>
211 punct!(")") >>
212 (Visibility::Crate)
213 )
214 |
215 do_parse!(
216 keyword!("pub") >>
217 punct!("(") >>
Arnaviond32b2942017-04-29 17:18:02 -0700218 keyword!("self") >>
219 punct!(")") >>
220 (Visibility::Restricted(Box::new("self".into())))
221 )
222 |
223 do_parse!(
224 keyword!("pub") >>
225 punct!("(") >>
226 keyword!("super") >>
227 punct!(")") >>
228 (Visibility::Restricted(Box::new("super".into())))
229 )
230 |
231 do_parse!(
232 keyword!("pub") >>
233 punct!("(") >>
234 keyword!("in") >>
235 restricted: mod_style_path >>
David Tolnaye07f9e02016-10-30 17:05:55 -0700236 punct!(")") >>
237 (Visibility::Restricted(Box::new(restricted)))
238 )
239 |
David Tolnaybd76e572016-10-02 13:43:16 -0700240 keyword!("pub") => { |_| Visibility::Public }
David Tolnayf38cdf62016-09-23 19:07:09 -0700241 |
242 epsilon!() => { |_| Visibility::Inherited }
243 ));
David Tolnayf38cdf62016-09-23 19:07:09 -0700244}
245
246#[cfg(feature = "printing")]
247mod printing {
248 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -0700249 use quote::{Tokens, ToTokens};
Arnaviond32b2942017-04-29 17:18:02 -0700250 use ty::PathParameters;
David Tolnayf38cdf62016-09-23 19:07:09 -0700251
252 impl ToTokens for Variant {
253 fn to_tokens(&self, tokens: &mut Tokens) {
254 for attr in &self.attrs {
255 attr.to_tokens(tokens);
256 }
257 self.ident.to_tokens(tokens);
258 self.data.to_tokens(tokens);
259 if let Some(ref disr) = self.discriminant {
260 tokens.append("=");
261 disr.to_tokens(tokens);
262 }
263 }
264 }
265
266 impl ToTokens for VariantData {
267 fn to_tokens(&self, tokens: &mut Tokens) {
268 match *self {
269 VariantData::Struct(ref fields) => {
270 tokens.append("{");
271 tokens.append_separated(fields, ",");
272 tokens.append("}");
273 }
274 VariantData::Tuple(ref fields) => {
275 tokens.append("(");
276 tokens.append_separated(fields, ",");
277 tokens.append(")");
278 }
279 VariantData::Unit => {}
280 }
281 }
282 }
283
284 impl ToTokens for Field {
285 fn to_tokens(&self, tokens: &mut Tokens) {
286 for attr in &self.attrs {
287 attr.to_tokens(tokens);
288 }
David Tolnay47a877c2016-10-01 16:50:55 -0700289 self.vis.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700290 if let Some(ref ident) = self.ident {
291 ident.to_tokens(tokens);
292 tokens.append(":");
293 }
294 self.ty.to_tokens(tokens);
295 }
296 }
297
David Tolnay47a877c2016-10-01 16:50:55 -0700298 impl ToTokens for Visibility {
299 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye07f9e02016-10-30 17:05:55 -0700300 match *self {
301 Visibility::Public => tokens.append("pub"),
302 Visibility::Crate => {
303 tokens.append("pub");
304 tokens.append("(");
305 tokens.append("crate");
306 tokens.append(")");
307 }
308 Visibility::Restricted(ref path) => {
309 tokens.append("pub");
310 tokens.append("(");
Arnaviond32b2942017-04-29 17:18:02 -0700311
312 if !path.global &&
313 path.segments.len() == 1 &&
314 (path.segments[0].ident == "self" || path.segments[0].ident == "super") &&
315 path.segments[0].parameters == PathParameters::none() {
316
317 // Don't emit preceding `in` if path is `self` or `super`
318 } else {
319 tokens.append("in");
320 }
321
David Tolnaye07f9e02016-10-30 17:05:55 -0700322 path.to_tokens(tokens);
323 tokens.append(")");
324 }
325 Visibility::Inherited => {}
David Tolnay47a877c2016-10-01 16:50:55 -0700326 }
327 }
328 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700329}