blob: edadba2bae2283851039a10090619221a0ac8e59 [file] [log] [blame]
David Tolnayf38cdf62016-09-23 19:07:09 -07001use super::*;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07002use delimited::Delimited;
David Tolnayf38cdf62016-09-23 19:07:09 -07003
Alex Crichton62a0a592017-05-22 13:58:53 -07004ast_struct! {
5 /// Struct or enum sent to a `proc_macro_derive` macro.
6 pub struct DeriveInput {
David Tolnay4a3f59a2017-12-28 21:21:12 -05007 /// Attributes tagged on the whole struct or enum.
8 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -05009
Alex Crichton62a0a592017-05-22 13:58:53 -070010 /// Visibility of the struct or enum.
11 pub vis: Visibility,
Clar Charrd22b5702017-03-10 15:24:56 -050012
David Tolnay4a3f59a2017-12-28 21:21:12 -050013 /// Name of the struct or enum.
14 pub ident: Ident,
Clar Charrd22b5702017-03-10 15:24:56 -050015
Alex Crichton62a0a592017-05-22 13:58:53 -070016 /// Generics required to complete the definition.
17 pub generics: Generics,
Clar Charrd22b5702017-03-10 15:24:56 -050018
Alex Crichton62a0a592017-05-22 13:58:53 -070019 /// Data within the struct or enum.
20 pub body: Body,
21 }
David Tolnayf38cdf62016-09-23 19:07:09 -070022}
23
Alex Crichtonccbb45d2017-05-23 10:58:24 -070024ast_enum_of_structs! {
Alex Crichton62a0a592017-05-22 13:58:53 -070025 /// Body of a derived struct or enum.
26 pub enum Body {
27 /// It's an enum.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070028 pub Enum(BodyEnum {
David Tolnayf8db7ba2017-11-11 22:52:16 -080029 pub enum_token: Token![enum],
David Tolnay32954ef2017-12-26 22:43:16 -050030 pub brace_token: token::Brace,
David Tolnayf8db7ba2017-11-11 22:52:16 -080031 pub variants: Delimited<Variant, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070032 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070033
34 /// It's a struct.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070035 pub Struct(BodyStruct {
36 pub data: VariantData,
David Tolnayf8db7ba2017-11-11 22:52:16 -080037 pub struct_token: Token![struct],
38 pub semi_token: Option<Token![;]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070039 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070040 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070041
42 do_not_generate_to_tokens
David Tolnayf38cdf62016-09-23 19:07:09 -070043}
44
45#[cfg(feature = "parsing")]
46pub mod parsing {
47 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -070048
Michael Layzell92639a52017-06-01 00:07:44 -040049 use synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -070050
51 impl Synom for DeriveInput {
Michael Layzell92639a52017-06-01 00:07:44 -040052 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -050053 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -040054 vis: syn!(Visibility) >>
55 which: alt!(
David Tolnayf8db7ba2017-11-11 22:52:16 -080056 keyword!(struct) => { Ok }
Michael Layzell92639a52017-06-01 00:07:44 -040057 |
David Tolnayf8db7ba2017-11-11 22:52:16 -080058 keyword!(enum) => { Err }
Michael Layzell92639a52017-06-01 00:07:44 -040059 ) >>
60 id: syn!(Ident) >>
61 generics: syn!(Generics) >>
62 item: switch!(value!(which),
63 Ok(s) => map!(struct_body, move |(wh, body, semi)| DeriveInput {
64 ident: id,
65 vis: vis,
66 attrs: attrs,
67 generics: Generics {
68 where_clause: wh,
69 .. generics
70 },
71 body: Body::Struct(BodyStruct {
72 struct_token: s,
73 data: body,
74 semi_token: semi,
75 }),
76 })
77 |
David Tolnay92a56512017-11-10 00:02:14 -080078 Err(e) => map!(enum_body, move |(wh, body, brace)| DeriveInput {
Michael Layzell92639a52017-06-01 00:07:44 -040079 ident: id,
80 vis: vis,
81 attrs: attrs,
82 generics: Generics {
83 where_clause: wh,
84 .. generics
85 },
86 body: Body::Enum(BodyEnum {
87 variants: body,
88 brace_token: brace,
89 enum_token: e,
90 }),
91 })
92 ) >>
93 (item)
94 ));
Alex Crichton954046c2017-05-30 21:49:42 -070095
96 fn description() -> Option<&'static str> {
97 Some("derive input")
98 }
99 }
100
David Tolnayac997dd2017-12-27 23:18:22 -0500101 named!(struct_body -> (Option<WhereClause>, VariantData, Option<Token![;]>), alt!(
Alex Crichton954046c2017-05-30 21:49:42 -0700102 do_parse!(
David Tolnayac997dd2017-12-27 23:18:22 -0500103 wh: option!(syn!(WhereClause)) >>
Alex Crichton954046c2017-05-30 21:49:42 -0700104 body: struct_like_body >>
105 (wh, VariantData::Struct(body.0, body.1), None)
106 )
107 |
108 do_parse!(
109 body: tuple_like_body >>
David Tolnayac997dd2017-12-27 23:18:22 -0500110 wh: option!(syn!(WhereClause)) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800111 semi: punct!(;) >>
Alex Crichton954046c2017-05-30 21:49:42 -0700112 (wh, VariantData::Tuple(body.0, body.1), Some(semi))
113 )
114 |
115 do_parse!(
David Tolnayac997dd2017-12-27 23:18:22 -0500116 wh: option!(syn!(WhereClause)) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800117 semi: punct!(;) >>
Alex Crichton954046c2017-05-30 21:49:42 -0700118 (wh, VariantData::Unit, Some(semi))
119 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700120 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700121
David Tolnayac997dd2017-12-27 23:18:22 -0500122 named!(enum_body -> (Option<WhereClause>, Delimited<Variant, Token![,]>, token::Brace), do_parse!(
123 wh: option!(syn!(WhereClause)) >>
Alex Crichton954046c2017-05-30 21:49:42 -0700124 data: braces!(Delimited::parse_terminated) >>
125 (wh, data.0, data.1)
126 ));
127
128 impl Synom for Variant {
Michael Layzell92639a52017-06-01 00:07:44 -0400129 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500130 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400131 id: syn!(Ident) >>
132 data: alt!(
133 struct_like_body => { |(d, b)| VariantData::Struct(d, b) }
134 |
135 tuple_like_body => { |(d, b)| VariantData::Tuple(d, b) }
136 |
137 epsilon!() => { |_| VariantData::Unit }
138 ) >>
139 disr: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800140 eq: punct!(=) >>
Michael Layzelld7ee9102017-06-07 10:02:19 -0400141 disr: syn!(Expr) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400142 (eq, disr)
143 )) >>
144 (Variant {
145 ident: id,
146 attrs: attrs,
147 data: data,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800148 eq_token: disr.as_ref().map(|p| Token![=]((p.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400149 discriminant: disr.map(|p| p.1),
150 })
151 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700152 }
153
David Tolnay32954ef2017-12-26 22:43:16 -0500154 named!(struct_like_body -> (Delimited<Field, Token![,]>, token::Brace),
Alex Crichton954046c2017-05-30 21:49:42 -0700155 braces!(call!(Delimited::parse_terminated_with, Field::parse_struct)));
156
David Tolnay32954ef2017-12-26 22:43:16 -0500157 named!(tuple_like_body -> (Delimited<Field, Token![,]>, token::Paren),
Alex Crichton954046c2017-05-30 21:49:42 -0700158 parens!(call!(Delimited::parse_terminated_with, Field::parse_tuple)));
David Tolnayf38cdf62016-09-23 19:07:09 -0700159}
160
David Tolnayc2dfbf42016-09-23 23:52:15 -0700161#[cfg(feature = "printing")]
David Tolnayf38cdf62016-09-23 19:07:09 -0700162mod printing {
163 use super::*;
David Tolnay4a51dc72016-10-01 00:40:31 -0700164 use attr::FilterAttrs;
David Tolnay47a877c2016-10-01 16:50:55 -0700165 use data::VariantData;
David Tolnay51382052017-12-27 13:46:21 -0500166 use quote::{ToTokens, Tokens};
David Tolnayf38cdf62016-09-23 19:07:09 -0700167
David Tolnay0e837402016-12-22 17:25:55 -0500168 impl ToTokens for DeriveInput {
David Tolnayf38cdf62016-09-23 19:07:09 -0700169 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay4a51dc72016-10-01 00:40:31 -0700170 for attr in self.attrs.outer() {
David Tolnayf38cdf62016-09-23 19:07:09 -0700171 attr.to_tokens(tokens);
172 }
David Tolnay47a877c2016-10-01 16:50:55 -0700173 self.vis.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700174 match self.body {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700175 Body::Enum(ref d) => d.enum_token.to_tokens(tokens),
176 Body::Struct(ref d) => d.struct_token.to_tokens(tokens),
David Tolnayf38cdf62016-09-23 19:07:09 -0700177 }
178 self.ident.to_tokens(tokens);
179 self.generics.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700180 match self.body {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700181 Body::Enum(ref data) => {
David Tolnay28c1db62016-10-27 22:48:18 -0700182 self.generics.where_clause.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700183 data.brace_token.surround(tokens, |tokens| {
184 data.variants.to_tokens(tokens);
185 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700186 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700187 Body::Struct(ref data) => {
188 match data.data {
189 VariantData::Struct(..) => {
David Tolnay28c1db62016-10-27 22:48:18 -0700190 self.generics.where_clause.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700191 data.data.to_tokens(tokens);
David Tolnaydaaf7742016-10-03 11:11:43 -0700192 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700193 VariantData::Tuple(..) => {
194 data.data.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700195 self.generics.where_clause.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700196 }
197 VariantData::Unit => {
198 self.generics.where_clause.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700199 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700200 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700201 data.semi_token.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700202 }
203 }
204 }
205 }
206}