// SPDX-License-Identifier: Apache-2.0 OR MIT12//! Extension traits to provide parsing methods on foreign types.34use crate::buffer::Cursor;5use crate::error::Result;6use crate::parse::ParseStream;7use crate::parse::Peek;8use crate::sealed::lookahead;9use crate::token::CustomToken;10use proc_macro2::Ident;1112/// Additional methods for `Ident` not provided by proc-macro2 or libproc_macro.13///14/// This trait is sealed and cannot be implemented for types outside of Syn. It15/// is implemented only for `proc_macro2::Ident`.16pub trait IdentExt: Sized + private::Sealed {17/// Parses any identifier including keywords.18///19/// This is useful when parsing macro input which allows Rust keywords as20/// identifiers.21///22/// # Example23///24/// ```25/// use syn::{Error, Ident, Result, Token};26/// use syn::ext::IdentExt;27/// use syn::parse::ParseStream;28///29/// mod kw {30/// syn::custom_keyword!(name);31/// }32///33/// // Parses input that looks like `name = NAME` where `NAME` can be34/// // any identifier.35/// //36/// // Examples:37/// //38/// // name = anything39/// // name = impl40/// fn parse_dsl(input: ParseStream) -> Result<Ident> {41/// input.parse::<kw::name>()?;42/// input.parse::<Token![=]>()?;43/// let name = input.call(Ident::parse_any)?;44/// Ok(name)45/// }46/// ```47fn parse_any(input: ParseStream) -> Result<Self>;4849/// Peeks any identifier including keywords. Usage:50/// `input.peek(Ident::peek_any)`51///52/// This is different from `input.peek(Ident)` which only returns true in53/// the case of an ident which is not a Rust keyword.54#[allow(non_upper_case_globals)]55const peek_any: private::PeekFn = private::PeekFn;5657/// Strips the raw marker `r#`, if any, from the beginning of an ident.58///59/// - unraw(`x`) = `x`60/// - unraw(`move`) = `move`61/// - unraw(`r#move`) = `move`62///63/// # Example64///65/// In the case of interop with other languages like Python that have a66/// different set of keywords than Rust, we might come across macro input67/// that involves raw identifiers to refer to ordinary variables in the68/// other language with a name that happens to be a Rust keyword.69///70/// The function below appends an identifier from the caller's input onto a71/// fixed prefix. Without using `unraw()`, this would tend to produce72/// invalid identifiers like `__pyo3_get_r#move`.73///74/// ```75/// use proc_macro2::Span;76/// use syn::Ident;77/// use syn::ext::IdentExt;78///79/// fn ident_for_getter(variable: &Ident) -> Ident {80/// let getter = format!("__pyo3_get_{}", variable.unraw());81/// Ident::new(&getter, Span::call_site())82/// }83/// ```84fn unraw(&self) -> Ident;85}8687impl IdentExt for Ident {88fn parse_any(input: ParseStream) -> Result<Self> {89input.step(|cursor| match cursor.ident() {90Some((ident, rest)) => Ok((ident, rest)),91None => Err(cursor.error("expected ident")),92})93}9495fn unraw(&self) -> Ident {96let string = self.to_string();97if let Some(string) = string.strip_prefix("r#") {98Ident::new(string, self.span())99} else {100self.clone()101}102}103}104105impl Peek for private::PeekFn {106type Token = private::IdentAny;107}108109impl CustomToken for private::IdentAny {110fn peek(cursor: Cursor) -> bool {111cursor.ident().is_some()112}113114fn display() -> &'static str {115"identifier"116}117}118119impl lookahead::Sealed for private::PeekFn {}120121mod private {122use proc_macro2::Ident;123124pub trait Sealed {}125126impl Sealed for Ident {}127128pub struct PeekFn;129pub struct IdentAny;130131impl Copy for PeekFn {}132impl Clone for PeekFn {133fn clone(&self) -> Self {134*self135}136}137}138139140