Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3use crate::path::Path;
4use crate::token;
5
6ast_enum! {
7 /// The visibility level of an item: inherited or `pub` or
8 /// `pub(restricted)`.
9 ///
10 /// # Syntax tree enum
11 ///
12 /// This type is a [syntax tree enum].
13 ///
14 /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
15 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
16 pub enum Visibility {
17 /// A public visibility level: `pub`.
18 Public(Token![pub]),
19
20 /// A visibility level restricted to some path: `pub(self)` or
21 /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
22 Restricted(VisRestricted),
23
24 /// An inherited visibility, which usually means private.
25 Inherited,
26 }
27}
28
29ast_struct! {
30 /// A visibility level restricted to some path: `pub(self)` or
31 /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
32 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
33 pub struct VisRestricted {
34 pub pub_token: Token![pub],
35 pub paren_token: token::Paren,
36 pub in_token: Option<Token![in]>,
37 pub path: Box<Path>,
38 }
39}
40
41ast_enum! {
42 /// Unused, but reserved for RFC 3323 restrictions.
43 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
44 #[non_exhaustive]
45 pub enum FieldMutability {
46 None,
47
48 // TODO: https://rust-lang.github.io/rfcs/3323-restrictions.html
49 //
50 // FieldMutability::Restricted(MutRestricted)
51 //
52 // pub struct MutRestricted {
53 // pub mut_token: Token![mut],
54 // pub paren_token: token::Paren,
55 // pub in_token: Option<Token![in]>,
56 // pub path: Box<Path>,
57 // }
58 }
59}
60
61#[cfg(feature = "parsing")]
62pub(crate) mod parsing {
63 use crate::error::Result;
64 use crate::ext::IdentExt as _;
65 use crate::ident::Ident;
66 use crate::parse::discouraged::Speculative as _;
67 use crate::parse::{Parse, ParseStream};
68 use crate::path::Path;
69 use crate::restriction::{VisRestricted, Visibility};
70 use crate::token;
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(Token![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::<Token![pub]>()?;
97
98 if input.peek(token::Paren) {
99 let ahead = input.fork();
100
101 let content;
102 let paren_token = parenthesized!(content in ahead);
103 if content.peek(Token![crate])
104 || content.peek(Token![self])
105 || content.peek(Token![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(Token![in]) {
123 let in_token: Token![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}