blob: 3bf125c9cf2ce2416a40e4d70274c715a543f554 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayf38cdf62016-09-23 19:07:09 -07009use super::*;
Nika Layzell5680dcc2018-01-16 15:14:27 -050010use punctuated::Punctuated;
David Tolnayf38cdf62016-09-23 19:07:09 -070011
Alex Crichton62a0a592017-05-22 13:58:53 -070012ast_struct! {
David Tolnaye3d41b72017-12-31 15:24:00 -050013 /// Data structure sent to a `proc_macro_derive` macro.
David Tolnay461d98e2018-01-07 11:07:19 -080014 ///
15 /// *This type is available if Syn is built with the `"derive"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -070016 pub struct DeriveInput {
David Tolnay4a3f59a2017-12-28 21:21:12 -050017 /// Attributes tagged on the whole struct or enum.
18 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050019
Alex Crichton62a0a592017-05-22 13:58:53 -070020 /// Visibility of the struct or enum.
21 pub vis: Visibility,
Clar Charrd22b5702017-03-10 15:24:56 -050022
David Tolnay4a3f59a2017-12-28 21:21:12 -050023 /// Name of the struct or enum.
24 pub ident: Ident,
Clar Charrd22b5702017-03-10 15:24:56 -050025
Alex Crichton62a0a592017-05-22 13:58:53 -070026 /// Generics required to complete the definition.
27 pub generics: Generics,
Clar Charrd22b5702017-03-10 15:24:56 -050028
Alex Crichton62a0a592017-05-22 13:58:53 -070029 /// Data within the struct or enum.
David Tolnaye3d41b72017-12-31 15:24:00 -050030 pub data: Data,
Alex Crichton62a0a592017-05-22 13:58:53 -070031 }
David Tolnayf38cdf62016-09-23 19:07:09 -070032}
33
Alex Crichtonccbb45d2017-05-23 10:58:24 -070034ast_enum_of_structs! {
David Tolnaye3d41b72017-12-31 15:24:00 -050035 /// The storage of a struct, enum or union data structure.
David Tolnay614a0142018-01-07 10:25:43 -080036 ///
David Tolnay461d98e2018-01-07 11:07:19 -080037 /// *This type is available if Syn is built with the `"derive"` feature.*
38 ///
David Tolnay614a0142018-01-07 10:25:43 -080039 /// # Syntax tree enum
40 ///
41 /// This type is a [syntax tree enum].
42 ///
43 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
David Tolnaye3d41b72017-12-31 15:24:00 -050044 pub enum Data {
David Tolnayd2aa8832018-01-07 01:05:09 -080045 /// A struct input to a `proc_macro_derive` macro.
David Tolnay461d98e2018-01-07 11:07:19 -080046 ///
47 /// *This type is available if Syn is built with the `"derive"`
48 /// feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050049 pub Struct(DataStruct {
50 pub struct_token: Token![struct],
51 pub fields: Fields,
52 pub semi_token: Option<Token![;]>,
53 }),
54
David Tolnayd2aa8832018-01-07 01:05:09 -080055 /// An enum input to a `proc_macro_derive` macro.
David Tolnay461d98e2018-01-07 11:07:19 -080056 ///
57 /// *This type is available if Syn is built with the `"derive"`
58 /// feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050059 pub Enum(DataEnum {
David Tolnayf8db7ba2017-11-11 22:52:16 -080060 pub enum_token: Token![enum],
David Tolnay32954ef2017-12-26 22:43:16 -050061 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -050062 pub variants: Punctuated<Variant, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070063 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070064
David Tolnayd2aa8832018-01-07 01:05:09 -080065 /// A tagged union input to a `proc_macro_derive` macro.
David Tolnay461d98e2018-01-07 11:07:19 -080066 ///
67 /// *This type is available if Syn is built with the `"derive"`
68 /// feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050069 pub Union(DataUnion {
70 pub union_token: Token![union],
71 pub fields: FieldsNamed,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070072 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070073 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070074
75 do_not_generate_to_tokens
David Tolnayf38cdf62016-09-23 19:07:09 -070076}
77
78#[cfg(feature = "parsing")]
79pub mod parsing {
80 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -070081
Michael Layzell92639a52017-06-01 00:07:44 -040082 use synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -070083
David Tolnayb022d062018-07-21 18:59:36 -070084 enum DeriveInputKind {
85 Struct(Token![struct]),
86 Enum(Token![enum]),
87 Union(Token![union]),
88 }
89
90 impl Synom for DeriveInputKind {
91 named!(parse -> Self, alt!(
92 keyword!(struct) => { DeriveInputKind::Struct }
93 |
94 keyword!(enum) => { DeriveInputKind::Enum }
95 |
96 keyword!(union) => { DeriveInputKind::Union }
97 ));
98 }
99
Alex Crichton954046c2017-05-30 21:49:42 -0700100 impl Synom for DeriveInput {
Michael Layzell92639a52017-06-01 00:07:44 -0400101 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500102 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400103 vis: syn!(Visibility) >>
David Tolnayb022d062018-07-21 18:59:36 -0700104 which: syn!(DeriveInputKind) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400105 id: syn!(Ident) >>
106 generics: syn!(Generics) >>
107 item: switch!(value!(which),
David Tolnayb022d062018-07-21 18:59:36 -0700108 DeriveInputKind::Struct(s) => map!(data_struct, move |(wh, fields, semi)| DeriveInput {
Michael Layzell92639a52017-06-01 00:07:44 -0400109 ident: id,
110 vis: vis,
111 attrs: attrs,
112 generics: Generics {
113 where_clause: wh,
David Tolnayd142fc52018-07-21 15:09:53 -0700114 ..generics
Michael Layzell92639a52017-06-01 00:07:44 -0400115 },
David Tolnaye3d41b72017-12-31 15:24:00 -0500116 data: Data::Struct(DataStruct {
Michael Layzell92639a52017-06-01 00:07:44 -0400117 struct_token: s,
David Tolnaye3d41b72017-12-31 15:24:00 -0500118 fields: fields,
Michael Layzell92639a52017-06-01 00:07:44 -0400119 semi_token: semi,
120 }),
121 })
122 |
David Tolnayb022d062018-07-21 18:59:36 -0700123 DeriveInputKind::Enum(e) => map!(data_enum, move |(wh, brace, variants)| DeriveInput {
Michael Layzell92639a52017-06-01 00:07:44 -0400124 ident: id,
125 vis: vis,
126 attrs: attrs,
127 generics: Generics {
128 where_clause: wh,
David Tolnayd142fc52018-07-21 15:09:53 -0700129 ..generics
Michael Layzell92639a52017-06-01 00:07:44 -0400130 },
David Tolnaye3d41b72017-12-31 15:24:00 -0500131 data: Data::Enum(DataEnum {
132 variants: variants,
Michael Layzell92639a52017-06-01 00:07:44 -0400133 brace_token: brace,
134 enum_token: e,
135 }),
136 })
David Tolnayb022d062018-07-21 18:59:36 -0700137 |
138 DeriveInputKind::Union(u) => map!(data_union, move |(wh, fields)| DeriveInput {
139 ident: id,
140 vis: vis,
141 attrs: attrs,
142 generics: Generics {
143 where_clause: wh,
144 ..generics
145 },
146 data: Data::Union(DataUnion {
147 union_token: u,
148 fields: fields,
149 }),
150 })
Michael Layzell92639a52017-06-01 00:07:44 -0400151 ) >>
152 (item)
153 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700154
155 fn description() -> Option<&'static str> {
156 Some("derive input")
157 }
158 }
159
David Tolnaye3d41b72017-12-31 15:24:00 -0500160 named!(data_struct -> (Option<WhereClause>, Fields, Option<Token![;]>), alt!(
Alex Crichton954046c2017-05-30 21:49:42 -0700161 do_parse!(
David Tolnayac997dd2017-12-27 23:18:22 -0500162 wh: option!(syn!(WhereClause)) >>
David Tolnaye3d41b72017-12-31 15:24:00 -0500163 fields: syn!(FieldsNamed) >>
164 (wh, Fields::Named(fields), None)
Alex Crichton954046c2017-05-30 21:49:42 -0700165 )
166 |
167 do_parse!(
David Tolnaye3d41b72017-12-31 15:24:00 -0500168 fields: syn!(FieldsUnnamed) >>
David Tolnayac997dd2017-12-27 23:18:22 -0500169 wh: option!(syn!(WhereClause)) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800170 semi: punct!(;) >>
David Tolnaye3d41b72017-12-31 15:24:00 -0500171 (wh, Fields::Unnamed(fields), Some(semi))
Alex Crichton954046c2017-05-30 21:49:42 -0700172 )
173 |
174 do_parse!(
David Tolnayac997dd2017-12-27 23:18:22 -0500175 wh: option!(syn!(WhereClause)) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800176 semi: punct!(;) >>
David Tolnaye3d41b72017-12-31 15:24:00 -0500177 (wh, Fields::Unit, Some(semi))
Alex Crichton954046c2017-05-30 21:49:42 -0700178 )
David Tolnayf38cdf62016-09-23 19:07:09 -0700179 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700180
David Tolnayf2cfd722017-12-31 18:02:51 -0500181 named!(data_enum -> (Option<WhereClause>, token::Brace, Punctuated<Variant, Token![,]>), do_parse!(
David Tolnayac997dd2017-12-27 23:18:22 -0500182 wh: option!(syn!(WhereClause)) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500183 data: braces!(Punctuated::parse_terminated) >>
Alex Crichton954046c2017-05-30 21:49:42 -0700184 (wh, data.0, data.1)
185 ));
David Tolnayb022d062018-07-21 18:59:36 -0700186
187 named!(data_union -> (Option<WhereClause>, FieldsNamed), tuple!(
188 option!(syn!(WhereClause)),
189 syn!(FieldsNamed)
190 ));
David Tolnayf38cdf62016-09-23 19:07:09 -0700191}
192
David Tolnayc2dfbf42016-09-23 23:52:15 -0700193#[cfg(feature = "printing")]
David Tolnayf38cdf62016-09-23 19:07:09 -0700194mod printing {
195 use super::*;
David Tolnay4a51dc72016-10-01 00:40:31 -0700196 use attr::FilterAttrs;
Alex Crichtona74a1c82018-05-16 10:20:44 -0700197 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700198 use quote::ToTokens;
David Tolnayf38cdf62016-09-23 19:07:09 -0700199
David Tolnay0e837402016-12-22 17:25:55 -0500200 impl ToTokens for DeriveInput {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700201 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay4a51dc72016-10-01 00:40:31 -0700202 for attr in self.attrs.outer() {
David Tolnayf38cdf62016-09-23 19:07:09 -0700203 attr.to_tokens(tokens);
204 }
David Tolnay47a877c2016-10-01 16:50:55 -0700205 self.vis.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500206 match self.data {
207 Data::Struct(ref d) => d.struct_token.to_tokens(tokens),
208 Data::Enum(ref d) => d.enum_token.to_tokens(tokens),
209 Data::Union(ref d) => d.union_token.to_tokens(tokens),
David Tolnayf38cdf62016-09-23 19:07:09 -0700210 }
211 self.ident.to_tokens(tokens);
212 self.generics.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500213 match self.data {
David Tolnay61037c62018-01-05 16:21:03 -0800214 Data::Struct(ref data) => match data.fields {
215 Fields::Named(ref fields) => {
216 self.generics.where_clause.to_tokens(tokens);
217 fields.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500218 }
David Tolnay61037c62018-01-05 16:21:03 -0800219 Fields::Unnamed(ref fields) => {
220 fields.to_tokens(tokens);
221 self.generics.where_clause.to_tokens(tokens);
222 TokensOrDefault(&data.semi_token).to_tokens(tokens);
223 }
224 Fields::Unit => {
225 self.generics.where_clause.to_tokens(tokens);
226 TokensOrDefault(&data.semi_token).to_tokens(tokens);
227 }
228 },
David Tolnaye3d41b72017-12-31 15:24:00 -0500229 Data::Enum(ref data) => {
David Tolnay28c1db62016-10-27 22:48:18 -0700230 self.generics.where_clause.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700231 data.brace_token.surround(tokens, |tokens| {
232 data.variants.to_tokens(tokens);
233 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700234 }
David Tolnaye3d41b72017-12-31 15:24:00 -0500235 Data::Union(ref data) => {
236 self.generics.where_clause.to_tokens(tokens);
237 data.fields.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700238 }
239 }
240 }
241 }
242}