aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_mbe/src/lib.rs44
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs8
-rw-r--r--crates/ra_mbe/src/subtree_parser.rs4
-rw-r--r--crates/ra_mbe/src/tt_cursor.rs5
-rw-r--r--crates/ra_parser/src/grammar.rs4
-rw-r--r--crates/ra_parser/src/lib.rs5
6 files changed, 70 insertions, 0 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index a1f438906..2f47e32d3 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -597,4 +597,48 @@ SOURCE_FILE@[0; 40)
597 assert_expansion(&rules, "foo! { 2 }", "fn bar () {2 ;}"); 597 assert_expansion(&rules, "foo! { 2 }", "fn bar () {2 ;}");
598 assert_expansion(&rules, "foo! { let a = 0 }", "fn bar () {let a = 0 ;}"); 598 assert_expansion(&rules, "foo! { let a = 0 }", "fn bar () {let a = 0 ;}");
599 } 599 }
600
601 #[test]
602 fn test_single_item() {
603 let rules = create_rules(
604 r#"
605 macro_rules! foo {
606 ($ i:item) => (
607 $ i
608 )
609 }
610"#,
611 );
612 assert_expansion(&rules, "foo! {mod c {}}", "mod c {}");
613 }
614
615 #[test]
616 fn test_all_items() {
617 let rules = create_rules(
618 r#"
619 macro_rules! foo {
620 ($ ($ i:item)*) => ($ (
621 $ i
622 )*)
623 }
624"#,
625 );
626 assert_expansion(&rules, r#"
627 foo! {
628 extern crate a;
629 mod b;
630 mod c {}
631 use d;
632 const E: i32 = 0;
633 static F: i32 = 0;
634 impl G {}
635 struct H;
636 enum I { Foo }
637 trait J {}
638 fn h() {}
639 extern {}
640 type T = u8;
641 }
642"#, r#"extern crate a ; mod b ; mod c {} use d ; const E : i32 = 0 ; static F : i32 = 0 ; impl G {} struct H ; enum I {Foo} trait J {} fn h () {} extern {} type T = u8 ;"#);
643 }
600} 644}
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 7587b575d..acba42809 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -161,6 +161,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
161 let pat = input.eat_stmt().ok_or(ExpandError::UnexpectedToken)?.clone(); 161 let pat = input.eat_stmt().ok_or(ExpandError::UnexpectedToken)?.clone();
162 res.inner.insert(text.clone(), Binding::Simple(pat.into())); 162 res.inner.insert(text.clone(), Binding::Simple(pat.into()));
163 } 163 }
164 "item" => {
165 let item =
166 input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone();
167 res.inner.insert(text.clone(), Binding::Simple(item.into()));
168 }
164 _ => return Err(ExpandError::UnexpectedToken), 169 _ => return Err(ExpandError::UnexpectedToken),
165 } 170 }
166 } 171 }
@@ -278,6 +283,9 @@ mod tests {
278 283
279 assert_err("($i) => ($i)", "foo!{a}", ExpandError::UnexpectedToken); 284 assert_err("($i) => ($i)", "foo!{a}", ExpandError::UnexpectedToken);
280 assert_err("($i:) => ($i)", "foo!{a}", ExpandError::UnexpectedToken); 285 assert_err("($i:) => ($i)", "foo!{a}", ExpandError::UnexpectedToken);
286
287 // FIXME:
288 // Add an err test case for ($($i:ident)) => ($())
281 } 289 }
282 290
283 fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) { 291 fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) {
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs
index f075ce245..195e4c3ac 100644
--- a/crates/ra_mbe/src/subtree_parser.rs
+++ b/crates/ra_mbe/src/subtree_parser.rs
@@ -46,6 +46,10 @@ impl<'a> Parser<'a> {
46 self.parse(|src, sink| ra_parser::parse_stmt(src, sink, false)) 46 self.parse(|src, sink| ra_parser::parse_stmt(src, sink, false))
47 } 47 }
48 48
49 pub fn parse_item(self) -> Option<tt::TokenTree> {
50 self.parse(ra_parser::parse_item)
51 }
52
49 fn parse<F>(self, f: F) -> Option<tt::TokenTree> 53 fn parse<F>(self, f: F) -> Option<tt::TokenTree>
50 where 54 where
51 F: FnOnce(&dyn TokenSource, &mut dyn TreeSink), 55 F: FnOnce(&dyn TokenSource, &mut dyn TreeSink),
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs
index adfe5520d..484437b0e 100644
--- a/crates/ra_mbe/src/tt_cursor.rs
+++ b/crates/ra_mbe/src/tt_cursor.rs
@@ -104,6 +104,11 @@ impl<'a> TtCursor<'a> {
104 parser.parse_stmt() 104 parser.parse_stmt()
105 } 105 }
106 106
107 pub(crate) fn eat_item(&mut self) -> Option<tt::TokenTree> {
108 let parser = Parser::new(&mut self.pos, self.subtree);
109 parser.parse_item()
110 }
111
107 pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { 112 pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> {
108 if self.at_char(char) { 113 if self.at_char(char) {
109 self.bump(); 114 self.bump();
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index 2c2f785d0..f8ed1299a 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -69,6 +69,10 @@ pub(crate) fn stmt(p: &mut Parser, with_semi: bool) {
69 expressions::stmt(p, with_semi) 69 expressions::stmt(p, with_semi)
70} 70}
71 71
72pub(crate) fn item(p: &mut Parser) {
73 items::item_or_macro(p, true, items::ItemFlavor::Mod)
74}
75
72pub(crate) fn reparser( 76pub(crate) fn reparser(
73 node: SyntaxKind, 77 node: SyntaxKind,
74 first_child: Option<SyntaxKind>, 78 first_child: Option<SyntaxKind>,
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs
index 9133c1b8a..11b5b9a75 100644
--- a/crates/ra_parser/src/lib.rs
+++ b/crates/ra_parser/src/lib.rs
@@ -93,6 +93,11 @@ pub fn parse_stmt(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink,
93 parse_from_tokens(token_source, tree_sink, |p| grammar::stmt(p, with_semi)); 93 parse_from_tokens(token_source, tree_sink, |p| grammar::stmt(p, with_semi));
94} 94}
95 95
96/// Parse given tokens into the given sink as an item
97pub fn parse_item(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) {
98 parse_from_tokens(token_source, tree_sink, grammar::item);
99}
100
96/// A parsing function for a specific braced-block. 101/// A parsing function for a specific braced-block.
97pub struct Reparser(fn(&mut parser::Parser)); 102pub struct Reparser(fn(&mut parser::Parser));
98 103