blob: 217461744d667f55a247cd9254567424581e3462 [file] [log] [blame]
David Tolnayf38cdf62016-09-23 19:07:09 -07001use super::*;
2
Clar Charrd22b5702017-03-10 15:24:56 -05003/// An enum variant.
David Tolnay9bf4af82017-01-07 11:17:46 -08004#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf38cdf62016-09-23 19:07:09 -07005pub struct Variant {
Clar Charrd22b5702017-03-10 15:24:56 -05006 /// Name of the variant.
David Tolnayf38cdf62016-09-23 19:07:09 -07007 pub ident: Ident,
Clar Charrd22b5702017-03-10 15:24:56 -05008
9 /// Attributes tagged on the variant.
David Tolnayf38cdf62016-09-23 19:07:09 -070010 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050011
12 /// Type of variant.
David Tolnayf38cdf62016-09-23 19:07:09 -070013 pub data: VariantData,
Clar Charrd22b5702017-03-10 15:24:56 -050014
David Tolnayf38cdf62016-09-23 19:07:09 -070015 /// Explicit discriminant, e.g. `Foo = 1`
David Tolnay3cb23a92016-10-07 23:02:21 -070016 pub discriminant: Option<ConstExpr>,
David Tolnayf38cdf62016-09-23 19:07:09 -070017}
18
Clar Charrd22b5702017-03-10 15:24:56 -050019/// Data stored within an enum variant or struct.
David Tolnay9bf4af82017-01-07 11:17:46 -080020#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf38cdf62016-09-23 19:07:09 -070021pub enum VariantData {
Clar Charrd22b5702017-03-10 15:24:56 -050022 /// Struct variant, e.g. `Point { x: f64, y: f64 }`.
David Tolnayf38cdf62016-09-23 19:07:09 -070023 Struct(Vec<Field>),
Clar Charrd22b5702017-03-10 15:24:56 -050024
25 /// Tuple variant, e.g. `Some(T)`.
David Tolnayf38cdf62016-09-23 19:07:09 -070026 Tuple(Vec<Field>),
Clar Charrd22b5702017-03-10 15:24:56 -050027
28 /// Unit variant, e.g. `None`.
David Tolnayf38cdf62016-09-23 19:07:09 -070029 Unit,
30}
31
32impl VariantData {
Clar Charrd22b5702017-03-10 15:24:56 -050033 /// Slice containing the fields stored in the variant.
David Tolnayf38cdf62016-09-23 19:07:09 -070034 pub fn fields(&self) -> &[Field] {
35 match *self {
36 VariantData::Struct(ref fields) |
37 VariantData::Tuple(ref fields) => fields,
38 VariantData::Unit => &[],
39 }
40 }
Sean Griffin15085c42016-10-03 11:40:31 -040041
Clar Charrd22b5702017-03-10 15:24:56 -050042 /// Mutable slice containing the fields stored in the variant.
Sean Griffin15085c42016-10-03 11:40:31 -040043 pub fn fields_mut(&mut self) -> &mut [Field] {
44 match *self {
45 VariantData::Struct(ref mut fields) |
46 VariantData::Tuple(ref mut fields) => fields,
47 VariantData::Unit => &mut [],
48 }
49 }
David Tolnayf38cdf62016-09-23 19:07:09 -070050}
51
Clar Charrd22b5702017-03-10 15:24:56 -050052/// A field of a struct or enum variant.
David Tolnay9bf4af82017-01-07 11:17:46 -080053#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf38cdf62016-09-23 19:07:09 -070054pub struct Field {
Clar Charrd22b5702017-03-10 15:24:56 -050055 /// Name of the field, if any.
56 ///
57 /// Fields of tuple structs have no names.
David Tolnayf38cdf62016-09-23 19:07:09 -070058 pub ident: Option<Ident>,
Clar Charrd22b5702017-03-10 15:24:56 -050059
60 /// Visibility of the field.
David Tolnayf38cdf62016-09-23 19:07:09 -070061 pub vis: Visibility,
Clar Charrd22b5702017-03-10 15:24:56 -050062
63 /// Attributes tagged on the field.
David Tolnayf38cdf62016-09-23 19:07:09 -070064 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050065
66 /// Type of the field.
David Tolnayf38cdf62016-09-23 19:07:09 -070067 pub ty: Ty,
68}
69
Clar Charrd22b5702017-03-10 15:24:56 -050070
71/// Visibility level of an item.
David Tolnay9bf4af82017-01-07 11:17:46 -080072#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayf38cdf62016-09-23 19:07:09 -070073pub enum Visibility {
Clar Charrd22b5702017-03-10 15:24:56 -050074 /// Public, i.e. `pub`.
David Tolnayf38cdf62016-09-23 19:07:09 -070075 Public,
Clar Charrd22b5702017-03-10 15:24:56 -050076
77 /// Crate-visible, i.e. `pub(crate)`.
David Tolnaye07f9e02016-10-30 17:05:55 -070078 Crate,
Clar Charrd22b5702017-03-10 15:24:56 -050079
Arnaviond32b2942017-04-29 17:18:02 -070080 /// Restricted, e.g. `pub(self)` or `pub(super)` or `pub(in some::module)`.
David Tolnaye07f9e02016-10-30 17:05:55 -070081 Restricted(Box<Path>),
Clar Charrd22b5702017-03-10 15:24:56 -050082
83 /// Inherited, i.e. private.
David Tolnayf38cdf62016-09-23 19:07:09 -070084 Inherited,
85}
86
David Tolnayf38cdf62016-09-23 19:07:09 -070087#[cfg(feature = "parsing")]
88pub mod parsing {
89 use super::*;
David Tolnay28c1db62016-10-27 22:48:18 -070090 use WhereClause;
David Tolnay514f1292017-02-27 12:30:57 -080091 #[cfg(feature = "full")]
92 use ConstExpr;
David Tolnay4a51dc72016-10-01 00:40:31 -070093 use attr::parsing::outer_attr;
David Tolnayf945fb52017-02-27 12:53:54 -080094 #[cfg(feature = "full")]
David Tolnay3cb23a92016-10-07 23:02:21 -070095 use constant::parsing::const_expr;
David Tolnay514f1292017-02-27 12:30:57 -080096 #[cfg(feature = "full")]
97 use expr::parsing::expr;
David Tolnay28c1db62016-10-27 22:48:18 -070098 use generics::parsing::where_clause;
David Tolnayf38cdf62016-09-23 19:07:09 -070099 use ident::parsing::ident;
Arnaviond32b2942017-04-29 17:18:02 -0700100 use ty::parsing::{mod_style_path, ty};
David Tolnayf38cdf62016-09-23 19:07:09 -0700101
David Tolnay28c1db62016-10-27 22:48:18 -0700102 named!(pub struct_body -> (WhereClause, VariantData), alt!(
103 do_parse!(
104 wh: where_clause >>
105 body: struct_like_body >>
106 (wh, VariantData::Struct(body))
107 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700108 |
David Tolnay28c1db62016-10-27 22:48:18 -0700109 do_parse!(
110 body: tuple_like_body >>
111 wh: where_clause >>
112 punct!(";") >>
113 (wh, VariantData::Tuple(body))
114 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700115 |
David Tolnay28c1db62016-10-27 22:48:18 -0700116 do_parse!(
117 wh: where_clause >>
118 punct!(";") >>
119 (wh, VariantData::Unit)
120 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700121 ));
122
David Tolnay28c1db62016-10-27 22:48:18 -0700123 named!(pub enum_body -> (WhereClause, Vec<Variant>), do_parse!(
124 wh: where_clause >>
Michael Layzell416724e2017-05-24 21:12:34 -0400125 variants: delim!(Brace, terminated_list!(punct!(","), variant)) >>
David Tolnay28c1db62016-10-27 22:48:18 -0700126 (wh, variants)
David Tolnayf38cdf62016-09-23 19:07:09 -0700127 ));
128
129 named!(variant -> Variant, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700130 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700131 id: ident >>
132 data: alt!(
133 struct_like_body => { VariantData::Struct }
134 |
135 tuple_like_body => { VariantData::Tuple }
136 |
137 epsilon!() => { |_| VariantData::Unit }
138 ) >>
David Tolnay514f1292017-02-27 12:30:57 -0800139 disr: option!(preceded!(punct!("="), discriminant)) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700140 (Variant {
141 ident: id,
142 attrs: attrs,
143 data: data,
144 discriminant: disr,
145 })
146 ));
147
David Tolnay514f1292017-02-27 12:30:57 -0800148 #[cfg(not(feature = "full"))]
David Tolnayf945fb52017-02-27 12:53:54 -0800149 use constant::parsing::const_expr as discriminant;
David Tolnay514f1292017-02-27 12:30:57 -0800150
151 #[cfg(feature = "full")]
152 named!(discriminant -> ConstExpr, alt!(
153 terminated!(const_expr, after_discriminant)
154 |
155 terminated!(expr, after_discriminant) => { ConstExpr::Other }
156 ));
157
Michael Layzell416724e2017-05-24 21:12:34 -0400158 // XXX: HACKY
David Tolnay514f1292017-02-27 12:30:57 -0800159 #[cfg(feature = "full")]
Michael Layzell416724e2017-05-24 21:12:34 -0400160 pub fn eof(input: &[synom::TokenTree]) -> synom::IResult<&[synom::TokenTree], &'static str> {
161 if input.is_empty() {
162 synom::IResult::Done(&[], "")
163 } else {
164 synom::IResult::Error
165 }
166 }
167
168 #[cfg(feature = "full")]
169 named!(after_discriminant -> &str, peek!(alt!(punct!(",") | input_end!())));
David Tolnay514f1292017-02-27 12:30:57 -0800170
David Tolnay2f9fa632016-10-03 22:08:48 -0700171 named!(pub struct_like_body -> Vec<Field>, do_parse!(
Michael Layzell416724e2017-05-24 21:12:34 -0400172 fields: delim!(Brace, terminated_list!(punct!(","), struct_field)) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700173 (fields)
174 ));
175
176 named!(tuple_like_body -> Vec<Field>, do_parse!(
Michael Layzell416724e2017-05-24 21:12:34 -0400177 fields: delim!(Parenthesis, terminated_list!(punct!(","), tuple_field)) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700178 (fields)
179 ));
180
181 named!(struct_field -> Field, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700182 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700183 vis: visibility >>
184 id: ident >>
185 punct!(":") >>
186 ty: ty >>
187 (Field {
188 ident: Some(id),
189 vis: vis,
190 attrs: attrs,
191 ty: ty,
192 })
193 ));
194
195 named!(tuple_field -> Field, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700196 attrs: many0!(outer_attr) >>
David Tolnayf38cdf62016-09-23 19:07:09 -0700197 vis: visibility >>
198 ty: ty >>
199 (Field {
200 ident: None,
201 vis: vis,
202 attrs: attrs,
203 ty: ty,
204 })
205 ));
206
207 named!(pub visibility -> Visibility, alt!(
David Tolnaye07f9e02016-10-30 17:05:55 -0700208 do_parse!(
209 keyword!("pub") >>
Michael Layzell416724e2017-05-24 21:12:34 -0400210 delim!(Parenthesis, keyword!("crate")) >>
David Tolnaye07f9e02016-10-30 17:05:55 -0700211 (Visibility::Crate)
212 )
213 |
214 do_parse!(
215 keyword!("pub") >>
Michael Layzell416724e2017-05-24 21:12:34 -0400216 delim!(Parenthesis, keyword!("self")) >>
Arnaviond32b2942017-04-29 17:18:02 -0700217 (Visibility::Restricted(Box::new("self".into())))
218 )
219 |
220 do_parse!(
221 keyword!("pub") >>
Michael Layzell416724e2017-05-24 21:12:34 -0400222 delim!(Parenthesis, keyword!("super")) >>
Arnaviond32b2942017-04-29 17:18:02 -0700223 (Visibility::Restricted(Box::new("super".into())))
224 )
225 |
226 do_parse!(
227 keyword!("pub") >>
Michael Layzell416724e2017-05-24 21:12:34 -0400228 restricted: delim!(Parenthesis, preceded!(keyword!("in"), mod_style_path)) >>
David Tolnaye07f9e02016-10-30 17:05:55 -0700229 (Visibility::Restricted(Box::new(restricted)))
230 )
231 |
David Tolnaybd76e572016-10-02 13:43:16 -0700232 keyword!("pub") => { |_| Visibility::Public }
David Tolnayf38cdf62016-09-23 19:07:09 -0700233 |
234 epsilon!() => { |_| Visibility::Inherited }
235 ));
David Tolnayf38cdf62016-09-23 19:07:09 -0700236}
237
238#[cfg(feature = "printing")]
239mod printing {
240 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -0700241 use quote::{Tokens, ToTokens};
Arnaviond32b2942017-04-29 17:18:02 -0700242 use ty::PathParameters;
David Tolnayf38cdf62016-09-23 19:07:09 -0700243
244 impl ToTokens for Variant {
245 fn to_tokens(&self, tokens: &mut Tokens) {
246 for attr in &self.attrs {
247 attr.to_tokens(tokens);
248 }
249 self.ident.to_tokens(tokens);
250 self.data.to_tokens(tokens);
251 if let Some(ref disr) = self.discriminant {
252 tokens.append("=");
253 disr.to_tokens(tokens);
254 }
255 }
256 }
257
258 impl ToTokens for VariantData {
259 fn to_tokens(&self, tokens: &mut Tokens) {
260 match *self {
261 VariantData::Struct(ref fields) => {
262 tokens.append("{");
263 tokens.append_separated(fields, ",");
264 tokens.append("}");
265 }
266 VariantData::Tuple(ref fields) => {
267 tokens.append("(");
268 tokens.append_separated(fields, ",");
269 tokens.append(")");
270 }
271 VariantData::Unit => {}
272 }
273 }
274 }
275
276 impl ToTokens for Field {
277 fn to_tokens(&self, tokens: &mut Tokens) {
278 for attr in &self.attrs {
279 attr.to_tokens(tokens);
280 }
David Tolnay47a877c2016-10-01 16:50:55 -0700281 self.vis.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700282 if let Some(ref ident) = self.ident {
283 ident.to_tokens(tokens);
284 tokens.append(":");
285 }
286 self.ty.to_tokens(tokens);
287 }
288 }
289
David Tolnay47a877c2016-10-01 16:50:55 -0700290 impl ToTokens for Visibility {
291 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye07f9e02016-10-30 17:05:55 -0700292 match *self {
293 Visibility::Public => tokens.append("pub"),
294 Visibility::Crate => {
295 tokens.append("pub");
296 tokens.append("(");
297 tokens.append("crate");
298 tokens.append(")");
299 }
300 Visibility::Restricted(ref path) => {
301 tokens.append("pub");
302 tokens.append("(");
Arnaviond32b2942017-04-29 17:18:02 -0700303
304 if !path.global &&
305 path.segments.len() == 1 &&
306 (path.segments[0].ident == "self" || path.segments[0].ident == "super") &&
307 path.segments[0].parameters == PathParameters::none() {
308
309 // Don't emit preceding `in` if path is `self` or `super`
310 } else {
311 tokens.append("in");
312 }
313
David Tolnaye07f9e02016-10-30 17:05:55 -0700314 path.to_tokens(tokens);
315 tokens.append(")");
316 }
317 Visibility::Inherited => {}
David Tolnay47a877c2016-10-01 16:50:55 -0700318 }
319 }
320 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700321}