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