rust: macros: update 'paste!' macro to accept string literals
Enable combining identifiers with literals in the 'paste!' macro. This allows combining user-specified strings with affixes to create namespaced identifiers. This sample code: macro_rules! m { ($name:lit) => { paste!(struct [<_some_ $name _struct_>] {}) } } m!("foo_bar"); Would previously cause a compilation error. It will now generate: struct _some_foo_bar_struct_ {} Signed-off-by: Trevor Gross <tmgross@umich.edu> Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com> Reviewed-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20231118013959.37384-1-tmgross@umich.edu [ Added `:` before example block. ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
parent
743766565d
commit
2dc318ea96
@ -254,8 +254,8 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
|
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
|
||||||
/// single identifier.
|
/// single identifier.
|
||||||
///
|
///
|
||||||
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers
|
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers and
|
||||||
/// (literals, lifetimes and documentation strings are not supported). There is a difference in
|
/// literals (lifetimes and documentation strings are not supported). There is a difference in
|
||||||
/// supported modifiers as well.
|
/// supported modifiers as well.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -337,6 +337,24 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
/// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK);
|
/// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// # Literals
|
||||||
|
///
|
||||||
|
/// Literals can also be concatenated with other identifiers:
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// macro_rules! create_numbered_fn {
|
||||||
|
/// ($name:literal, $val:literal) => {
|
||||||
|
/// kernel::macros::paste! {
|
||||||
|
/// fn [<some_ $name _fn $val>]() -> u32 { $val }
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// create_numbered_fn!("foo", 100);
|
||||||
|
///
|
||||||
|
/// assert_eq!(some_foo_fn100(), 100)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// [`paste`]: https://docs.rs/paste/
|
/// [`paste`]: https://docs.rs/paste/
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn paste(input: TokenStream) -> TokenStream {
|
pub fn paste(input: TokenStream) -> TokenStream {
|
||||||
|
@ -9,7 +9,15 @@ fn concat(tokens: &[TokenTree], group_span: Span) -> TokenTree {
|
|||||||
loop {
|
loop {
|
||||||
match tokens.next() {
|
match tokens.next() {
|
||||||
None => break,
|
None => break,
|
||||||
Some(TokenTree::Literal(lit)) => segments.push((lit.to_string(), lit.span())),
|
Some(TokenTree::Literal(lit)) => {
|
||||||
|
// Allow us to concat string literals by stripping quotes
|
||||||
|
let mut value = lit.to_string();
|
||||||
|
if value.starts_with('"') && value.ends_with('"') {
|
||||||
|
value.remove(0);
|
||||||
|
value.pop();
|
||||||
|
}
|
||||||
|
segments.push((value, lit.span()));
|
||||||
|
}
|
||||||
Some(TokenTree::Ident(ident)) => {
|
Some(TokenTree::Ident(ident)) => {
|
||||||
let mut value = ident.to_string();
|
let mut value = ident.to_string();
|
||||||
if value.starts_with("r#") {
|
if value.starts_with("r#") {
|
||||||
|
Loading…
Reference in New Issue
Block a user