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