blob: 7fc5097c32c6e8b4510a0fc3caa6b9cd12157e97 [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 {
7 /// Name of the struct or enum.
8 pub ident: Ident,
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
Alex Crichton62a0a592017-05-22 13:58:53 -070013 /// Attributes tagged on the whole struct or enum.
14 pub attrs: Vec<Attribute>,
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
Clar Charrd22b5702017-03-10 15:24:56 -050024
Alex Crichtonccbb45d2017-05-23 10:58:24 -070025ast_enum_of_structs! {
Alex Crichton62a0a592017-05-22 13:58:53 -070026 /// Body of a derived struct or enum.
27 pub enum Body {
28 /// It's an enum.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070029 pub Enum(BodyEnum {
David Tolnayf8db7ba2017-11-11 22:52:16 -080030 pub enum_token: Token![enum],
David Tolnay32954ef2017-12-26 22:43:16 -050031 pub brace_token: token::Brace,
David Tolnayf8db7ba2017-11-11 22:52:16 -080032 pub variants: Delimited<Variant, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070033 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070034
35 /// It's a struct.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070036 pub Struct(BodyStruct {
37 pub data: VariantData,
David Tolnayf8db7ba2017-11-11 22:52:16 -080038 pub struct_token: Token![struct],
39 pub semi_token: Option<Token![;]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070040 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070041 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070042
43 do_not_generate_to_tokens
David Tolnayf38cdf62016-09-23 19:07:09 -070044}
45
46#[cfg(feature = "parsing")]
47pub mod parsing {
48 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -070049
Michael Layzell92639a52017-06-01 00:07:44 -040050 use synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -070051
52 impl Synom for DeriveInput {
Michael Layzell92639a52017-06-01 00:07:44 -040053 named!(parse -> Self, do_parse!(
54 attrs: many0!(call!(Attribute::parse_outer)) >>
55 vis: syn!(Visibility) >>
56 which: alt!(
David Tolnayf8db7ba2017-11-11 22:52:16 -080057 keyword!(struct) => { Ok }
Michael Layzell92639a52017-06-01 00:07:44 -040058 |
David Tolnayf8db7ba2017-11-11 22:52:16 -080059 keyword!(enum) => { Err }
Michael Layzell92639a52017-06-01 00:07:44 -040060 ) >>
61 id: syn!(Ident) >>
62 generics: syn!(Generics) >>
63 item: switch!(value!(which),
64 Ok(s) => map!(struct_body, move |(wh, body, semi)| DeriveInput {
65 ident: id,
66 vis: vis,
67 attrs: attrs,
68 generics: Generics {
69 where_clause: wh,
70 .. generics
71 },
72 body: Body::Struct(BodyStruct {
73 struct_token: s,
74 data: body,
75 semi_token: semi,
76 }),
77 })
78 |
David Tolnay92a56512017-11-10 00:02:14 -080079 Err(e) => map!(enum_body, move |(wh, body, brace)| DeriveInput {
Michael Layzell92639a52017-06-01 00:07:44 -040080 ident: id,
81 vis: vis,
82 attrs: attrs,
83 generics: Generics {
84 where_clause: wh,
85 .. generics
86 },
87 body: Body::Enum(BodyEnum {
88 variants: body,
89 brace_token: brace,
90 enum_token: e,
91 }),
92 })
93 ) >>
94 (item)
95 ));
Alex Crichton954046c2017-05-30 21:49:42 -070096
97 fn description() -> Option<&'static str> {
98 Some("derive input")
99 }
100 }
101
102
David Tolnayf8db7ba2017-11-11 22:52:16 -0800103 named!(struct_body -> (WhereClause, VariantData, Option<Token![;]>), alt!(
Alex Crichton954046c2017-05-30 21:49:42 -0700104 do_parse!(
105 wh: syn!(WhereClause) >>
106 body: struct_like_body >>
107 (wh, VariantData::Struct(body.0, body.1), None)
108 )
109 |
110 do_parse!(
111 body: tuple_like_body >>
112 wh: syn!(WhereClause) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800113 semi: punct!(;) >>
Alex Crichton954046c2017-05-30 21:49:42 -0700114 (wh, VariantData::Tuple(body.0, body.1), Some(semi))
115 )
116 |
117 do_parse!(
118 wh: syn!(WhereClause) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800119 semi: punct!(;) >>
Alex Crichton954046c2017-05-30 21:49:42 -0700120 (wh, VariantData::Unit, Some(semi))
121 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700122 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700123
David Tolnay32954ef2017-12-26 22:43:16 -0500124 named!(enum_body -> (WhereClause, Delimited<Variant, Token![,]>, token::Brace), do_parse!(
Alex Crichton954046c2017-05-30 21:49:42 -0700125 wh: syn!(WhereClause) >>
126 data: braces!(Delimited::parse_terminated) >>
127 (wh, data.0, data.1)
128 ));
129
130 impl Synom for Variant {
Michael Layzell92639a52017-06-01 00:07:44 -0400131 named!(parse -> Self, do_parse!(
132 attrs: many0!(call!(Attribute::parse_outer)) >>
133 id: syn!(Ident) >>
134 data: alt!(
135 struct_like_body => { |(d, b)| VariantData::Struct(d, b) }
136 |
137 tuple_like_body => { |(d, b)| VariantData::Tuple(d, b) }
138 |
139 epsilon!() => { |_| VariantData::Unit }
140 ) >>
141 disr: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800142 eq: punct!(=) >>
Michael Layzelld7ee9102017-06-07 10:02:19 -0400143 disr: syn!(Expr) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400144 (eq, disr)
145 )) >>
146 (Variant {
147 ident: id,
148 attrs: attrs,
149 data: data,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800150 eq_token: disr.as_ref().map(|p| Token![=]((p.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400151 discriminant: disr.map(|p| p.1),
152 })
153 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700154 }
155
David Tolnay32954ef2017-12-26 22:43:16 -0500156 named!(struct_like_body -> (Delimited<Field, Token![,]>, token::Brace),
Alex Crichton954046c2017-05-30 21:49:42 -0700157 braces!(call!(Delimited::parse_terminated_with, Field::parse_struct)));
158
David Tolnay32954ef2017-12-26 22:43:16 -0500159 named!(tuple_like_body -> (Delimited<Field, Token![,]>, token::Paren),
Alex Crichton954046c2017-05-30 21:49:42 -0700160 parens!(call!(Delimited::parse_terminated_with, Field::parse_tuple)));
David Tolnayf38cdf62016-09-23 19:07:09 -0700161}
162
David Tolnayc2dfbf42016-09-23 23:52:15 -0700163#[cfg(feature = "printing")]
David Tolnayf38cdf62016-09-23 19:07:09 -0700164mod printing {
165 use super::*;
David Tolnay4a51dc72016-10-01 00:40:31 -0700166 use attr::FilterAttrs;
David Tolnay47a877c2016-10-01 16:50:55 -0700167 use data::VariantData;
David Tolnayf38cdf62016-09-23 19:07:09 -0700168 use quote::{Tokens, ToTokens};
169
David Tolnay0e837402016-12-22 17:25:55 -0500170 impl ToTokens for DeriveInput {
David Tolnayf38cdf62016-09-23 19:07:09 -0700171 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay4a51dc72016-10-01 00:40:31 -0700172 for attr in self.attrs.outer() {
David Tolnayf38cdf62016-09-23 19:07:09 -0700173 attr.to_tokens(tokens);
174 }
David Tolnay47a877c2016-10-01 16:50:55 -0700175 self.vis.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700176 match self.body {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700177 Body::Enum(ref d) => d.enum_token.to_tokens(tokens),
178 Body::Struct(ref d) => d.struct_token.to_tokens(tokens),
David Tolnayf38cdf62016-09-23 19:07:09 -0700179 }
180 self.ident.to_tokens(tokens);
181 self.generics.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700182 match self.body {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700183 Body::Enum(ref data) => {
David Tolnay28c1db62016-10-27 22:48:18 -0700184 self.generics.where_clause.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700185 data.brace_token.surround(tokens, |tokens| {
186 data.variants.to_tokens(tokens);
187 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700188 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700189 Body::Struct(ref data) => {
190 match data.data {
191 VariantData::Struct(..) => {
David Tolnay28c1db62016-10-27 22:48:18 -0700192 self.generics.where_clause.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700193 data.data.to_tokens(tokens);
David Tolnaydaaf7742016-10-03 11:11:43 -0700194 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700195 VariantData::Tuple(..) => {
196 data.data.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700197 self.generics.where_clause.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700198 }
199 VariantData::Unit => {
200 self.generics.where_clause.to_tokens(tokens);
David Tolnay28c1db62016-10-27 22:48:18 -0700201 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700202 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700203 data.semi_token.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700204 }
205 }
206 }
207 }
208}