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