| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- // SPDX-License-Identifier: Apache-2.0 OR MIT
- /// Formatting macro for constructing `Ident`s.
- ///
- /// <br>
- ///
- /// # Syntax
- ///
- /// Syntax is copied from the [`format!`] macro, supporting both positional and
- /// named arguments.
- ///
- /// Only a limited set of formatting traits are supported. The current mapping
- /// of format types to traits is:
- ///
- /// * `{}` ⇒ [`IdentFragment`]
- /// * `{:o}` ⇒ [`Octal`](std::fmt::Octal)
- /// * `{:x}` ⇒ [`LowerHex`](std::fmt::LowerHex)
- /// * `{:X}` ⇒ [`UpperHex`](std::fmt::UpperHex)
- /// * `{:b}` ⇒ [`Binary`](std::fmt::Binary)
- ///
- /// See [`std::fmt`] for more information.
- ///
- /// <br>
- ///
- /// # IdentFragment
- ///
- /// Unlike `format!`, this macro uses the [`IdentFragment`] formatting trait by
- /// default. This trait is like `Display`, with a few differences:
- ///
- /// * `IdentFragment` is only implemented for a limited set of types, such as
- /// unsigned integers and strings.
- /// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.
- ///
- /// [`IdentFragment`]: crate::IdentFragment
- /// [`Ident`]: proc_macro2::Ident
- ///
- /// <br>
- ///
- /// # Hygiene
- ///
- /// The [`Span`] of the first `Ident` argument is used as the span of the final
- /// identifier, falling back to [`Span::call_site`] when no identifiers are
- /// provided.
- ///
- /// ```
- /// # use quote::format_ident;
- /// # let ident = format_ident!("Ident");
- /// // If `ident` is an Ident, the span of `my_ident` will be inherited from it.
- /// let my_ident = format_ident!("My{}{}", ident, "IsCool");
- /// assert_eq!(my_ident, "MyIdentIsCool");
- /// ```
- ///
- /// Alternatively, the span can be overridden by passing the `span` named
- /// argument.
- ///
- /// ```
- /// # use quote::format_ident;
- /// # const IGNORE_TOKENS: &'static str = stringify! {
- /// let my_span = /* ... */;
- /// # };
- /// # let my_span = proc_macro2::Span::call_site();
- /// format_ident!("MyIdent", span = my_span);
- /// ```
- ///
- /// [`Span`]: proc_macro2::Span
- /// [`Span::call_site`]: proc_macro2::Span::call_site
- ///
- /// <p><br></p>
- ///
- /// # Panics
- ///
- /// This method will panic if the resulting formatted string is not a valid
- /// identifier.
- ///
- /// <br>
- ///
- /// # Examples
- ///
- /// Composing raw and non-raw identifiers:
- /// ```
- /// # use quote::format_ident;
- /// let my_ident = format_ident!("My{}", "Ident");
- /// assert_eq!(my_ident, "MyIdent");
- ///
- /// let raw = format_ident!("r#Raw");
- /// assert_eq!(raw, "r#Raw");
- ///
- /// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw);
- /// assert_eq!(my_ident_raw, "MyIdentIsRaw");
- /// ```
- ///
- /// Integer formatting options:
- /// ```
- /// # use quote::format_ident;
- /// let num: u32 = 10;
- ///
- /// let decimal = format_ident!("Id_{}", num);
- /// assert_eq!(decimal, "Id_10");
- ///
- /// let octal = format_ident!("Id_{:o}", num);
- /// assert_eq!(octal, "Id_12");
- ///
- /// let binary = format_ident!("Id_{:b}", num);
- /// assert_eq!(binary, "Id_1010");
- ///
- /// let lower_hex = format_ident!("Id_{:x}", num);
- /// assert_eq!(lower_hex, "Id_a");
- ///
- /// let upper_hex = format_ident!("Id_{:X}", num);
- /// assert_eq!(upper_hex, "Id_A");
- /// ```
- #[macro_export]
- macro_rules! format_ident {
- ($fmt:expr) => {
- $crate::format_ident_impl!([
- $crate::__private::Option::None,
- $fmt
- ])
- };
- ($fmt:expr, $($rest:tt)*) => {
- $crate::format_ident_impl!([
- $crate::__private::Option::None,
- $fmt
- ] $($rest)*)
- };
- }
- #[macro_export]
- #[doc(hidden)]
- macro_rules! format_ident_impl {
- // Final state
- ([$span:expr, $($fmt:tt)*]) => {
- $crate::__private::mk_ident(
- &$crate::__private::format!($($fmt)*),
- $span,
- )
- };
- // Span argument
- ([$old:expr, $($fmt:tt)*] span = $span:expr) => {
- $crate::format_ident_impl!([$old, $($fmt)*] span = $span,)
- };
- ([$old:expr, $($fmt:tt)*] span = $span:expr, $($rest:tt)*) => {
- $crate::format_ident_impl!([
- $crate::__private::Option::Some::<$crate::__private::Span>($span),
- $($fmt)*
- ] $($rest)*)
- };
- // Named argument
- ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr) => {
- $crate::format_ident_impl!([$span, $($fmt)*] $name = $arg,)
- };
- ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr, $($rest:tt)*) => {
- match $crate::__private::IdentFragmentAdapter(&$arg) {
- arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, $name = arg] $($rest)*),
- }
- };
- // Positional argument
- ([$span:expr, $($fmt:tt)*] $arg:expr) => {
- $crate::format_ident_impl!([$span, $($fmt)*] $arg,)
- };
- ([$span:expr, $($fmt:tt)*] $arg:expr, $($rest:tt)*) => {
- match $crate::__private::IdentFragmentAdapter(&$arg) {
- arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, arg] $($rest)*),
- }
- };
- }
|