diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-03 07:32:59 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-03 07:32:59 +0000 |
commit | 02bacf70fa80936a11aa10c1316af2e9c17a71da (patch) | |
tree | 1c3a292f4322a97eaa608e6807385714c2a69e2a /crates | |
parent | e351ff0542a4d97d6c2d7ce8610778cb81af1f07 (diff) | |
parent | 0bb8456e7d7b6994c9e5efa9d5962f003ffa0a1e (diff) |
Merge #727
727: Fix macro_rules separator parsing. r=matklad a=jrmuizel
macro_rules rules are separated by ';' including an optional ';' at the end
Co-authored-by: Jeff Muizelaar <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 46 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_parser.rs | 8 |
2 files changed, 53 insertions, 1 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 3e7f458cf..922256c03 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -160,4 +160,50 @@ impl_froms!(TokenTree: Leaf, Subtree); | |||
160 | impl From < Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree :: Subtree (it)}}" | 160 | impl From < Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree :: Subtree (it)}}" |
161 | ) | 161 | ) |
162 | } | 162 | } |
163 | |||
164 | fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) { | ||
165 | let source_file = ast::SourceFile::parse(invocation); | ||
166 | let macro_invocation = source_file | ||
167 | .syntax() | ||
168 | .descendants() | ||
169 | .find_map(ast::MacroCall::cast) | ||
170 | .unwrap(); | ||
171 | |||
172 | let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap(); | ||
173 | |||
174 | let expaned = rules.expand(&invocation_tt).unwrap(); | ||
175 | assert_eq!(expaned.to_string(), expansion); | ||
176 | } | ||
177 | |||
178 | #[test] | ||
179 | fn test_fail_match_pattern_by_token() { | ||
180 | let macro_definition = r#" | ||
181 | macro_rules! foo { | ||
182 | ($ i:ident) => ( | ||
183 | mod $ i {} | ||
184 | ); | ||
185 | (= $ i:ident) => ( | ||
186 | fn $ i() {} | ||
187 | ); | ||
188 | (+ $ i:ident) => ( | ||
189 | struct $ i; | ||
190 | ) | ||
191 | } | ||
192 | "#; | ||
193 | |||
194 | let source_file = ast::SourceFile::parse(macro_definition); | ||
195 | let macro_definition = source_file | ||
196 | .syntax() | ||
197 | .descendants() | ||
198 | .find_map(ast::MacroCall::cast) | ||
199 | .unwrap(); | ||
200 | |||
201 | let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap(); | ||
202 | let rules = crate::MacroRules::parse(&definition_tt).unwrap(); | ||
203 | |||
204 | assert_expansion(&rules, "foo! { foo }", "mod foo {}"); | ||
205 | assert_expansion(&rules, "foo! { = bar }", "fn bar () {}"); | ||
206 | assert_expansion(&rules, "foo! { + Baz }", "struct Baz ;"); | ||
207 | } | ||
208 | |||
163 | } | 209 | } |
diff --git a/crates/ra_mbe/src/mbe_parser.rs b/crates/ra_mbe/src/mbe_parser.rs index a3e6abffc..abad2e8c8 100644 --- a/crates/ra_mbe/src/mbe_parser.rs +++ b/crates/ra_mbe/src/mbe_parser.rs | |||
@@ -7,7 +7,13 @@ pub(crate) fn parse(tt: &tt::Subtree) -> Option<crate::MacroRules> { | |||
7 | let mut parser = TtCursor::new(tt); | 7 | let mut parser = TtCursor::new(tt); |
8 | let mut rules = Vec::new(); | 8 | let mut rules = Vec::new(); |
9 | while !parser.is_eof() { | 9 | while !parser.is_eof() { |
10 | rules.push(parse_rule(&mut parser)?) | 10 | rules.push(parse_rule(&mut parser)?); |
11 | if parser.expect_char(';') == None { | ||
12 | if !parser.is_eof() { | ||
13 | return None; | ||
14 | } | ||
15 | break; | ||
16 | } | ||
11 | } | 17 | } |
12 | Some(crate::MacroRules { rules }) | 18 | Some(crate::MacroRules { rules }) |
13 | } | 19 | } |