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