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