Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/syn/derive.rs
38271 views
1
// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3
use crate::attr::Attribute;
4
use crate::data::{Fields, FieldsNamed, Variant};
5
use crate::generics::Generics;
6
use crate::ident::Ident;
7
use crate::punctuated::Punctuated;
8
use crate::restriction::Visibility;
9
use crate::token;
10
11
ast_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
23
ast_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
39
ast_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
49
ast_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
59
ast_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")]
69
pub(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")]
210
mod 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
}
262
263