xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/syn-2.0.55/src/ext.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 //! Extension traits to provide parsing methods on foreign types.
2 
3 use crate::buffer::Cursor;
4 use crate::error::Result;
5 use crate::parse::ParseStream;
6 use crate::parse::Peek;
7 use crate::sealed::lookahead;
8 use crate::token::CustomToken;
9 use proc_macro2::Ident;
10 
11 /// Additional methods for `Ident` not provided by proc-macro2 or libproc_macro.
12 ///
13 /// This trait is sealed and cannot be implemented for types outside of Syn. It
14 /// is implemented only for `proc_macro2::Ident`.
15 pub trait IdentExt: Sized + private::Sealed {
16     /// Parses any identifier including keywords.
17     ///
18     /// This is useful when parsing macro input which allows Rust keywords as
19     /// identifiers.
20     ///
21     /// # Example
22     ///
23     /// ```
24     /// use syn::{Error, Ident, Result, Token};
25     /// use syn::ext::IdentExt;
26     /// use syn::parse::ParseStream;
27     ///
28     /// mod kw {
29     ///     syn::custom_keyword!(name);
30     /// }
31     ///
32     /// // Parses input that looks like `name = NAME` where `NAME` can be
33     /// // any identifier.
34     /// //
35     /// // Examples:
36     /// //
37     /// //     name = anything
38     /// //     name = impl
39     /// fn parse_dsl(input: ParseStream) -> Result<Ident> {
40     ///     input.parse::<kw::name>()?;
41     ///     input.parse::<Token![=]>()?;
42     ///     let name = input.call(Ident::parse_any)?;
43     ///     Ok(name)
44     /// }
45     /// ```
parse_any(input: ParseStream) -> Result<Self>46     fn parse_any(input: ParseStream) -> Result<Self>;
47 
48     /// Peeks any identifier including keywords. Usage:
49     /// `input.peek(Ident::peek_any)`
50     ///
51     /// This is different from `input.peek(Ident)` which only returns true in
52     /// the case of an ident which is not a Rust keyword.
53     #[allow(non_upper_case_globals)]
54     const peek_any: private::PeekFn = private::PeekFn;
55 
56     /// Strips the raw marker `r#`, if any, from the beginning of an ident.
57     ///
58     ///   - unraw(`x`) = `x`
59     ///   - unraw(`move`) = `move`
60     ///   - unraw(`r#move`) = `move`
61     ///
62     /// # Example
63     ///
64     /// In the case of interop with other languages like Python that have a
65     /// different set of keywords than Rust, we might come across macro input
66     /// that involves raw identifiers to refer to ordinary variables in the
67     /// other language with a name that happens to be a Rust keyword.
68     ///
69     /// The function below appends an identifier from the caller's input onto a
70     /// fixed prefix. Without using `unraw()`, this would tend to produce
71     /// invalid identifiers like `__pyo3_get_r#move`.
72     ///
73     /// ```
74     /// use proc_macro2::Span;
75     /// use syn::Ident;
76     /// use syn::ext::IdentExt;
77     ///
78     /// fn ident_for_getter(variable: &Ident) -> Ident {
79     ///     let getter = format!("__pyo3_get_{}", variable.unraw());
80     ///     Ident::new(&getter, Span::call_site())
81     /// }
82     /// ```
unraw(&self) -> Ident83     fn unraw(&self) -> Ident;
84 }
85 
86 impl IdentExt for Ident {
parse_any(input: ParseStream) -> Result<Self>87     fn parse_any(input: ParseStream) -> Result<Self> {
88         input.step(|cursor| match cursor.ident() {
89             Some((ident, rest)) => Ok((ident, rest)),
90             None => Err(cursor.error("expected ident")),
91         })
92     }
93 
unraw(&self) -> Ident94     fn unraw(&self) -> Ident {
95         let string = self.to_string();
96         if let Some(string) = string.strip_prefix("r#") {
97             Ident::new(string, self.span())
98         } else {
99             self.clone()
100         }
101     }
102 }
103 
104 impl Peek for private::PeekFn {
105     type Token = private::IdentAny;
106 }
107 
108 impl CustomToken for private::IdentAny {
peek(cursor: Cursor) -> bool109     fn peek(cursor: Cursor) -> bool {
110         cursor.ident().is_some()
111     }
112 
display() -> &'static str113     fn display() -> &'static str {
114         "identifier"
115     }
116 }
117 
118 impl lookahead::Sealed for private::PeekFn {}
119 
120 mod private {
121     use proc_macro2::Ident;
122 
123     pub trait Sealed {}
124 
125     impl Sealed for Ident {}
126 
127     pub struct PeekFn;
128     pub struct IdentAny;
129 
130     impl Copy for PeekFn {}
131     impl Clone for PeekFn {
clone(&self) -> Self132         fn clone(&self) -> Self {
133             *self
134         }
135     }
136 }
137