blob: 48ae7e46ee2769706aecdbfb89f7496cc2022d81 [file] [log] [blame]
David Tolnayf38cdf62016-09-23 19:07:09 -07001use super::*;
Nika Layzell5680dcc2018-01-16 15:14:27 -05002use punctuated::Punctuated;
David Tolnayf38cdf62016-09-23 19:07:09 -07003
Alex Crichton62a0a592017-05-22 13:58:53 -07004ast_struct! {
David Tolnaye3d41b72017-12-31 15:24:00 -05005 /// Data structure sent to a `proc_macro_derive` macro.
David Tolnay461d98e2018-01-07 11:07:19 -08006 ///
7 /// *This type is available if Syn is built with the `"derive"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -07008 pub struct DeriveInput {
David Tolnay4a3f59a2017-12-28 21:21:12 -05009 /// Attributes tagged on the whole struct or enum.
10 pub attrs: Vec<Attribute>,
Clar Charrd22b5702017-03-10 15:24:56 -050011
Alex Crichton62a0a592017-05-22 13:58:53 -070012 /// Visibility of the struct or enum.
13 pub vis: Visibility,
Clar Charrd22b5702017-03-10 15:24:56 -050014
David Tolnay4a3f59a2017-12-28 21:21:12 -050015 /// Name of the struct or enum.
16 pub ident: Ident,
Clar Charrd22b5702017-03-10 15:24:56 -050017
Alex Crichton62a0a592017-05-22 13:58:53 -070018 /// Generics required to complete the definition.
19 pub generics: Generics,
Clar Charrd22b5702017-03-10 15:24:56 -050020
Alex Crichton62a0a592017-05-22 13:58:53 -070021 /// Data within the struct or enum.
David Tolnaye3d41b72017-12-31 15:24:00 -050022 pub data: Data,
Alex Crichton62a0a592017-05-22 13:58:53 -070023 }
David Tolnayf38cdf62016-09-23 19:07:09 -070024}
25
Alex Crichtonccbb45d2017-05-23 10:58:24 -070026ast_enum_of_structs! {
David Tolnaye3d41b72017-12-31 15:24:00 -050027 /// The storage of a struct, enum or union data structure.
David Tolnay614a0142018-01-07 10:25:43 -080028 ///
David Tolnay461d98e2018-01-07 11:07:19 -080029 /// *This type is available if Syn is built with the `"derive"` feature.*
30 ///
David Tolnay614a0142018-01-07 10:25:43 -080031 /// # Syntax tree enum
32 ///
33 /// This type is a [syntax tree enum].
34 ///
35 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
David Tolnaye3d41b72017-12-31 15:24:00 -050036 pub enum Data {
David Tolnayd2aa8832018-01-07 01:05:09 -080037 /// A struct input to a `proc_macro_derive` macro.
David Tolnay461d98e2018-01-07 11:07:19 -080038 ///
39 /// *This type is available if Syn is built with the `"derive"`
40 /// feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050041 pub Struct(DataStruct {
42 pub struct_token: Token![struct],
43 pub fields: Fields,
44 pub semi_token: Option<Token![;]>,
45 }),
46
David Tolnayd2aa8832018-01-07 01:05:09 -080047 /// An enum input to a `proc_macro_derive` macro.
David Tolnay461d98e2018-01-07 11:07:19 -080048 ///
49 /// *This type is available if Syn is built with the `"derive"`
50 /// feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050051 pub Enum(DataEnum {
David Tolnayf8db7ba2017-11-11 22:52:16 -080052 pub enum_token: Token![enum],
David Tolnay32954ef2017-12-26 22:43:16 -050053 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -050054 pub variants: Punctuated<Variant, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070055 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070056
David Tolnayd2aa8832018-01-07 01:05:09 -080057 /// A tagged union input to a `proc_macro_derive` macro.
David Tolnay461d98e2018-01-07 11:07:19 -080058 ///
59 /// *This type is available if Syn is built with the `"derive"`
60 /// feature.*
David Tolnaye3d41b72017-12-31 15:24:00 -050061 pub Union(DataUnion {
62 pub union_token: Token![union],
63 pub fields: FieldsNamed,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070064 }),
Alex Crichton62a0a592017-05-22 13:58:53 -070065 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070066
67 do_not_generate_to_tokens
David Tolnayf38cdf62016-09-23 19:07:09 -070068}
69
70#[cfg(feature = "parsing")]
71pub mod parsing {
72 use super::*;
David Tolnayf38cdf62016-09-23 19:07:09 -070073
David Tolnay3ecbcaf2018-08-25 23:03:26 -040074 use parse::{Parse, ParseStream, Result};
Alex Crichton954046c2017-05-30 21:49:42 -070075
David Tolnay3ecbcaf2018-08-25 23:03:26 -040076 impl Parse for DeriveInput {
77 fn parse(input: ParseStream) -> Result<Self> {
78 let attrs = input.call(Attribute::parse_outer)?;
79 let vis = input.parse::<Visibility>()?;
David Tolnayb022d062018-07-21 18:59:36 -070080
David Tolnay3ecbcaf2018-08-25 23:03:26 -040081 let lookahead = input.lookahead1();
82 if lookahead.peek(Token![struct]) {
83 let struct_token = input.parse::<Token![struct]>()?;
84 let ident = input.parse::<Ident>()?;
David Tolnay1b8e2852018-08-26 08:25:18 -040085 let generics = input.parse::<Generics>()?;
David Tolnay3ecbcaf2018-08-25 23:03:26 -040086 let (where_clause, fields, semi) = data_struct(input)?;
87 Ok(DeriveInput {
Michael Layzell92639a52017-06-01 00:07:44 -040088 attrs: attrs,
David Tolnay3ecbcaf2018-08-25 23:03:26 -040089 vis: vis,
90 ident: ident,
Michael Layzell92639a52017-06-01 00:07:44 -040091 generics: Generics {
David Tolnay3ecbcaf2018-08-25 23:03:26 -040092 where_clause: where_clause,
David Tolnayd142fc52018-07-21 15:09:53 -070093 ..generics
Michael Layzell92639a52017-06-01 00:07:44 -040094 },
David Tolnaye3d41b72017-12-31 15:24:00 -050095 data: Data::Struct(DataStruct {
David Tolnay3ecbcaf2018-08-25 23:03:26 -040096 struct_token: struct_token,
David Tolnaye3d41b72017-12-31 15:24:00 -050097 fields: fields,
Michael Layzell92639a52017-06-01 00:07:44 -040098 semi_token: semi,
99 }),
100 })
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400101 } else if lookahead.peek(Token![enum]) {
102 let enum_token = input.parse::<Token![enum]>()?;
103 let ident = input.parse::<Ident>()?;
David Tolnay1b8e2852018-08-26 08:25:18 -0400104 let generics = input.parse::<Generics>()?;
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400105 let (where_clause, brace, variants) = data_enum(input)?;
106 Ok(DeriveInput {
Michael Layzell92639a52017-06-01 00:07:44 -0400107 attrs: attrs,
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400108 vis: vis,
109 ident: ident,
Michael Layzell92639a52017-06-01 00:07:44 -0400110 generics: Generics {
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400111 where_clause: where_clause,
David Tolnayd142fc52018-07-21 15:09:53 -0700112 ..generics
Michael Layzell92639a52017-06-01 00:07:44 -0400113 },
David Tolnaye3d41b72017-12-31 15:24:00 -0500114 data: Data::Enum(DataEnum {
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400115 enum_token: enum_token,
Michael Layzell92639a52017-06-01 00:07:44 -0400116 brace_token: brace,
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400117 variants: variants,
Michael Layzell92639a52017-06-01 00:07:44 -0400118 }),
119 })
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400120 } else if lookahead.peek(Token![union]) {
121 let union_token = input.parse::<Token![union]>()?;
122 let ident = input.parse::<Ident>()?;
David Tolnay1b8e2852018-08-26 08:25:18 -0400123 let generics = input.parse::<Generics>()?;
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400124 let (where_clause, fields) = data_union(input)?;
125 Ok(DeriveInput {
David Tolnayb022d062018-07-21 18:59:36 -0700126 attrs: attrs,
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400127 vis: vis,
128 ident: ident,
David Tolnayb022d062018-07-21 18:59:36 -0700129 generics: Generics {
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400130 where_clause: where_clause,
David Tolnayb022d062018-07-21 18:59:36 -0700131 ..generics
132 },
133 data: Data::Union(DataUnion {
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400134 union_token: union_token,
David Tolnayb022d062018-07-21 18:59:36 -0700135 fields: fields,
136 }),
137 })
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400138 } else {
139 Err(lookahead.error())
140 }
Alex Crichton954046c2017-05-30 21:49:42 -0700141 }
142 }
143
David Tolnay6a170ce2018-08-26 22:29:24 -0700144 pub fn data_struct(
145 input: ParseStream,
146 ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400147 let mut lookahead = input.lookahead1();
148 let mut where_clause = None;
149 if lookahead.peek(Token![where]) {
David Tolnay1b8e2852018-08-26 08:25:18 -0400150 where_clause = Some(input.parse()?);
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400151 lookahead = input.lookahead1();
152 }
Alex Crichton954046c2017-05-30 21:49:42 -0700153
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400154 if where_clause.is_none() && lookahead.peek(token::Paren) {
155 let fields = input.parse()?;
David Tolnayb022d062018-07-21 18:59:36 -0700156
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400157 lookahead = input.lookahead1();
158 if lookahead.peek(Token![where]) {
David Tolnay1b8e2852018-08-26 08:25:18 -0400159 where_clause = Some(input.parse()?);
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400160 lookahead = input.lookahead1();
161 }
162
163 if lookahead.peek(Token![;]) {
164 let semi = input.parse()?;
165 Ok((where_clause, Fields::Unnamed(fields), Some(semi)))
166 } else {
167 Err(lookahead.error())
168 }
169 } else if lookahead.peek(token::Brace) {
170 let fields = input.parse()?;
171 Ok((where_clause, Fields::Named(fields), None))
172 } else if lookahead.peek(Token![;]) {
173 let semi = input.parse()?;
174 Ok((where_clause, Fields::Unit, Some(semi)))
175 } else {
176 Err(lookahead.error())
177 }
178 }
179
David Tolnay6a170ce2018-08-26 22:29:24 -0700180 pub fn data_enum(
David Tolnay4fb71232018-08-25 23:14:50 -0400181 input: ParseStream,
182 ) -> Result<(
183 Option<WhereClause>,
184 token::Brace,
185 Punctuated<Variant, Token![,]>,
186 )> {
David Tolnay1b8e2852018-08-26 08:25:18 -0400187 let where_clause = input.parse()?;
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400188
189 let content;
190 let brace = braced!(content in input);
David Tolnay60484fe2018-08-30 18:43:04 -0700191 let variants = content.parse_terminated(Variant::parse)?;
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400192
193 Ok((where_clause, brace, variants))
194 }
195
David Tolnay6a170ce2018-08-26 22:29:24 -0700196 pub fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
David Tolnay1b8e2852018-08-26 08:25:18 -0400197 let where_clause = input.parse()?;
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400198 let fields = input.parse()?;
David Tolnay3ecbcaf2018-08-25 23:03:26 -0400199 Ok((where_clause, fields))
200 }
David Tolnayf38cdf62016-09-23 19:07:09 -0700201}
202
David Tolnayc2dfbf42016-09-23 23:52:15 -0700203#[cfg(feature = "printing")]
David Tolnayf38cdf62016-09-23 19:07:09 -0700204mod printing {
205 use super::*;
David Tolnay64023912018-08-31 09:51:12 -0700206
Alex Crichtona74a1c82018-05-16 10:20:44 -0700207 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700208 use quote::ToTokens;
David Tolnayf38cdf62016-09-23 19:07:09 -0700209
David Tolnay64023912018-08-31 09:51:12 -0700210 use attr::FilterAttrs;
211 use print::TokensOrDefault;
212
David Tolnay0e837402016-12-22 17:25:55 -0500213 impl ToTokens for DeriveInput {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700214 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay4a51dc72016-10-01 00:40:31 -0700215 for attr in self.attrs.outer() {
David Tolnayf38cdf62016-09-23 19:07:09 -0700216 attr.to_tokens(tokens);
217 }
David Tolnay47a877c2016-10-01 16:50:55 -0700218 self.vis.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500219 match self.data {
220 Data::Struct(ref d) => d.struct_token.to_tokens(tokens),
221 Data::Enum(ref d) => d.enum_token.to_tokens(tokens),
222 Data::Union(ref d) => d.union_token.to_tokens(tokens),
David Tolnayf38cdf62016-09-23 19:07:09 -0700223 }
224 self.ident.to_tokens(tokens);
225 self.generics.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500226 match self.data {
David Tolnay61037c62018-01-05 16:21:03 -0800227 Data::Struct(ref data) => match data.fields {
228 Fields::Named(ref fields) => {
229 self.generics.where_clause.to_tokens(tokens);
230 fields.to_tokens(tokens);
David Tolnaye3d41b72017-12-31 15:24:00 -0500231 }
David Tolnay61037c62018-01-05 16:21:03 -0800232 Fields::Unnamed(ref fields) => {
233 fields.to_tokens(tokens);
234 self.generics.where_clause.to_tokens(tokens);
235 TokensOrDefault(&data.semi_token).to_tokens(tokens);
236 }
237 Fields::Unit => {
238 self.generics.where_clause.to_tokens(tokens);
239 TokensOrDefault(&data.semi_token).to_tokens(tokens);
240 }
241 },
David Tolnaye3d41b72017-12-31 15:24:00 -0500242 Data::Enum(ref data) => {
David Tolnay28c1db62016-10-27 22:48:18 -0700243 self.generics.where_clause.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700244 data.brace_token.surround(tokens, |tokens| {
245 data.variants.to_tokens(tokens);
246 });
David Tolnayf38cdf62016-09-23 19:07:09 -0700247 }
David Tolnaye3d41b72017-12-31 15:24:00 -0500248 Data::Union(ref data) => {
249 self.generics.where_clause.to_tokens(tokens);
250 data.fields.to_tokens(tokens);
David Tolnayf38cdf62016-09-23 19:07:09 -0700251 }
252 }
253 }
254 }
255}