Skip to content

Commit b6819c2

Browse files
authored
Merge pull request #3451 from edwin0cheng/fix-mbe-composited
Fix mbe composited token bug
2 parents 9c906bd + 0c79e1d commit b6819c2

File tree

7 files changed

+122
-9
lines changed

7 files changed

+122
-9
lines changed

crates/ra_hir_expand/src/builtin_derive.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ mod tests {
266266
BuiltinDeriveExpander::Copy,
267267
);
268268

269-
assert_eq!(expanded, "impl <>std::marker::CopyforFoo <>{}");
269+
assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}");
270270
}
271271

272272
#[test]

crates/ra_hir_expand/src/builtin_macro.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ mod tests {
367367
"#,
368368
);
369369

370-
assert_eq!(expanded, "std::option::Option::None:: <&str>");
370+
assert_eq!(expanded, "std::option::Option::None:: < &str>");
371371
}
372372

373373
#[test]
@@ -414,7 +414,7 @@ mod tests {
414414

415415
assert_eq!(
416416
expanded,
417-
r#"std::fmt::Arguments::new_v1(&[] ,&[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"#
417+
r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"#
418418
);
419419
}
420420
}

crates/ra_hir_expand/src/db.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,20 @@ pub(crate) fn parse_macro(
176176
MacroCallId::LazyMacro(id) => {
177177
let loc: MacroCallLoc = db.lookup_intern_macro(id);
178178
let node = loc.kind.node(db);
179+
180+
// collect parent information for warning log
181+
let parents = std::iter::successors(loc.kind.file_id().call_node(db), |it| {
182+
it.file_id.call_node(db)
183+
})
184+
.map(|n| format!("{:#}", n.value))
185+
.collect::<Vec<_>>()
186+
.join("\n");
187+
179188
log::warn!(
180-
"fail on macro_parse: (reason: {} macro_call: {:#})",
189+
"fail on macro_parse: (reason: {} macro_call: {:#}) parents: {}",
181190
err,
182-
node.value
191+
node.value,
192+
parents
183193
);
184194
}
185195
_ => {

crates/ra_mbe/src/mbe_expander/matcher.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,60 @@ impl<'a> TtIter<'a> {
155155
ok
156156
}
157157

158+
pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> {
159+
let tt = self.next().ok_or_else(|| ())?.clone();
160+
let punct = match tt {
161+
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.spacing == tt::Spacing::Joint => {
162+
punct
163+
}
164+
_ => return Ok(tt),
165+
};
166+
167+
let (second, third) = match (self.peek_n(0), self.peek_n(1)) {
168+
(
169+
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))),
170+
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p3))),
171+
) if p2.spacing == tt::Spacing::Joint => (p2.char, Some(p3.char)),
172+
(Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), _) => (p2.char, None),
173+
_ => return Ok(tt),
174+
};
175+
176+
match (punct.char, second, third) {
177+
('.', '.', Some('.'))
178+
| ('.', '.', Some('='))
179+
| ('<', '<', Some('='))
180+
| ('>', '>', Some('=')) => {
181+
let tt2 = self.next().unwrap().clone();
182+
let tt3 = self.next().unwrap().clone();
183+
Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into())
184+
}
185+
('-', '=', None)
186+
| ('-', '>', None)
187+
| (':', ':', None)
188+
| ('!', '=', None)
189+
| ('.', '.', None)
190+
| ('*', '=', None)
191+
| ('/', '=', None)
192+
| ('&', '&', None)
193+
| ('&', '=', None)
194+
| ('%', '=', None)
195+
| ('^', '=', None)
196+
| ('+', '=', None)
197+
| ('<', '<', None)
198+
| ('<', '=', None)
199+
| ('=', '=', None)
200+
| ('=', '>', None)
201+
| ('>', '=', None)
202+
| ('>', '>', None)
203+
| ('|', '=', None)
204+
| ('|', '|', None) => {
205+
let tt2 = self.next().unwrap().clone();
206+
Ok(tt::Subtree { delimiter: None, token_trees: vec![tt.clone(), tt2] }.into())
207+
}
208+
_ => Ok(tt),
209+
}
210+
}
211+
158212
pub(crate) fn expect_lifetime(&mut self) -> Result<&tt::Ident, ()> {
159213
let ident = self.expect_ident()?;
160214
// check if it start from "`"
@@ -302,7 +356,7 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, Ex
302356
let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone();
303357
tt::Leaf::from(ident).into()
304358
}
305-
"tt" => input.next().ok_or_else(|| err!())?.clone(),
359+
"tt" => input.expect_tt().map_err(|()| err!())?.clone(),
306360
"lifetime" => {
307361
let ident = input.expect_lifetime().map_err(|()| err!())?;
308362
tt::Leaf::Ident(ident.clone()).into()

crates/ra_mbe/src/syntax_bridge.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,11 +388,12 @@ impl<'a> TreeSink for TtTreeSink<'a> {
388388
return;
389389
}
390390

391+
let mut last = self.cursor;
391392
for _ in 0..n_tokens {
392393
if self.cursor.eof() {
393394
break;
394395
}
395-
396+
last = self.cursor;
396397
let text: SmolStr = match self.cursor.token_tree() {
397398
Some(tt::TokenTree::Leaf(leaf)) => {
398399
// Mark the range if needed
@@ -441,11 +442,11 @@ impl<'a> TreeSink for TtTreeSink<'a> {
441442
self.inner.token(kind, text);
442443

443444
// Add whitespace between adjoint puncts
444-
let next = self.cursor.bump();
445+
let next = last.bump();
445446
if let (
446447
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(curr))),
447448
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(_))),
448-
) = (self.cursor.token_tree(), next.token_tree())
449+
) = (last.token_tree(), next.token_tree())
449450
{
450451
if curr.spacing == tt::Spacing::Alone {
451452
self.inner.token(WHITESPACE, " ".into());

crates/ra_mbe/src/tests.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,50 @@ fn test_tt_group() {
825825
)
826826
.assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#);
827827
}
828+
829+
#[test]
830+
fn test_tt_composite() {
831+
parse_macro(
832+
r#"
833+
macro_rules! foo {
834+
($i:tt) => { 0 }
835+
}
836+
"#,
837+
)
838+
.assert_expand_items(r#"foo! { => }"#, r#"0"#);
839+
}
840+
841+
#[test]
842+
fn test_tt_composite2() {
843+
let node = parse_macro(
844+
r#"
845+
macro_rules! foo {
846+
($($tt:tt)*) => { abs!(=> $($tt)*) }
847+
}
848+
"#,
849+
)
850+
.expand_items(r#"foo!{#}"#);
851+
852+
let res = format!("{:#?}", &node);
853+
assert_eq_text!(
854+
res.trim(),
855+
r###"MACRO_ITEMS@[0; 10)
856+
MACRO_CALL@[0; 10)
857+
PATH@[0; 3)
858+
PATH_SEGMENT@[0; 3)
859+
NAME_REF@[0; 3)
860+
IDENT@[0; 3) "abs"
861+
EXCL@[3; 4) "!"
862+
TOKEN_TREE@[4; 10)
863+
L_PAREN@[4; 5) "("
864+
EQ@[5; 6) "="
865+
R_ANGLE@[6; 7) ">"
866+
WHITESPACE@[7; 8) " "
867+
POUND@[8; 9) "#"
868+
R_PAREN@[9; 10) ")""###
869+
);
870+
}
871+
828872
#[test]
829873
fn test_lifetime() {
830874
parse_macro(

crates/ra_mbe/src/tt_iter.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ impl<'a> TtIter<'a> {
5353
_ => Err(()),
5454
}
5555
}
56+
57+
pub(crate) fn peek_n(&self, n: usize) -> Option<&tt::TokenTree> {
58+
self.inner.as_slice().get(n)
59+
}
5660
}
5761

5862
impl<'a> Iterator for TtIter<'a> {

0 commit comments

Comments
 (0)