// SPDX-License-Identifier: Apache-2.0 OR MIT12/// Formatting macro for constructing `Ident`s.3///4/// <br>5///6/// # Syntax7///8/// Syntax is copied from the [`format!`] macro, supporting both positional and9/// named arguments.10///11/// Only a limited set of formatting traits are supported. The current mapping12/// of format types to traits is:13///14/// * `{}` ⇒ [`IdentFragment`]15/// * `{:o}` ⇒ [`Octal`](std::fmt::Octal)16/// * `{:x}` ⇒ [`LowerHex`](std::fmt::LowerHex)17/// * `{:X}` ⇒ [`UpperHex`](std::fmt::UpperHex)18/// * `{:b}` ⇒ [`Binary`](std::fmt::Binary)19///20/// See [`std::fmt`] for more information.21///22/// <br>23///24/// # IdentFragment25///26/// Unlike `format!`, this macro uses the [`IdentFragment`] formatting trait by27/// default. This trait is like `Display`, with a few differences:28///29/// * `IdentFragment` is only implemented for a limited set of types, such as30/// unsigned integers and strings.31/// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.32///33/// [`IdentFragment`]: crate::IdentFragment34/// [`Ident`]: proc_macro2::Ident35///36/// <br>37///38/// # Hygiene39///40/// The [`Span`] of the first `Ident` argument is used as the span of the final41/// identifier, falling back to [`Span::call_site`] when no identifiers are42/// provided.43///44/// ```45/// # use quote::format_ident;46/// # let ident = format_ident!("Ident");47/// // If `ident` is an Ident, the span of `my_ident` will be inherited from it.48/// let my_ident = format_ident!("My{}{}", ident, "IsCool");49/// assert_eq!(my_ident, "MyIdentIsCool");50/// ```51///52/// Alternatively, the span can be overridden by passing the `span` named53/// argument.54///55/// ```56/// # use quote::format_ident;57/// # const IGNORE_TOKENS: &'static str = stringify! {58/// let my_span = /* ... */;59/// # };60/// # let my_span = proc_macro2::Span::call_site();61/// format_ident!("MyIdent", span = my_span);62/// ```63///64/// [`Span`]: proc_macro2::Span65/// [`Span::call_site`]: proc_macro2::Span::call_site66///67/// <p><br></p>68///69/// # Panics70///71/// This method will panic if the resulting formatted string is not a valid72/// identifier.73///74/// <br>75///76/// # Examples77///78/// Composing raw and non-raw identifiers:79/// ```80/// # use quote::format_ident;81/// let my_ident = format_ident!("My{}", "Ident");82/// assert_eq!(my_ident, "MyIdent");83///84/// let raw = format_ident!("r#Raw");85/// assert_eq!(raw, "r#Raw");86///87/// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw);88/// assert_eq!(my_ident_raw, "MyIdentIsRaw");89/// ```90///91/// Integer formatting options:92/// ```93/// # use quote::format_ident;94/// let num: u32 = 10;95///96/// let decimal = format_ident!("Id_{}", num);97/// assert_eq!(decimal, "Id_10");98///99/// let octal = format_ident!("Id_{:o}", num);100/// assert_eq!(octal, "Id_12");101///102/// let binary = format_ident!("Id_{:b}", num);103/// assert_eq!(binary, "Id_1010");104///105/// let lower_hex = format_ident!("Id_{:x}", num);106/// assert_eq!(lower_hex, "Id_a");107///108/// let upper_hex = format_ident!("Id_{:X}", num);109/// assert_eq!(upper_hex, "Id_A");110/// ```111#[macro_export]112macro_rules! format_ident {113($fmt:expr) => {114$crate::format_ident_impl!([115$crate::__private::Option::None,116$fmt117])118};119120($fmt:expr, $($rest:tt)*) => {121$crate::format_ident_impl!([122$crate::__private::Option::None,123$fmt124] $($rest)*)125};126}127128#[macro_export]129#[doc(hidden)]130macro_rules! format_ident_impl {131// Final state132([$span:expr, $($fmt:tt)*]) => {133$crate::__private::mk_ident(134&$crate::__private::format!($($fmt)*),135$span,136)137};138139// Span argument140([$old:expr, $($fmt:tt)*] span = $span:expr) => {141$crate::format_ident_impl!([$old, $($fmt)*] span = $span,)142};143([$old:expr, $($fmt:tt)*] span = $span:expr, $($rest:tt)*) => {144$crate::format_ident_impl!([145$crate::__private::Option::Some::<$crate::__private::Span>($span),146$($fmt)*147] $($rest)*)148};149150// Named argument151([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr) => {152$crate::format_ident_impl!([$span, $($fmt)*] $name = $arg,)153};154([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr, $($rest:tt)*) => {155match $crate::__private::IdentFragmentAdapter(&$arg) {156arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, $name = arg] $($rest)*),157}158};159160// Positional argument161([$span:expr, $($fmt:tt)*] $arg:expr) => {162$crate::format_ident_impl!([$span, $($fmt)*] $arg,)163};164([$span:expr, $($fmt:tt)*] $arg:expr, $($rest:tt)*) => {165match $crate::__private::IdentFragmentAdapter(&$arg) {166arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, arg] $($rest)*),167}168};169}170171172