diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index b9dd22dc95..074be90434 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs @@ -809,4 +809,16 @@ MACRO_ITEMS@[0; 40) ); assert_expansion(&rules, r#"foo!(u8 0)"#, r#"const VALUE: u8 = 0;"#); } + + #[test] + fn test_vis() { + let rules = create_rules( + r#" + macro_rules! foo { + ($ vis:vis $ name:ident) => { $ vis fn $ name() {}}; + } +"#, + ); + assert_expansion(&rules, r#"foo!(pub foo);"#, r#"pub fn foo() {}"#); + } } diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index 548b155354..01e29b556a 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs @@ -193,6 +193,10 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result { + let vis = input.eat_vis().ok_or(ExpandError::UnexpectedToken)?.clone(); + res.inner.insert(text.clone(), Binding::Simple(vis.into())); + } _ => return Err(ExpandError::UnexpectedToken), } diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs index 5d5557113e..528aa0f8a0 100644 --- a/crates/ra_mbe/src/subtree_parser.rs +++ b/crates/ra_mbe/src/subtree_parser.rs @@ -58,6 +58,10 @@ impl<'a> Parser<'a> { self.parse(ra_parser::parse_item) } + pub fn parse_vis(self) -> Option { + self.parse(ra_parser::parse_vis) + } + fn parse(self, f: F) -> Option where 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 6184fb31fa..818c412a08 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs @@ -137,6 +137,11 @@ impl<'a> TtCursor<'a> { self.eat_ident().cloned().map(|ident| tt::Leaf::from(ident).into()) } + pub(crate) fn eat_vis(&mut self) -> Option { + let parser = Parser::new(&mut self.pos, self.subtree); + parser.parse_vis() + } + pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { if self.at_char(char) { self.bump(); diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index 13c50c79c1..67eae749d5 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs @@ -167,7 +167,7 @@ impl BlockLike { } } -fn opt_visibility(p: &mut Parser) -> bool { +pub(crate) fn opt_visibility(p: &mut Parser) -> bool { match p.current() { PUB_KW => { let m = p.start(); diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs index 4787b5b9ea..970d699c01 100644 --- a/crates/ra_parser/src/lib.rs +++ b/crates/ra_parser/src/lib.rs @@ -107,6 +107,13 @@ pub fn parse_item(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) parse_from_tokens(token_source, tree_sink, grammar::item); } +/// Parse given tokens into the given sink as an visibility qualifier +pub fn parse_vis(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { + parse_from_tokens(token_source, tree_sink, |p| { + grammar::opt_visibility(p); + }); +} + pub fn parse_macro_items(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { parse_from_tokens(token_source, tree_sink, grammar::macro_items); }