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