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