Skip to content

Commit 0285955

Browse files
committed
Fix #3436
1 parent e76dddd commit 0285955

File tree

4 files changed

+74
-7
lines changed

4 files changed

+74
-7
lines changed

crates/ra_hir_expand/src/db.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,9 @@ pub(crate) fn parse_macro(
181181
err,
182182
node.value
183183
);
184-
185-
let mut parent = loc.kind.file_id().call_node(db);
184+
let mut parent = loc.kind.file_id().call_node(db);
186185
while let Some(node) = parent.clone() {
187-
log::warn!(
188-
"parent: macro_call: {:#})",
189-
node.value
190-
);
186+
log::warn!("parent: macro_call: {:#})", node.value);
191187
parent = node.file_id.call_node(db);
192188
}
193189
}

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/tests.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,19 @@ 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+
828841
#[test]
829842
fn test_lifetime() {
830843
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)