| use super::*; |
| |
| ast_enum! { |
| /// The visibility level of an item: inherited or `pub` or |
| /// `pub(restricted)`. |
| /// |
| /// # Syntax tree enum |
| /// |
| /// This type is a [syntax tree enum]. |
| /// |
| /// [syntax tree enum]: Expr#syntax-tree-enums |
| #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] |
| pub enum Visibility { |
| /// A public visibility level: `pub`. |
| Public(Token![pub]), |
| |
| /// A visibility level restricted to some path: `pub(self)` or |
| /// `pub(super)` or `pub(crate)` or `pub(in some::module)`. |
| Restricted(VisRestricted), |
| |
| /// An inherited visibility, which usually means private. |
| Inherited, |
| } |
| } |
| |
| ast_struct! { |
| /// A visibility level restricted to some path: `pub(self)` or |
| /// `pub(super)` or `pub(crate)` or `pub(in some::module)`. |
| #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] |
| pub struct VisRestricted { |
| pub pub_token: Token![pub], |
| pub paren_token: token::Paren, |
| pub in_token: Option<Token![in]>, |
| pub path: Box<Path>, |
| } |
| } |
| |
| ast_enum! { |
| /// Unused, but reserved for RFC 3323 restrictions. |
| #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] |
| #[non_exhaustive] |
| pub enum FieldMutability { |
| None, |
| |
| // TODO: https://rust-lang.github.io/rfcs/3323-restrictions.html |
| // |
| // FieldMutability::Restricted(MutRestricted) |
| // |
| // pub struct MutRestricted { |
| // pub mut_token: Token![mut], |
| // pub paren_token: token::Paren, |
| // pub in_token: Option<Token![in]>, |
| // pub path: Box<Path>, |
| // } |
| } |
| } |
| |
| #[cfg(feature = "parsing")] |
| pub(crate) mod parsing { |
| use super::*; |
| use crate::ext::IdentExt; |
| use crate::parse::discouraged::Speculative; |
| use crate::parse::{Parse, ParseStream, Result}; |
| |
| #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] |
| impl Parse for Visibility { |
| fn parse(input: ParseStream) -> Result<Self> { |
| // Recognize an empty None-delimited group, as produced by a $:vis |
| // matcher that matched no tokens. |
| if input.peek(token::Group) { |
| let ahead = input.fork(); |
| let group = crate::group::parse_group(&ahead)?; |
| if group.content.is_empty() { |
| input.advance_to(&ahead); |
| return Ok(Visibility::Inherited); |
| } |
| } |
| |
| if input.peek(Token![pub]) { |
| Self::parse_pub(input) |
| } else { |
| Ok(Visibility::Inherited) |
| } |
| } |
| } |
| |
| impl Visibility { |
| fn parse_pub(input: ParseStream) -> Result<Self> { |
| let pub_token = input.parse::<Token![pub]>()?; |
| |
| if input.peek(token::Paren) { |
| let ahead = input.fork(); |
| |
| let content; |
| let paren_token = parenthesized!(content in ahead); |
| if content.peek(Token![crate]) |
| || content.peek(Token![self]) |
| || content.peek(Token![super]) |
| { |
| let path = content.call(Ident::parse_any)?; |
| |
| // Ensure there are no additional tokens within `content`. |
| // Without explicitly checking, we may misinterpret a tuple |
| // field as a restricted visibility, causing a parse error. |
| // e.g. `pub (crate::A, crate::B)` (Issue #720). |
| if content.is_empty() { |
| input.advance_to(&ahead); |
| return Ok(Visibility::Restricted(VisRestricted { |
| pub_token, |
| paren_token, |
| in_token: None, |
| path: Box::new(Path::from(path)), |
| })); |
| } |
| } else if content.peek(Token![in]) { |
| let in_token: Token![in] = content.parse()?; |
| let path = content.call(Path::parse_mod_style)?; |
| |
| input.advance_to(&ahead); |
| return Ok(Visibility::Restricted(VisRestricted { |
| pub_token, |
| paren_token, |
| in_token: Some(in_token), |
| path: Box::new(path), |
| })); |
| } |
| } |
| |
| Ok(Visibility::Public(pub_token)) |
| } |
| |
| #[cfg(feature = "full")] |
| pub(crate) fn is_some(&self) -> bool { |
| match self { |
| Visibility::Inherited => false, |
| _ => true, |
| } |
| } |
| } |
| } |
| |
| #[cfg(feature = "printing")] |
| mod printing { |
| use super::*; |
| use proc_macro2::TokenStream; |
| use quote::ToTokens; |
| |
| #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] |
| impl ToTokens for Visibility { |
| fn to_tokens(&self, tokens: &mut TokenStream) { |
| match self { |
| Visibility::Public(pub_token) => pub_token.to_tokens(tokens), |
| Visibility::Restricted(vis_restricted) => vis_restricted.to_tokens(tokens), |
| Visibility::Inherited => {} |
| } |
| } |
| } |
| |
| #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] |
| impl ToTokens for VisRestricted { |
| fn to_tokens(&self, tokens: &mut TokenStream) { |
| self.pub_token.to_tokens(tokens); |
| self.paren_token.surround(tokens, |tokens| { |
| // TODO: If we have a path which is not "self" or "super" or |
| // "crate", automatically add the "in" token. |
| self.in_token.to_tokens(tokens); |
| self.path.to_tokens(tokens); |
| }); |
| } |
| } |
| } |