syn/
restriction.rs

1use crate::path::Path;
2use crate::token;
3use alloc::boxed::Box;
4
5#[doc = r" The visibility level of an item: inherited or `pub` or"]
#[doc = r" `pub(restricted)`."]
#[doc = r""]
#[doc = r" # Syntax tree enum"]
#[doc = r""]
#[doc = r" This type is a [syntax tree enum]."]
#[doc = r""]
#[doc = r" [syntax tree enum]: crate::expr::Expr#syntax-tree-enums"]
pub enum Visibility {

    #[doc = r" A public visibility level: `pub`."]
    Public(crate::token::Pub),

    #[doc = r" A visibility level restricted to some path: `pub(self)` or"]
    #[doc = r" `pub(super)` or `pub(crate)` or `pub(in some::module)`."]
    Restricted(VisRestricted),

    #[doc = r" An inherited visibility, which usually means private."]
    Inherited,
}ast_enum! {
6    /// The visibility level of an item: inherited or `pub` or
7    /// `pub(restricted)`.
8    ///
9    /// # Syntax tree enum
10    ///
11    /// This type is a [syntax tree enum].
12    ///
13    /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
14    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
15    pub enum Visibility {
16        /// A public visibility level: `pub`.
17        Public(Token![pub]),
18
19        /// A visibility level restricted to some path: `pub(self)` or
20        /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
21        Restricted(VisRestricted),
22
23        /// An inherited visibility, which usually means private.
24        Inherited,
25    }
26}
27
28#[doc = r" A visibility level restricted to some path: `pub(self)` or"]
#[doc = r" `pub(super)` or `pub(crate)` or `pub(in some::module)`."]
pub struct VisRestricted {
    pub pub_token: crate::token::Pub,
    pub paren_token: token::Paren,
    pub in_token: Option<crate::token::In>,
    pub path: Box<Path>,
}ast_struct! {
29    /// A visibility level restricted to some path: `pub(self)` or
30    /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
31    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
32    pub struct VisRestricted {
33        pub pub_token: Token![pub],
34        pub paren_token: token::Paren,
35        pub in_token: Option<Token![in]>,
36        pub path: Box<Path>,
37    }
38}
39
40#[doc = r" Unused, but reserved for RFC 3323 restrictions."]
#[non_exhaustive]
pub enum FieldMutability { None, }ast_enum! {
41    /// Unused, but reserved for RFC 3323 restrictions.
42    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
43    #[non_exhaustive]
44    pub enum FieldMutability {
45        None,
46
47        // TODO: https://rust-lang.github.io/rfcs/3323-restrictions.html
48        //
49        // FieldMutability::Restricted(MutRestricted)
50        //
51        // pub struct MutRestricted {
52        //     pub mut_token: Token![mut],
53        //     pub paren_token: token::Paren,
54        //     pub in_token: Option<Token![in]>,
55        //     pub path: Box<Path>,
56        // }
57    }
58}
59
60#[cfg(feature = "parsing")]
61pub(crate) mod parsing {
62    use crate::error::Result;
63    use crate::ext::IdentExt as _;
64    use crate::ident::Ident;
65    use crate::parse::discouraged::Speculative as _;
66    use crate::parse::{Parse, ParseStream};
67    use crate::path::Path;
68    use crate::restriction::{VisRestricted, Visibility};
69    use crate::token;
70    use alloc::boxed::Box;
71
72    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
73    impl Parse for Visibility {
74        fn parse(input: ParseStream) -> Result<Self> {
75            // Recognize an empty None-delimited group, as produced by a $:vis
76            // matcher that matched no tokens.
77            if input.peek(token::Group) {
78                let ahead = input.fork();
79                let group = crate::group::parse_group(&ahead)?;
80                if group.content.is_empty() {
81                    input.advance_to(&ahead);
82                    return Ok(Visibility::Inherited);
83                }
84            }
85
86            if input.peek(crate::token::PubToken![pub]) {
87                Self::parse_pub(input)
88            } else {
89                Ok(Visibility::Inherited)
90            }
91        }
92    }
93
94    impl Visibility {
95        fn parse_pub(input: ParseStream) -> Result<Self> {
96            let pub_token = input.parse::<crate::token::PubToken![pub]>()?;
97
98            if input.peek(token::Paren) {
99                let ahead = input.fork();
100
101                let content;
102                let paren_token = match crate::__private::parse_parens(&ahead) {
    crate::__private::Ok(parens) => {
        content = parens.content;
        _ = content;
        parens.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in ahead);
103                if content.peek(crate::token::CrateToken![crate])
104                    || content.peek(crate::token::SelfValueToken![self])
105                    || content.peek(crate::token::SuperToken![super])
106                {
107                    let path = content.call(Ident::parse_any)?;
108
109                    // Ensure there are no additional tokens within `content`.
110                    // Without explicitly checking, we may misinterpret a tuple
111                    // field as a restricted visibility, causing a parse error.
112                    // e.g. `pub (crate::A, crate::B)` (Issue #720).
113                    if content.is_empty() {
114                        input.advance_to(&ahead);
115                        return Ok(Visibility::Restricted(VisRestricted {
116                            pub_token,
117                            paren_token,
118                            in_token: None,
119                            path: Box::new(Path::from(path)),
120                        }));
121                    }
122                } else if content.peek(crate::token::InToken![in]) {
123                    let in_token: crate::token::InToken![in] = content.parse()?;
124                    let path = content.call(Path::parse_mod_style)?;
125
126                    input.advance_to(&ahead);
127                    return Ok(Visibility::Restricted(VisRestricted {
128                        pub_token,
129                        paren_token,
130                        in_token: Some(in_token),
131                        path: Box::new(path),
132                    }));
133                }
134            }
135
136            Ok(Visibility::Public(pub_token))
137        }
138
139        #[cfg(feature = "full")]
140        pub(crate) fn is_some(&self) -> bool {
141            match self {
142                Visibility::Inherited => false,
143                _ => true,
144            }
145        }
146    }
147}
148
149#[cfg(feature = "printing")]
150mod printing {
151    use crate::path;
152    use crate::path::printing::PathStyle;
153    use crate::restriction::{VisRestricted, Visibility};
154    use proc_macro2::TokenStream;
155    use quote::ToTokens;
156
157    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
158    impl ToTokens for Visibility {
159        fn to_tokens(&self, tokens: &mut TokenStream) {
160            match self {
161                Visibility::Public(pub_token) => pub_token.to_tokens(tokens),
162                Visibility::Restricted(vis_restricted) => vis_restricted.to_tokens(tokens),
163                Visibility::Inherited => {}
164            }
165        }
166    }
167
168    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
169    impl ToTokens for VisRestricted {
170        fn to_tokens(&self, tokens: &mut TokenStream) {
171            self.pub_token.to_tokens(tokens);
172            self.paren_token.surround(tokens, |tokens| {
173                // TODO: If we have a path which is not "self" or "super" or
174                // "crate", automatically add the "in" token.
175                self.in_token.to_tokens(tokens);
176                path::printing::print_path(tokens, &self.path, PathStyle::Mod);
177            });
178        }
179    }
180}