]> git.proxmox.com Git - cargo.git/blob - vendor/syn/src/custom_keyword.rs
New upstream version 0.52.0
[cargo.git] / vendor / syn / src / custom_keyword.rs
1 /// Define a type that supports parsing and printing a given identifier as if it
2 /// were a keyword.
3 ///
4 /// # Usage
5 ///
6 /// As a convention, it is recommended that this macro be invoked within a
7 /// module called `kw` or `keyword` and that the resulting parser be invoked
8 /// with a `kw::` or `keyword::` prefix.
9 ///
10 /// ```
11 /// mod kw {
12 /// syn::custom_keyword!(whatever);
13 /// }
14 /// ```
15 ///
16 /// The generated syntax tree node supports the following operations just like
17 /// any built-in keyword token.
18 ///
19 /// - [Peeking] — `input.peek(kw::whatever)`
20 ///
21 /// - [Parsing] — `input.parse::<kw::whatever>()?`
22 ///
23 /// - [Printing] — `quote!( ... #whatever_token ... )`
24 ///
25 /// - Construction from a [`Span`] — `let whatever_token = kw::whatever(sp)`
26 ///
27 /// - Field access to its span — `let sp = whatever_token.span`
28 ///
29 /// [Peeking]: crate::parse::ParseBuffer::peek
30 /// [Parsing]: crate::parse::ParseBuffer::parse
31 /// [Printing]: quote::ToTokens
32 /// [`Span`]: proc_macro2::Span
33 ///
34 /// # Example
35 ///
36 /// This example parses input that looks like `bool = true` or `str = "value"`.
37 /// The key must be either the identifier `bool` or the identifier `str`. If
38 /// `bool`, the value may be either `true` or `false`. If `str`, the value may
39 /// be any string literal.
40 ///
41 /// The symbols `bool` and `str` are not reserved keywords in Rust so these are
42 /// not considered keywords in the `syn::token` module. Like any other
43 /// identifier that is not a keyword, these can be declared as custom keywords
44 /// by crates that need to use them as such.
45 ///
46 /// ```
47 /// use syn::{LitBool, LitStr, Result, Token};
48 /// use syn::parse::{Parse, ParseStream};
49 ///
50 /// mod kw {
51 /// syn::custom_keyword!(bool);
52 /// syn::custom_keyword!(str);
53 /// }
54 ///
55 /// enum Argument {
56 /// Bool {
57 /// bool_token: kw::bool,
58 /// eq_token: Token![=],
59 /// value: LitBool,
60 /// },
61 /// Str {
62 /// str_token: kw::str,
63 /// eq_token: Token![=],
64 /// value: LitStr,
65 /// },
66 /// }
67 ///
68 /// impl Parse for Argument {
69 /// fn parse(input: ParseStream) -> Result<Self> {
70 /// let lookahead = input.lookahead1();
71 /// if lookahead.peek(kw::bool) {
72 /// Ok(Argument::Bool {
73 /// bool_token: input.parse::<kw::bool>()?,
74 /// eq_token: input.parse()?,
75 /// value: input.parse()?,
76 /// })
77 /// } else if lookahead.peek(kw::str) {
78 /// Ok(Argument::Str {
79 /// str_token: input.parse::<kw::str>()?,
80 /// eq_token: input.parse()?,
81 /// value: input.parse()?,
82 /// })
83 /// } else {
84 /// Err(lookahead.error())
85 /// }
86 /// }
87 /// }
88 /// ```
89 #[macro_export]
90 macro_rules! custom_keyword {
91 ($ident:ident) => {
92 #[allow(non_camel_case_types)]
93 pub struct $ident {
94 pub span: $crate::__private::Span,
95 }
96
97 #[doc(hidden)]
98 #[allow(dead_code, non_snake_case)]
99 pub fn $ident<__S: $crate::__private::IntoSpans<[$crate::__private::Span; 1]>>(
100 span: __S,
101 ) -> $ident {
102 $ident {
103 span: $crate::__private::IntoSpans::into_spans(span)[0],
104 }
105 }
106
107 impl $crate::__private::Default for $ident {
108 fn default() -> Self {
109 $ident {
110 span: $crate::__private::Span::call_site(),
111 }
112 }
113 }
114
115 $crate::impl_parse_for_custom_keyword!($ident);
116 $crate::impl_to_tokens_for_custom_keyword!($ident);
117 $crate::impl_clone_for_custom_keyword!($ident);
118 $crate::impl_extra_traits_for_custom_keyword!($ident);
119 };
120 }
121
122 // Not public API.
123 #[cfg(feature = "parsing")]
124 #[doc(hidden)]
125 #[macro_export]
126 macro_rules! impl_parse_for_custom_keyword {
127 ($ident:ident) => {
128 // For peek.
129 impl $crate::token::CustomToken for $ident {
130 fn peek(cursor: $crate::buffer::Cursor) -> $crate::__private::bool {
131 if let Some((ident, _rest)) = cursor.ident() {
132 ident == stringify!($ident)
133 } else {
134 false
135 }
136 }
137
138 fn display() -> &'static $crate::__private::str {
139 concat!("`", stringify!($ident), "`")
140 }
141 }
142
143 impl $crate::parse::Parse for $ident {
144 fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
145 input.step(|cursor| {
146 if let $crate::__private::Some((ident, rest)) = cursor.ident() {
147 if ident == stringify!($ident) {
148 return $crate::__private::Ok(($ident { span: ident.span() }, rest));
149 }
150 }
151 $crate::__private::Err(cursor.error(concat!(
152 "expected `",
153 stringify!($ident),
154 "`"
155 )))
156 })
157 }
158 }
159 };
160 }
161
162 // Not public API.
163 #[cfg(not(feature = "parsing"))]
164 #[doc(hidden)]
165 #[macro_export]
166 macro_rules! impl_parse_for_custom_keyword {
167 ($ident:ident) => {};
168 }
169
170 // Not public API.
171 #[cfg(feature = "printing")]
172 #[doc(hidden)]
173 #[macro_export]
174 macro_rules! impl_to_tokens_for_custom_keyword {
175 ($ident:ident) => {
176 impl $crate::__private::ToTokens for $ident {
177 fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) {
178 let ident = $crate::Ident::new(stringify!($ident), self.span);
179 $crate::__private::TokenStreamExt::append(tokens, ident);
180 }
181 }
182 };
183 }
184
185 // Not public API.
186 #[cfg(not(feature = "printing"))]
187 #[doc(hidden)]
188 #[macro_export]
189 macro_rules! impl_to_tokens_for_custom_keyword {
190 ($ident:ident) => {};
191 }
192
193 // Not public API.
194 #[cfg(feature = "clone-impls")]
195 #[doc(hidden)]
196 #[macro_export]
197 macro_rules! impl_clone_for_custom_keyword {
198 ($ident:ident) => {
199 impl $crate::__private::Copy for $ident {}
200
201 #[allow(clippy::expl_impl_clone_on_copy)]
202 impl $crate::__private::Clone for $ident {
203 fn clone(&self) -> Self {
204 *self
205 }
206 }
207 };
208 }
209
210 // Not public API.
211 #[cfg(not(feature = "clone-impls"))]
212 #[doc(hidden)]
213 #[macro_export]
214 macro_rules! impl_clone_for_custom_keyword {
215 ($ident:ident) => {};
216 }
217
218 // Not public API.
219 #[cfg(feature = "extra-traits")]
220 #[doc(hidden)]
221 #[macro_export]
222 macro_rules! impl_extra_traits_for_custom_keyword {
223 ($ident:ident) => {
224 impl $crate::__private::Debug for $ident {
225 fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::fmt::Result {
226 $crate::__private::Formatter::write_str(
227 f,
228 concat!("Keyword [", stringify!($ident), "]"),
229 )
230 }
231 }
232
233 impl $crate::__private::Eq for $ident {}
234
235 impl $crate::__private::PartialEq for $ident {
236 fn eq(&self, _other: &Self) -> $crate::__private::bool {
237 true
238 }
239 }
240
241 impl $crate::__private::Hash for $ident {
242 fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {}
243 }
244 };
245 }
246
247 // Not public API.
248 #[cfg(not(feature = "extra-traits"))]
249 #[doc(hidden)]
250 #[macro_export]
251 macro_rules! impl_extra_traits_for_custom_keyword {
252 ($ident:ident) => {};
253 }