Skip to content
This repository has been archived by the owner on Oct 6, 2024. It is now read-only.

Commit

Permalink
Merge pull request #30 from dtolnay/var
Browse files Browse the repository at this point in the history
Preserve macro metavariables not containing a paste
  • Loading branch information
dtolnay authored May 24, 2020
2 parents 40e90f1 + ab8081b commit dd8fc9f
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 18 deletions.
51 changes: 33 additions & 18 deletions impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,46 @@ struct PasteInput {

impl Parse for PasteInput {
fn parse(input: ParseStream) -> Result<Self> {
let mut expanded = TokenStream::new();
while !input.is_empty() {
match input.parse()? {
TokenTree::Group(group) => {
let delimiter = group.delimiter();
let content = group.stream();
let span = group.span();
if delimiter == Delimiter::Bracket && is_paste_operation(&content) {
let segments = parse_bracket_as_segments.parse2(content)?;
let pasted = paste_segments(span, &segments)?;
pasted.to_tokens(&mut expanded);
} else if is_none_delimited_single_ident_or_lifetime(delimiter, &content) {
content.to_tokens(&mut expanded);
} else {
let nested = PasteInput::parse.parse2(content)?;
let mut group = Group::new(delimiter, nested.expanded);
let mut contains_paste = false;
let expanded = parse(input, &mut contains_paste)?;
Ok(PasteInput { expanded })
}
}

fn parse(input: ParseStream, contains_paste: &mut bool) -> Result<TokenStream> {
let mut expanded = TokenStream::new();
while !input.is_empty() {
let save = input.fork();
match input.parse()? {
TokenTree::Group(group) => {
let delimiter = group.delimiter();
let content = group.stream();
let span = group.span();
if delimiter == Delimiter::Bracket && is_paste_operation(&content) {
let segments = parse_bracket_as_segments.parse2(content)?;
let pasted = paste_segments(span, &segments)?;
pasted.to_tokens(&mut expanded);
*contains_paste = true;
} else if is_none_delimited_single_ident_or_lifetime(delimiter, &content) {
content.to_tokens(&mut expanded);
} else {
let mut group_contains_paste = false;
let nested = (|input: ParseStream| parse(input, &mut group_contains_paste))
.parse2(content)?;
if group_contains_paste {
let mut group = Group::new(delimiter, nested);
group.set_span(span);
group.to_tokens(&mut expanded);
*contains_paste |= group_contains_paste;
} else {
save.parse::<TokenTree>()?.to_tokens(&mut expanded);
}
}
other => other.to_tokens(&mut expanded),
}
other => other.to_tokens(&mut expanded),
}
Ok(PasteInput { expanded })
}
Ok(expanded)
}

fn is_paste_operation(input: &TokenStream) -> bool {
Expand Down
20 changes: 20 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,23 @@ fn test_env_to_camel() {
let _ = LIBPaste;
}
}

mod test_doc_expr {
// https://github.com/dtolnay/paste/issues/29

macro_rules! doc_expr {
($doc:expr) => {
paste::item! {
#[doc = $doc]
pub struct S;
}
};
}

doc_expr!(stringify!());

#[test]
fn test_doc_expr() {
let _: S;
}
}

0 comments on commit dd8fc9f

Please sign in to comment.