]> git.proxmox.com Git - rustc.git/blame - vendor/syn/src/data.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / vendor / syn / src / data.rs
CommitLineData
e74abb32
XL
1use super::*;
2use crate::punctuated::Punctuated;
3
4ast_struct! {
5 /// An enum variant.
6 ///
7 /// *This type is available if Syn is built with the `"derive"` or `"full"`
8 /// feature.*
9 pub struct Variant {
10 /// Attributes tagged on the variant.
11 pub attrs: Vec<Attribute>,
12
13 /// Name of the variant.
14 pub ident: Ident,
15
16 /// Content stored in the variant.
17 pub fields: Fields,
18
19 /// Explicit discriminant: `Variant = 1`
20 pub discriminant: Option<(Token![=], Expr)>,
21 }
22}
23
24ast_enum_of_structs! {
25 /// Data stored within an enum variant or struct.
26 ///
27 /// *This type is available if Syn is built with the `"derive"` or `"full"`
28 /// feature.*
29 ///
30 /// # Syntax tree enum
31 ///
32 /// This type is a [syntax tree enum].
33 ///
34 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
35 //
36 // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
37 // blocked on https://github.com/rust-lang/rust/issues/62833
38 pub enum Fields {
39 /// Named fields of a struct or struct variant such as `Point { x: f64,
40 /// y: f64 }`.
41 Named(FieldsNamed),
42
43 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
44 Unnamed(FieldsUnnamed),
45
46 /// Unit struct or unit variant such as `None`.
47 Unit,
48 }
49}
50
51ast_struct! {
52 /// Named fields of a struct or struct variant such as `Point { x: f64,
53 /// y: f64 }`.
54 ///
55 /// *This type is available if Syn is built with the `"derive"` or
56 /// `"full"` feature.*
57 pub struct FieldsNamed {
58 pub brace_token: token::Brace,
59 pub named: Punctuated<Field, Token![,]>,
60 }
61}
62
63ast_struct! {
64 /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
65 ///
66 /// *This type is available if Syn is built with the `"derive"` or
67 /// `"full"` feature.*
68 pub struct FieldsUnnamed {
69 pub paren_token: token::Paren,
70 pub unnamed: Punctuated<Field, Token![,]>,
71 }
72}
73
74impl Fields {
75 /// Get an iterator over the borrowed [`Field`] items in this object. This
76 /// iterator can be used to iterate over a named or unnamed struct or
77 /// variant's fields uniformly.
78 pub fn iter(&self) -> punctuated::Iter<Field> {
79 match self {
80 Fields::Unit => crate::punctuated::empty_punctuated_iter(),
81 Fields::Named(f) => f.named.iter(),
82 Fields::Unnamed(f) => f.unnamed.iter(),
83 }
84 }
85
86 /// Get an iterator over the mutably borrowed [`Field`] items in this
87 /// object. This iterator can be used to iterate over a named or unnamed
88 /// struct or variant's fields uniformly.
89 pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
90 match self {
91 Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
92 Fields::Named(f) => f.named.iter_mut(),
93 Fields::Unnamed(f) => f.unnamed.iter_mut(),
94 }
95 }
60c5eb7d
XL
96
97 /// Returns the number of fields.
98 pub fn len(&self) -> usize {
99 match self {
100 Fields::Unit => 0,
101 Fields::Named(f) => f.named.len(),
102 Fields::Unnamed(f) => f.unnamed.len(),
103 }
104 }
105
106 /// Returns `true` if there are zero fields.
107 pub fn is_empty(&self) -> bool {
108 match self {
109 Fields::Unit => true,
110 Fields::Named(f) => f.named.is_empty(),
111 Fields::Unnamed(f) => f.unnamed.is_empty(),
112 }
113 }
e74abb32
XL
114}
115
116impl IntoIterator for Fields {
117 type Item = Field;
118 type IntoIter = punctuated::IntoIter<Field>;
119
120 fn into_iter(self) -> Self::IntoIter {
121 match self {
122 Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
123 Fields::Named(f) => f.named.into_iter(),
124 Fields::Unnamed(f) => f.unnamed.into_iter(),
125 }
126 }
127}
128
129impl<'a> IntoIterator for &'a Fields {
130 type Item = &'a Field;
131 type IntoIter = punctuated::Iter<'a, Field>;
132
133 fn into_iter(self) -> Self::IntoIter {
134 self.iter()
135 }
136}
137
138impl<'a> IntoIterator for &'a mut Fields {
139 type Item = &'a mut Field;
140 type IntoIter = punctuated::IterMut<'a, Field>;
141
142 fn into_iter(self) -> Self::IntoIter {
143 self.iter_mut()
144 }
145}
146
147ast_struct! {
148 /// A field of a struct or enum variant.
149 ///
150 /// *This type is available if Syn is built with the `"derive"` or `"full"`
151 /// feature.*
152 pub struct Field {
153 /// Attributes tagged on the field.
154 pub attrs: Vec<Attribute>,
155
156 /// Visibility of the field.
157 pub vis: Visibility,
158
159 /// Name of the field, if any.
160 ///
161 /// Fields of tuple structs have no names.
162 pub ident: Option<Ident>,
163
164 pub colon_token: Option<Token![:]>,
165
166 /// Type of the field.
167 pub ty: Type,
168 }
169}
170
171ast_enum_of_structs! {
172 /// The visibility level of an item: inherited or `pub` or
173 /// `pub(restricted)`.
174 ///
175 /// *This type is available if Syn is built with the `"derive"` or `"full"`
176 /// feature.*
177 ///
178 /// # Syntax tree enum
179 ///
180 /// This type is a [syntax tree enum].
181 ///
182 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
183 //
184 // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
185 // blocked on https://github.com/rust-lang/rust/issues/62833
186 pub enum Visibility {
187 /// A public visibility level: `pub`.
188 Public(VisPublic),
189
190 /// A crate-level visibility: `crate`.
191 Crate(VisCrate),
192
193 /// A visibility level restricted to some path: `pub(self)` or
194 /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
195 Restricted(VisRestricted),
196
197 /// An inherited visibility, which usually means private.
198 Inherited,
199 }
200}
201
202ast_struct! {
203 /// A public visibility level: `pub`.
204 ///
205 /// *This type is available if Syn is built with the `"derive"` or
206 /// `"full"` feature.*
207 pub struct VisPublic {
208 pub pub_token: Token![pub],
209 }
210}
211
212ast_struct! {
213 /// A crate-level visibility: `crate`.
214 ///
215 /// *This type is available if Syn is built with the `"derive"` or
216 /// `"full"` feature.*
217 pub struct VisCrate {
218 pub crate_token: Token![crate],
219 }
220}
221
222ast_struct! {
223 /// A visibility level restricted to some path: `pub(self)` or
224 /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
225 ///
226 /// *This type is available if Syn is built with the `"derive"` or
227 /// `"full"` feature.*
228 pub struct VisRestricted {
229 pub pub_token: Token![pub],
230 pub paren_token: token::Paren,
231 pub in_token: Option<Token![in]>,
232 pub path: Box<Path>,
233 }
234}
235
236#[cfg(feature = "parsing")]
237pub mod parsing {
238 use super::*;
239
240 use crate::ext::IdentExt;
60c5eb7d 241 use crate::parse::discouraged::Speculative;
e74abb32
XL
242 use crate::parse::{Parse, ParseStream, Result};
243
244 impl Parse for Variant {
245 fn parse(input: ParseStream) -> Result<Self> {
246 Ok(Variant {
247 attrs: input.call(Attribute::parse_outer)?,
248 ident: input.parse()?,
249 fields: {
250 if input.peek(token::Brace) {
251 Fields::Named(input.parse()?)
252 } else if input.peek(token::Paren) {
253 Fields::Unnamed(input.parse()?)
254 } else {
255 Fields::Unit
256 }
257 },
258 discriminant: {
259 if input.peek(Token![=]) {
260 let eq_token: Token![=] = input.parse()?;
261 let discriminant: Expr = input.parse()?;
262 Some((eq_token, discriminant))
263 } else {
264 None
265 }
266 },
267 })
268 }
269 }
270
271 impl Parse for FieldsNamed {
272 fn parse(input: ParseStream) -> Result<Self> {
273 let content;
274 Ok(FieldsNamed {
275 brace_token: braced!(content in input),
276 named: content.parse_terminated(Field::parse_named)?,
277 })
278 }
279 }
280
281 impl Parse for FieldsUnnamed {
282 fn parse(input: ParseStream) -> Result<Self> {
283 let content;
284 Ok(FieldsUnnamed {
285 paren_token: parenthesized!(content in input),
286 unnamed: content.parse_terminated(Field::parse_unnamed)?,
287 })
288 }
289 }
290
291 impl Field {
292 /// Parses a named (braced struct) field.
293 pub fn parse_named(input: ParseStream) -> Result<Self> {
294 Ok(Field {
295 attrs: input.call(Attribute::parse_outer)?,
296 vis: input.parse()?,
297 ident: Some(input.parse()?),
298 colon_token: Some(input.parse()?),
299 ty: input.parse()?,
300 })
301 }
302
303 /// Parses an unnamed (tuple struct) field.
304 pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
305 Ok(Field {
306 attrs: input.call(Attribute::parse_outer)?,
307 vis: input.parse()?,
308 ident: None,
309 colon_token: None,
310 ty: input.parse()?,
311 })
312 }
313 }
314
315 impl Parse for Visibility {
316 fn parse(input: ParseStream) -> Result<Self> {
317 if input.peek(Token![pub]) {
318 Self::parse_pub(input)
319 } else if input.peek(Token![crate]) {
320 Self::parse_crate(input)
321 } else {
322 Ok(Visibility::Inherited)
323 }
324 }
325 }
326
327 impl Visibility {
328 fn parse_pub(input: ParseStream) -> Result<Self> {
329 let pub_token = input.parse::<Token![pub]>()?;
330
331 if input.peek(token::Paren) {
e74abb32 332 let ahead = input.fork();
e74abb32 333
60c5eb7d
XL
334 let content;
335 let paren_token = parenthesized!(content in ahead);
e74abb32
XL
336 if content.peek(Token![crate])
337 || content.peek(Token![self])
338 || content.peek(Token![super])
339 {
60c5eb7d
XL
340 let path = content.call(Ident::parse_any)?;
341
342 // Ensure there are no additional tokens within `content`.
343 // Without explicitly checking, we may misinterpret a tuple
344 // field as a restricted visibility, causing a parse error.
345 // e.g. `pub (crate::A, crate::B)` (Issue #720).
346 if content.is_empty() {
347 input.advance_to(&ahead);
348 return Ok(Visibility::Restricted(VisRestricted {
349 pub_token,
350 paren_token,
351 in_token: None,
352 path: Box::new(Path::from(path)),
353 }));
354 }
e74abb32 355 } else if content.peek(Token![in]) {
60c5eb7d
XL
356 let in_token: Token![in] = content.parse()?;
357 let path = content.call(Path::parse_mod_style)?;
358
359 input.advance_to(&ahead);
e74abb32
XL
360 return Ok(Visibility::Restricted(VisRestricted {
361 pub_token,
60c5eb7d
XL
362 paren_token,
363 in_token: Some(in_token),
364 path: Box::new(path),
e74abb32
XL
365 }));
366 }
367 }
368
369 Ok(Visibility::Public(VisPublic { pub_token }))
370 }
371
372 fn parse_crate(input: ParseStream) -> Result<Self> {
373 if input.peek2(Token![::]) {
374 Ok(Visibility::Inherited)
375 } else {
376 Ok(Visibility::Crate(VisCrate {
377 crate_token: input.parse()?,
378 }))
379 }
380 }
381 }
382}
383
384#[cfg(feature = "printing")]
385mod printing {
386 use super::*;
387
388 use proc_macro2::TokenStream;
389 use quote::{ToTokens, TokenStreamExt};
390
391 use crate::print::TokensOrDefault;
392
393 impl ToTokens for Variant {
394 fn to_tokens(&self, tokens: &mut TokenStream) {
395 tokens.append_all(&self.attrs);
396 self.ident.to_tokens(tokens);
397 self.fields.to_tokens(tokens);
398 if let Some((eq_token, disc)) = &self.discriminant {
399 eq_token.to_tokens(tokens);
400 disc.to_tokens(tokens);
401 }
402 }
403 }
404
405 impl ToTokens for FieldsNamed {
406 fn to_tokens(&self, tokens: &mut TokenStream) {
407 self.brace_token.surround(tokens, |tokens| {
408 self.named.to_tokens(tokens);
409 });
410 }
411 }
412
413 impl ToTokens for FieldsUnnamed {
414 fn to_tokens(&self, tokens: &mut TokenStream) {
415 self.paren_token.surround(tokens, |tokens| {
416 self.unnamed.to_tokens(tokens);
417 });
418 }
419 }
420
421 impl ToTokens for Field {
422 fn to_tokens(&self, tokens: &mut TokenStream) {
423 tokens.append_all(&self.attrs);
424 self.vis.to_tokens(tokens);
425 if let Some(ident) = &self.ident {
426 ident.to_tokens(tokens);
427 TokensOrDefault(&self.colon_token).to_tokens(tokens);
428 }
429 self.ty.to_tokens(tokens);
430 }
431 }
432
433 impl ToTokens for VisPublic {
434 fn to_tokens(&self, tokens: &mut TokenStream) {
435 self.pub_token.to_tokens(tokens)
436 }
437 }
438
439 impl ToTokens for VisCrate {
440 fn to_tokens(&self, tokens: &mut TokenStream) {
441 self.crate_token.to_tokens(tokens);
442 }
443 }
444
445 impl ToTokens for VisRestricted {
446 fn to_tokens(&self, tokens: &mut TokenStream) {
447 self.pub_token.to_tokens(tokens);
448 self.paren_token.surround(tokens, |tokens| {
449 // TODO: If we have a path which is not "self" or "super" or
450 // "crate", automatically add the "in" token.
451 self.in_token.to_tokens(tokens);
452 self.path.to_tokens(tokens);
453 });
454 }
455 }
456}