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(if input.peek(Token![_]) { 317 input.call(Ident::parse_any) 318 } else { 319 input.parse() 320 }?), 321 colon_token: Some(input.parse()?), 322 ty: input.parse()?, 323 }) 324 } 325 326 /// Parses an unnamed (tuple struct) field. 327 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] parse_unnamed(input: ParseStream) -> Result<Self>328 pub fn parse_unnamed(input: ParseStream) -> Result<Self> { 329 Ok(Field { 330 attrs: input.call(Attribute::parse_outer)?, 331 vis: input.parse()?, 332 ident: None, 333 colon_token: None, 334 ty: input.parse()?, 335 }) 336 } 337 } 338 339 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 340 impl Parse for Visibility { parse(input: ParseStream) -> Result<Self>341 fn parse(input: ParseStream) -> Result<Self> { 342 // Recognize an empty None-delimited group, as produced by a $:vis 343 // matcher that matched no tokens. 344 if input.peek(token::Group) { 345 let ahead = input.fork(); 346 let group = crate::group::parse_group(&ahead)?; 347 if group.content.is_empty() { 348 input.advance_to(&ahead); 349 return Ok(Visibility::Inherited); 350 } 351 } 352 353 if input.peek(Token![pub]) { 354 Self::parse_pub(input) 355 } else if input.peek(Token![crate]) { 356 Self::parse_crate(input) 357 } else { 358 Ok(Visibility::Inherited) 359 } 360 } 361 } 362 363 impl Visibility { parse_pub(input: ParseStream) -> Result<Self>364 fn parse_pub(input: ParseStream) -> Result<Self> { 365 let pub_token = input.parse::<Token![pub]>()?; 366 367 if input.peek(token::Paren) { 368 let ahead = input.fork(); 369 370 let content; 371 let paren_token = parenthesized!(content in ahead); 372 if content.peek(Token![crate]) 373 || content.peek(Token![self]) 374 || content.peek(Token![super]) 375 { 376 let path = content.call(Ident::parse_any)?; 377 378 // Ensure there are no additional tokens within `content`. 379 // Without explicitly checking, we may misinterpret a tuple 380 // field as a restricted visibility, causing a parse error. 381 // e.g. `pub (crate::A, crate::B)` (Issue #720). 382 if content.is_empty() { 383 input.advance_to(&ahead); 384 return Ok(Visibility::Restricted(VisRestricted { 385 pub_token, 386 paren_token, 387 in_token: None, 388 path: Box::new(Path::from(path)), 389 })); 390 } 391 } else if content.peek(Token![in]) { 392 let in_token: Token![in] = content.parse()?; 393 let path = content.call(Path::parse_mod_style)?; 394 395 input.advance_to(&ahead); 396 return Ok(Visibility::Restricted(VisRestricted { 397 pub_token, 398 paren_token, 399 in_token: Some(in_token), 400 path: Box::new(path), 401 })); 402 } 403 } 404 405 Ok(Visibility::Public(VisPublic { pub_token })) 406 } 407 parse_crate(input: ParseStream) -> Result<Self>408 fn parse_crate(input: ParseStream) -> Result<Self> { 409 if input.peek2(Token![::]) { 410 Ok(Visibility::Inherited) 411 } else { 412 Ok(Visibility::Crate(VisCrate { 413 crate_token: input.parse()?, 414 })) 415 } 416 } 417 418 #[cfg(feature = "full")] is_some(&self) -> bool419 pub(crate) fn is_some(&self) -> bool { 420 match self { 421 Visibility::Inherited => false, 422 _ => true, 423 } 424 } 425 } 426 } 427 428 #[cfg(feature = "printing")] 429 mod printing { 430 use super::*; 431 use crate::print::TokensOrDefault; 432 use proc_macro2::TokenStream; 433 use quote::{ToTokens, TokenStreamExt}; 434 435 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 436 impl ToTokens for Variant { to_tokens(&self, tokens: &mut TokenStream)437 fn to_tokens(&self, tokens: &mut TokenStream) { 438 tokens.append_all(&self.attrs); 439 self.ident.to_tokens(tokens); 440 self.fields.to_tokens(tokens); 441 if let Some((eq_token, disc)) = &self.discriminant { 442 eq_token.to_tokens(tokens); 443 disc.to_tokens(tokens); 444 } 445 } 446 } 447 448 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 449 impl ToTokens for FieldsNamed { to_tokens(&self, tokens: &mut TokenStream)450 fn to_tokens(&self, tokens: &mut TokenStream) { 451 self.brace_token.surround(tokens, |tokens| { 452 self.named.to_tokens(tokens); 453 }); 454 } 455 } 456 457 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 458 impl ToTokens for FieldsUnnamed { to_tokens(&self, tokens: &mut TokenStream)459 fn to_tokens(&self, tokens: &mut TokenStream) { 460 self.paren_token.surround(tokens, |tokens| { 461 self.unnamed.to_tokens(tokens); 462 }); 463 } 464 } 465 466 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 467 impl ToTokens for Field { to_tokens(&self, tokens: &mut TokenStream)468 fn to_tokens(&self, tokens: &mut TokenStream) { 469 tokens.append_all(&self.attrs); 470 self.vis.to_tokens(tokens); 471 if let Some(ident) = &self.ident { 472 ident.to_tokens(tokens); 473 TokensOrDefault(&self.colon_token).to_tokens(tokens); 474 } 475 self.ty.to_tokens(tokens); 476 } 477 } 478 479 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 480 impl ToTokens for VisPublic { to_tokens(&self, tokens: &mut TokenStream)481 fn to_tokens(&self, tokens: &mut TokenStream) { 482 self.pub_token.to_tokens(tokens); 483 } 484 } 485 486 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 487 impl ToTokens for VisCrate { to_tokens(&self, tokens: &mut TokenStream)488 fn to_tokens(&self, tokens: &mut TokenStream) { 489 self.crate_token.to_tokens(tokens); 490 } 491 } 492 493 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 494 impl ToTokens for VisRestricted { to_tokens(&self, tokens: &mut TokenStream)495 fn to_tokens(&self, tokens: &mut TokenStream) { 496 self.pub_token.to_tokens(tokens); 497 self.paren_token.surround(tokens, |tokens| { 498 // TODO: If we have a path which is not "self" or "super" or 499 // "crate", automatically add the "in" token. 500 self.in_token.to_tokens(tokens); 501 self.path.to_tokens(tokens); 502 }); 503 } 504 } 505 } 506