]> git.proxmox.com Git - cargo.git/blob - vendor/syn/src/derive.rs
New upstream version 0.33.0
[cargo.git] / vendor / syn / src / derive.rs
1 use super::*;
2 use punctuated::Punctuated;
3
4 ast_struct! {
5 /// Data structure sent to a `proc_macro_derive` macro.
6 ///
7 /// *This type is available if Syn is built with the `"derive"` feature.*
8 pub struct DeriveInput {
9 /// Attributes tagged on the whole struct or enum.
10 pub attrs: Vec<Attribute>,
11
12 /// Visibility of the struct or enum.
13 pub vis: Visibility,
14
15 /// Name of the struct or enum.
16 pub ident: Ident,
17
18 /// Generics required to complete the definition.
19 pub generics: Generics,
20
21 /// Data within the struct or enum.
22 pub data: Data,
23 }
24 }
25
26 ast_enum_of_structs! {
27 /// The storage of a struct, enum or union data structure.
28 ///
29 /// *This type is available if Syn is built with the `"derive"` feature.*
30 ///
31 /// # Syntax tree enum
32 ///
33 /// This type is a [syntax tree enum].
34 ///
35 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
36 pub enum Data {
37 /// A struct input to a `proc_macro_derive` macro.
38 ///
39 /// *This type is available if Syn is built with the `"derive"`
40 /// feature.*
41 pub Struct(DataStruct {
42 pub struct_token: Token![struct],
43 pub fields: Fields,
44 pub semi_token: Option<Token![;]>,
45 }),
46
47 /// An enum input to a `proc_macro_derive` macro.
48 ///
49 /// *This type is available if Syn is built with the `"derive"`
50 /// feature.*
51 pub Enum(DataEnum {
52 pub enum_token: Token![enum],
53 pub brace_token: token::Brace,
54 pub variants: Punctuated<Variant, Token![,]>,
55 }),
56
57 /// A tagged union input to a `proc_macro_derive` macro.
58 ///
59 /// *This type is available if Syn is built with the `"derive"`
60 /// feature.*
61 pub Union(DataUnion {
62 pub union_token: Token![union],
63 pub fields: FieldsNamed,
64 }),
65 }
66
67 do_not_generate_to_tokens
68 }
69
70 #[cfg(feature = "parsing")]
71 pub mod parsing {
72 use super::*;
73
74 use parse::{Parse, ParseStream, Result};
75
76 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>()?;
80
81 let lookahead = input.lookahead1();
82 if lookahead.peek(Token![struct]) {
83 let struct_token = input.parse::<Token![struct]>()?;
84 let ident = input.parse::<Ident>()?;
85 let generics = input.parse::<Generics>()?;
86 let (where_clause, fields, semi) = data_struct(input)?;
87 Ok(DeriveInput {
88 attrs: attrs,
89 vis: vis,
90 ident: ident,
91 generics: Generics {
92 where_clause: where_clause,
93 ..generics
94 },
95 data: Data::Struct(DataStruct {
96 struct_token: struct_token,
97 fields: fields,
98 semi_token: semi,
99 }),
100 })
101 } else if lookahead.peek(Token![enum]) {
102 let enum_token = input.parse::<Token![enum]>()?;
103 let ident = input.parse::<Ident>()?;
104 let generics = input.parse::<Generics>()?;
105 let (where_clause, brace, variants) = data_enum(input)?;
106 Ok(DeriveInput {
107 attrs: attrs,
108 vis: vis,
109 ident: ident,
110 generics: Generics {
111 where_clause: where_clause,
112 ..generics
113 },
114 data: Data::Enum(DataEnum {
115 enum_token: enum_token,
116 brace_token: brace,
117 variants: variants,
118 }),
119 })
120 } else if lookahead.peek(Token![union]) {
121 let union_token = input.parse::<Token![union]>()?;
122 let ident = input.parse::<Ident>()?;
123 let generics = input.parse::<Generics>()?;
124 let (where_clause, fields) = data_union(input)?;
125 Ok(DeriveInput {
126 attrs: attrs,
127 vis: vis,
128 ident: ident,
129 generics: Generics {
130 where_clause: where_clause,
131 ..generics
132 },
133 data: Data::Union(DataUnion {
134 union_token: union_token,
135 fields: fields,
136 }),
137 })
138 } else {
139 Err(lookahead.error())
140 }
141 }
142 }
143
144 pub fn data_struct(
145 input: ParseStream,
146 ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
147 let mut lookahead = input.lookahead1();
148 let mut where_clause = None;
149 if lookahead.peek(Token![where]) {
150 where_clause = Some(input.parse()?);
151 lookahead = input.lookahead1();
152 }
153
154 if where_clause.is_none() && lookahead.peek(token::Paren) {
155 let fields = input.parse()?;
156
157 lookahead = input.lookahead1();
158 if lookahead.peek(Token![where]) {
159 where_clause = Some(input.parse()?);
160 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
180 pub fn data_enum(
181 input: ParseStream,
182 ) -> Result<(
183 Option<WhereClause>,
184 token::Brace,
185 Punctuated<Variant, Token![,]>,
186 )> {
187 let where_clause = input.parse()?;
188
189 let content;
190 let brace = braced!(content in input);
191 let variants = content.parse_terminated(Variant::parse)?;
192
193 Ok((where_clause, brace, variants))
194 }
195
196 pub fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
197 let where_clause = input.parse()?;
198 let fields = input.parse()?;
199 Ok((where_clause, fields))
200 }
201 }
202
203 #[cfg(feature = "printing")]
204 mod printing {
205 use super::*;
206
207 use proc_macro2::TokenStream;
208 use quote::ToTokens;
209
210 use attr::FilterAttrs;
211 use print::TokensOrDefault;
212
213 impl ToTokens for DeriveInput {
214 fn to_tokens(&self, tokens: &mut TokenStream) {
215 for attr in self.attrs.outer() {
216 attr.to_tokens(tokens);
217 }
218 self.vis.to_tokens(tokens);
219 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),
223 }
224 self.ident.to_tokens(tokens);
225 self.generics.to_tokens(tokens);
226 match self.data {
227 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);
231 }
232 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 },
242 Data::Enum(ref data) => {
243 self.generics.where_clause.to_tokens(tokens);
244 data.brace_token.surround(tokens, |tokens| {
245 data.variants.to_tokens(tokens);
246 });
247 }
248 Data::Union(ref data) => {
249 self.generics.where_clause.to_tokens(tokens);
250 data.fields.to_tokens(tokens);
251 }
252 }
253 }
254 }
255 }