From 313854c728c45ce236f23ff7a8834690e06d8306 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 19 Apr 2019 21:15:19 +0800 Subject: Add lifetime matcher --- crates/ra_mbe/src/lib.rs | 13 ++++++++++++- crates/ra_mbe/src/mbe_expander.rs | 5 +++++ crates/ra_mbe/src/syntax_bridge.rs | 5 ++++- crates/ra_mbe/src/tt_cursor.rs | 4 ++++ 4 files changed, 25 insertions(+), 2 deletions(-) (limited to 'crates/ra_mbe') diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index ae8a62036..a143eaa36 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs @@ -209,7 +209,6 @@ impl_froms!(TokenTree: Leaf, Subtree); pub(crate) fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) { let expanded = expand(rules, invocation); - assert_eq!(expanded.to_string(), expansion); let tree = token_tree_to_macro_items(&expanded); @@ -786,4 +785,16 @@ MACRO_ITEMS@[0; 40) ); assert_expansion(&rules, r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); } + + #[test] + fn test_lifetime() { + let rules = create_rules( + r#" + macro_rules! foo { + ($ lt:lifetime) => { struct Ref<$ lt>{ s: &$ lt str } } + } +"#, + ); + assert_expansion(&rules, r#"foo!{'a}"#, r#"struct Ref < 'a > {s : & 'a str}"#); + } } diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index 4261dee8d..cacc3da19 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs @@ -180,6 +180,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result { + let lifetime = + input.eat_lifetime().ok_or(ExpandError::UnexpectedToken)?.clone(); + res.inner.insert(text.clone(), Binding::Simple(lifetime.into())); + } _ => return Err(ExpandError::UnexpectedToken), } } diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 5844d3f12..38a481029 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -157,7 +157,10 @@ fn convert_tt( ); } } else { - let child = if token.kind().is_keyword() || token.kind() == IDENT { + let child: tt::TokenTree = if token.kind().is_keyword() + || token.kind() == IDENT + || token.kind() == LIFETIME + { let relative_range = token.range() - global_offset; let id = token_map.alloc(relative_range); let text = token.text().clone(); diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index 04bb6b563..9c49648fa 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs @@ -119,6 +119,10 @@ impl<'a> TtCursor<'a> { parser.parse_item() } + pub(crate) fn eat_lifetime(&mut self) -> Option { + self.eat_ident().cloned().map(|ident| tt::Leaf::from(ident).into()) + } + pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { if self.at_char(char) { self.bump(); -- cgit v1.2.3