3482: Fix regression from #3451 r=matklad a=edwin0cheng

There is a regression from #3451 such that the following code has failed to parse in raw item collecting phase:

```rust
macro_rules! with_std { 
 	($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) 
}

with_std! {
	mod macros;
	mod others;
}
```

### Rationale

We always assume the last token of an statement will not end with a whitespace, which is true. It is because in parsing phase,  we always emit `SyntaxNode` before any whitespace. Such that in various parts of RA code, we solely check the semi-colon by using `SyntaxNode::last_child_token() == ";"` . 

However, in #3451, we insert some whitespaces between puncts such that we broke above assumption. This PR fixed this bug by make sure we don't add any whitespace if it is a semicolon.


Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
bors[bot] 2020-03-06 10:03:54 +00:00 committed by GitHub
commit 670895a49c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 1 deletions

View File

@ -448,7 +448,9 @@ impl<'a> TreeSink for TtTreeSink<'a> {
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(_))),
) = (last.token_tree(), next.token_tree())
{
if curr.spacing == tt::Spacing::Alone {
// Note: We always assume the semi-colon would be the last token in
// other parts of RA such that we don't add whitespace here.
if curr.spacing == tt::Spacing::Alone && curr.char != ';' {
self.inner.token(WHITESPACE, " ".into());
self.text_pos += TextUnit::of_char(' ');
}

View File

@ -1593,6 +1593,60 @@ fn test_repeat_bad_var() {
.assert_expand_items("foo!(b0 b1);", "b0 b1");
}
#[test]
fn test_no_space_after_semi_colon() {
let expanded = parse_macro(
r#"
macro_rules! with_std { ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) }
"#,
)
.expand_items(r#"with_std! {mod m;mod f;}"#);
let dump = format!("{:#?}", expanded);
assert_eq_text!(
dump.trim(),
r###"MACRO_ITEMS@[0; 52)
MODULE@[0; 26)
ATTR@[0; 21)
POUND@[0; 1) "#"
L_BRACK@[1; 2) "["
PATH@[2; 5)
PATH_SEGMENT@[2; 5)
NAME_REF@[2; 5)
IDENT@[2; 5) "cfg"
TOKEN_TREE@[5; 20)
L_PAREN@[5; 6) "("
IDENT@[6; 13) "feature"
EQ@[13; 14) "="
STRING@[14; 19) "\"std\""
R_PAREN@[19; 20) ")"
R_BRACK@[20; 21) "]"
MOD_KW@[21; 24) "mod"
NAME@[24; 25)
IDENT@[24; 25) "m"
SEMI@[25; 26) ";"
MODULE@[26; 52)
ATTR@[26; 47)
POUND@[26; 27) "#"
L_BRACK@[27; 28) "["
PATH@[28; 31)
PATH_SEGMENT@[28; 31)
NAME_REF@[28; 31)
IDENT@[28; 31) "cfg"
TOKEN_TREE@[31; 46)
L_PAREN@[31; 32) "("
IDENT@[32; 39) "feature"
EQ@[39; 40) "="
STRING@[40; 45) "\"std\""
R_PAREN@[45; 46) ")"
R_BRACK@[46; 47) "]"
MOD_KW@[47; 50) "mod"
NAME@[50; 51)
IDENT@[50; 51) "f"
SEMI@[51; 52) ";""###,
);
}
#[test]
fn test_expand_bad_literal() {
parse_macro(