This commit is contained in:
Edwin Cheng 2020-03-04 22:29:55 +08:00
parent e76dddd610
commit 028595548b
4 changed files with 74 additions and 7 deletions

View File

@ -181,13 +181,9 @@ pub(crate) fn parse_macro(
err, err,
node.value node.value
); );
let mut parent = loc.kind.file_id().call_node(db);
let mut parent = loc.kind.file_id().call_node(db);
while let Some(node) = parent.clone() { while let Some(node) = parent.clone() {
log::warn!( log::warn!("parent: macro_call: {:#})", node.value);
"parent: macro_call: {:#})",
node.value
);
parent = node.file_id.call_node(db); parent = node.file_id.call_node(db);
} }
} }

View File

@ -155,6 +155,60 @@ impl<'a> TtIter<'a> {
ok ok
} }
pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> {
let tt = self.next().ok_or_else(|| ())?.clone();
let punct = match tt {
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.spacing == tt::Spacing::Joint => {
punct
}
_ => return Ok(tt),
};
let (second, third) = match (self.peek_n(0), self.peek_n(1)) {
(
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))),
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p3))),
) if p2.spacing == tt::Spacing::Joint => (p2.char, Some(p3.char)),
(Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), _) => (p2.char, None),
_ => return Ok(tt),
};
match (punct.char, second, third) {
('.', '.', Some('.'))
| ('.', '.', Some('='))
| ('<', '<', Some('='))
| ('>', '>', Some('=')) => {
let tt2 = self.next().unwrap().clone();
let tt3 = self.next().unwrap().clone();
Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into())
}
('-', '=', None)
| ('-', '>', None)
| (':', ':', None)
| ('!', '=', None)
| ('.', '.', None)
| ('*', '=', None)
| ('/', '=', None)
| ('&', '&', None)
| ('&', '=', None)
| ('%', '=', None)
| ('^', '=', None)
| ('+', '=', None)
| ('<', '<', None)
| ('<', '=', None)
| ('=', '=', None)
| ('=', '>', None)
| ('>', '=', None)
| ('>', '>', None)
| ('|', '=', None)
| ('|', '|', None) => {
let tt2 = self.next().unwrap().clone();
Ok(tt::Subtree { delimiter: None, token_trees: vec![tt.clone(), tt2] }.into())
}
_ => Ok(tt),
}
}
pub(crate) fn expect_lifetime(&mut self) -> Result<&tt::Ident, ()> { pub(crate) fn expect_lifetime(&mut self) -> Result<&tt::Ident, ()> {
let ident = self.expect_ident()?; let ident = self.expect_ident()?;
// check if it start from "`" // check if it start from "`"
@ -302,7 +356,7 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, Ex
let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone(); let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone();
tt::Leaf::from(ident).into() tt::Leaf::from(ident).into()
} }
"tt" => input.next().ok_or_else(|| err!())?.clone(), "tt" => input.expect_tt().map_err(|()| err!())?.clone(),
"lifetime" => { "lifetime" => {
let ident = input.expect_lifetime().map_err(|()| err!())?; let ident = input.expect_lifetime().map_err(|()| err!())?;
tt::Leaf::Ident(ident.clone()).into() tt::Leaf::Ident(ident.clone()).into()

View File

@ -825,6 +825,19 @@ fn test_tt_group() {
) )
.assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#);
} }
#[test]
fn test_tt_composite() {
parse_macro(
r#"
macro_rules! foo {
($i:tt) => { 0 }
}
"#,
)
.assert_expand_items(r#"foo! { => }"#, r#"0"#);
}
#[test] #[test]
fn test_lifetime() { fn test_lifetime() {
parse_macro( parse_macro(

View File

@ -53,6 +53,10 @@ impl<'a> TtIter<'a> {
_ => Err(()), _ => Err(()),
} }
} }
pub(crate) fn peek_n(&self, n: usize) -> Option<&tt::TokenTree> {
self.inner.as_slice().get(n)
}
} }
impl<'a> Iterator for TtIter<'a> { impl<'a> Iterator for TtIter<'a> {