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 | |