]> git.proxmox.com Git - rustc.git/blame - vendor/syn/src/derive.rs
New upstream version 1.53.0+dfsg1
[rustc.git] / vendor / syn / src / derive.rs
CommitLineData
e74abb32
XL
1use super::*;
2use crate::punctuated::Punctuated;
3
4ast_struct! {
5 /// Data structure sent to a `proc_macro_derive` macro.
6 ///
f035d41b 7 /// *This type is available only if Syn is built with the `"derive"` feature.*
5869c6ff 8 #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
e74abb32
XL
9 pub struct DeriveInput {
10 /// Attributes tagged on the whole struct or enum.
11 pub attrs: Vec<Attribute>,
12
13 /// Visibility of the struct or enum.
14 pub vis: Visibility,
15
16 /// Name of the struct or enum.
17 pub ident: Ident,
18
19 /// Generics required to complete the definition.
20 pub generics: Generics,
21
22 /// Data within the struct or enum.
23 pub data: Data,
24 }
25}
26
27ast_enum_of_structs! {
28 /// The storage of a struct, enum or union data structure.
29 ///
f035d41b 30 /// *This type is available only if Syn is built with the `"derive"` feature.*
e74abb32
XL
31 ///
32 /// # Syntax tree enum
33 ///
34 /// This type is a [syntax tree enum].
35 ///
5869c6ff
XL
36 /// [syntax tree enum]: Expr#syntax-tree-enums
37 #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
e74abb32
XL
38 pub enum Data {
39 /// A struct input to a `proc_macro_derive` macro.
40 Struct(DataStruct),
41
42 /// An enum input to a `proc_macro_derive` macro.
43 Enum(DataEnum),
44
45 /// An untagged union input to a `proc_macro_derive` macro.
46 Union(DataUnion),
47 }
48
49 do_not_generate_to_tokens
50}
51
52ast_struct! {
53 /// A struct input to a `proc_macro_derive` macro.
54 ///
f035d41b 55 /// *This type is available only if Syn is built with the `"derive"`
e74abb32 56 /// feature.*
5869c6ff 57 #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
e74abb32
XL
58 pub struct DataStruct {
59 pub struct_token: Token![struct],
60 pub fields: Fields,
61 pub semi_token: Option<Token![;]>,
62 }
63}
64
65ast_struct! {
66 /// An enum input to a `proc_macro_derive` macro.
67 ///
f035d41b 68 /// *This type is available only if Syn is built with the `"derive"`
e74abb32 69 /// feature.*
5869c6ff 70 #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
e74abb32
XL
71 pub struct DataEnum {
72 pub enum_token: Token![enum],
73 pub brace_token: token::Brace,
74 pub variants: Punctuated<Variant, Token![,]>,
75 }
76}
77
78ast_struct! {
79 /// An untagged union input to a `proc_macro_derive` macro.
80 ///
f035d41b 81 /// *This type is available only if Syn is built with the `"derive"`
e74abb32 82 /// feature.*
5869c6ff 83 #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
e74abb32
XL
84 pub struct DataUnion {
85 pub union_token: Token![union],
86 pub fields: FieldsNamed,
87 }
88}
89
90#[cfg(feature = "parsing")]
91pub mod parsing {
92 use super::*;
e74abb32
XL
93 use crate::parse::{Parse, ParseStream, Result};
94
5869c6ff 95 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
96 impl Parse for DeriveInput {
97 fn parse(input: ParseStream) -> Result<Self> {
cdc7bbd5 98 let mut attrs = input.call(Attribute::parse_outer)?;
e74abb32
XL
99 let vis = input.parse::<Visibility>()?;
100
101 let lookahead = input.lookahead1();
102 if lookahead.peek(Token![struct]) {
103 let struct_token = input.parse::<Token![struct]>()?;
104 let ident = input.parse::<Ident>()?;
105 let generics = input.parse::<Generics>()?;
cdc7bbd5 106 let (where_clause, fields, semi) = data_struct(input, &mut attrs)?;
e74abb32
XL
107 Ok(DeriveInput {
108 attrs,
109 vis,
110 ident,
111 generics: Generics {
112 where_clause,
113 ..generics
114 },
115 data: Data::Struct(DataStruct {
116 struct_token,
117 fields,
118 semi_token: semi,
119 }),
120 })
121 } else if lookahead.peek(Token![enum]) {
122 let enum_token = input.parse::<Token![enum]>()?;
123 let ident = input.parse::<Ident>()?;
124 let generics = input.parse::<Generics>()?;
cdc7bbd5 125 let (where_clause, brace, variants) = data_enum(input, &mut attrs)?;
e74abb32
XL
126 Ok(DeriveInput {
127 attrs,
128 vis,
129 ident,
130 generics: Generics {
131 where_clause,
132 ..generics
133 },
134 data: Data::Enum(DataEnum {
135 enum_token,
136 brace_token: brace,
137 variants,
138 }),
139 })
140 } else if lookahead.peek(Token![union]) {
141 let union_token = input.parse::<Token![union]>()?;
142 let ident = input.parse::<Ident>()?;
143 let generics = input.parse::<Generics>()?;
cdc7bbd5 144 let (where_clause, fields) = data_union(input, &mut attrs)?;
e74abb32
XL
145 Ok(DeriveInput {
146 attrs,
147 vis,
148 ident,
149 generics: Generics {
150 where_clause,
151 ..generics
152 },
153 data: Data::Union(DataUnion {
154 union_token,
155 fields,
156 }),
157 })
158 } else {
159 Err(lookahead.error())
160 }
161 }
162 }
163
164 pub fn data_struct(
165 input: ParseStream,
cdc7bbd5 166 attrs: &mut Vec<Attribute>,
e74abb32
XL
167 ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
168 let mut lookahead = input.lookahead1();
169 let mut where_clause = None;
170 if lookahead.peek(Token![where]) {
171 where_clause = Some(input.parse()?);
172 lookahead = input.lookahead1();
173 }
174
175 if where_clause.is_none() && lookahead.peek(token::Paren) {
176 let fields = input.parse()?;
177
178 lookahead = input.lookahead1();
179 if lookahead.peek(Token![where]) {
180 where_clause = Some(input.parse()?);
181 lookahead = input.lookahead1();
182 }
183
184 if lookahead.peek(Token![;]) {
185 let semi = input.parse()?;
186 Ok((where_clause, Fields::Unnamed(fields), Some(semi)))
187 } else {
188 Err(lookahead.error())
189 }
190 } else if lookahead.peek(token::Brace) {
cdc7bbd5 191 let fields = data::parsing::parse_braced(input, attrs)?;
e74abb32
XL
192 Ok((where_clause, Fields::Named(fields), None))
193 } else if lookahead.peek(Token![;]) {
194 let semi = input.parse()?;
195 Ok((where_clause, Fields::Unit, Some(semi)))
196 } else {
197 Err(lookahead.error())
198 }
199 }
200
201 pub fn data_enum(
202 input: ParseStream,
cdc7bbd5 203 attrs: &mut Vec<Attribute>,
e74abb32
XL
204 ) -> Result<(
205 Option<WhereClause>,
206 token::Brace,
207 Punctuated<Variant, Token![,]>,
208 )> {
209 let where_clause = input.parse()?;
210
211 let content;
212 let brace = braced!(content in input);
cdc7bbd5 213 attr::parsing::parse_inner(&content, attrs)?;
e74abb32
XL
214 let variants = content.parse_terminated(Variant::parse)?;
215
216 Ok((where_clause, brace, variants))
217 }
218
cdc7bbd5
XL
219 pub fn data_union(
220 input: ParseStream,
221 attrs: &mut Vec<Attribute>,
222 ) -> Result<(Option<WhereClause>, FieldsNamed)> {
e74abb32 223 let where_clause = input.parse()?;
cdc7bbd5 224 let fields = data::parsing::parse_braced(input, attrs)?;
e74abb32
XL
225 Ok((where_clause, fields))
226 }
227}
228
229#[cfg(feature = "printing")]
230mod printing {
231 use super::*;
e74abb32
XL
232 use crate::attr::FilterAttrs;
233 use crate::print::TokensOrDefault;
29967ef6
XL
234 use proc_macro2::TokenStream;
235 use quote::ToTokens;
e74abb32 236
5869c6ff 237 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
238 impl ToTokens for DeriveInput {
239 fn to_tokens(&self, tokens: &mut TokenStream) {
240 for attr in self.attrs.outer() {
241 attr.to_tokens(tokens);
242 }
243 self.vis.to_tokens(tokens);
244 match &self.data {
245 Data::Struct(d) => d.struct_token.to_tokens(tokens),
246 Data::Enum(d) => d.enum_token.to_tokens(tokens),
247 Data::Union(d) => d.union_token.to_tokens(tokens),
248 }
249 self.ident.to_tokens(tokens);
250 self.generics.to_tokens(tokens);
251 match &self.data {
252 Data::Struct(data) => match &data.fields {
253 Fields::Named(fields) => {
254 self.generics.where_clause.to_tokens(tokens);
255 fields.to_tokens(tokens);
256 }
257 Fields::Unnamed(fields) => {
258 fields.to_tokens(tokens);
259 self.generics.where_clause.to_tokens(tokens);
260 TokensOrDefault(&data.semi_token).to_tokens(tokens);
261 }
262 Fields::Unit => {
263 self.generics.where_clause.to_tokens(tokens);
264 TokensOrDefault(&data.semi_token).to_tokens(tokens);
265 }
266 },
267 Data::Enum(data) => {
268 self.generics.where_clause.to_tokens(tokens);
269 data.brace_token.surround(tokens, |tokens| {
270 data.variants.to_tokens(tokens);
271 });
272 }
273 Data::Union(data) => {
274 self.generics.where_clause.to_tokens(tokens);
275 data.fields.to_tokens(tokens);
276 }
277 }
278 }
279 }
280}