180 lines · 6.0 KB · Rust
RawDownload
// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::path::Path;use crate::token; 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]: crate::expr::Expr#syntax-tree-enums    #[cfg_attr(docsrs, 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(docsrs, 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(docsrs, 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 crate::error::Result;    use crate::ext::IdentExt as _;    use crate::ident::Ident;    use crate::parse::discouraged::Speculative as _;    use crate::parse::{Parse, ParseStream};    use crate::path::Path;    use crate::restriction::{VisRestricted, Visibility};    use crate::token;     #[cfg_attr(docsrs, 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 crate::path;    use crate::path::printing::PathStyle;    use crate::restriction::{VisRestricted, Visibility};    use proc_macro2::TokenStream;    use quote::ToTokens;     #[cfg_attr(docsrs, 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(docsrs, 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);                path::printing::print_path(tokens, &self.path, PathStyle::Mod);            });        }    }}