From f20a2930bc153449a9fae154eab22817f557e7b3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 13 Mar 2021 15:51:20 -0800 Subject: [PATCH 1/2] Add regression test for issue 63 --- tests/test_doc.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/test_doc.rs b/tests/test_doc.rs index 1ceaf23..2e2b14d 100644 --- a/tests/test_doc.rs +++ b/tests/test_doc.rs @@ -52,3 +52,26 @@ fn test_case() { let expected = "HTTP GET!"; assert_eq!(doc, expected); } + +// https://github.com/dtolnay/paste/issues/63 +#[test] +fn test_stringify() { + macro_rules! create { + ($doc:expr) => { + paste! { + #[doc = $doc] + pub struct Struct; + } + }; + } + + macro_rules! forward { + ($name:ident) => { + create!(stringify!($name)); + }; + } + + forward!(documentation); + + let _ = Struct; +} From e5e87d382e8e104dd1c090f75368ed49c2489bc6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 13 Mar 2021 17:39:37 -0800 Subject: [PATCH 2/2] Work around conflict with extended_key_value_attributes --- src/lib.rs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ebe5eeb..d066ca0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -160,7 +160,8 @@ use std::panic; #[proc_macro] pub fn paste(input: TokenStream) -> TokenStream { let mut contains_paste = false; - match expand(input, &mut contains_paste) { + let flatten_single_interpolation = true; + match expand(input, &mut contains_paste, flatten_single_interpolation) { Ok(expanded) => expanded, Err(err) => err.to_compile_error(), } @@ -178,7 +179,11 @@ pub fn expr(input: TokenStream) -> TokenStream { paste(input) } -fn expand(input: TokenStream, contains_paste: &mut bool) -> Result { +fn expand( + input: TokenStream, + contains_paste: &mut bool, + flatten_single_interpolation: bool, +) -> Result { let mut expanded = TokenStream::new(); let mut lookbehind = Lookbehind::Other; let mut prev_none_group = None::; @@ -209,15 +214,22 @@ fn expand(input: TokenStream, contains_paste: &mut bool) -> Result let tokens = pasted_to_tokens(pasted, span)?; expanded.extend(tokens); *contains_paste = true; - } else if delimiter == Delimiter::None && is_flat_group(&content) { + } else if flatten_single_interpolation + && delimiter == Delimiter::None + && is_single_interpolation_group(&content) + { expanded.extend(content); *contains_paste = true; } else { let mut group_contains_paste = false; - let mut nested = expand(content, &mut group_contains_paste)?; - if delimiter == Delimiter::Bracket - && (lookbehind == Lookbehind::Pound || lookbehind == Lookbehind::PoundBang) - { + let is_attribute = delimiter == Delimiter::Bracket + && (lookbehind == Lookbehind::Pound || lookbehind == Lookbehind::PoundBang); + let mut nested = expand( + content, + &mut group_contains_paste, + flatten_single_interpolation && !is_attribute, + )?; + if is_attribute { nested = expand_attr(nested, span, &mut group_contains_paste)? } let group = if group_contains_paste { @@ -268,7 +280,7 @@ enum Lookbehind { } // https://github.com/dtolnay/paste/issues/26 -fn is_flat_group(input: &TokenStream) -> bool { +fn is_single_interpolation_group(input: &TokenStream) -> bool { #[derive(PartialEq)] enum State { Init,