diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-04 00:50:48 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-04 00:50:48 +0000 |
commit | 13a2bdb0a89260e978ba8e55abd7a51a003e62a7 (patch) | |
tree | 35eb019bf768f8566156126d88175d33d7278f56 | |
parent | 998ed13d09992d1fe24a45cc725c55390d9a5ca7 (diff) | |
parent | 0000f007873a3de2b454bd808083c0c0e8c6c6fa (diff) |
Merge #736
736: mbe: Add support matching for matching idents r=jrmuizel a=jrmuizel
Factors out a helper and adds support for matching idents.
Co-authored-by: Jeff Muizelaar <[email protected]>
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 68 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 5 |
2 files changed, 49 insertions, 24 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index ec12192cc..6f719acbf 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -161,6 +161,18 @@ impl_froms!(TokenTree: Leaf, Subtree); | |||
161 | ) | 161 | ) |
162 | } | 162 | } |
163 | 163 | ||
164 | fn create_rules(macro_definition: &str) -> MacroRules { | ||
165 | let source_file = ast::SourceFile::parse(macro_definition); | ||
166 | let macro_definition = source_file | ||
167 | .syntax() | ||
168 | .descendants() | ||
169 | .find_map(ast::MacroCall::cast) | ||
170 | .unwrap(); | ||
171 | |||
172 | let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap(); | ||
173 | crate::MacroRules::parse(&definition_tt).unwrap() | ||
174 | } | ||
175 | |||
164 | fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) { | 176 | fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) { |
165 | let source_file = ast::SourceFile::parse(invocation); | 177 | let source_file = ast::SourceFile::parse(invocation); |
166 | let macro_invocation = source_file | 178 | let macro_invocation = source_file |
@@ -177,7 +189,8 @@ impl_froms!(TokenTree: Leaf, Subtree); | |||
177 | 189 | ||
178 | #[test] | 190 | #[test] |
179 | fn test_fail_match_pattern_by_first_token() { | 191 | fn test_fail_match_pattern_by_first_token() { |
180 | let macro_definition = r#" | 192 | let rules = create_rules( |
193 | r#" | ||
181 | macro_rules! foo { | 194 | macro_rules! foo { |
182 | ($ i:ident) => ( | 195 | ($ i:ident) => ( |
183 | mod $ i {} | 196 | mod $ i {} |
@@ -189,17 +202,8 @@ impl_froms!(TokenTree: Leaf, Subtree); | |||
189 | struct $ i; | 202 | struct $ i; |
190 | ) | 203 | ) |
191 | } | 204 | } |
192 | "#; | 205 | "#, |
193 | 206 | ); | |
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 | 207 | ||
204 | assert_expansion(&rules, "foo! { foo }", "mod foo {}"); | 208 | assert_expansion(&rules, "foo! { foo }", "mod foo {}"); |
205 | assert_expansion(&rules, "foo! { = bar }", "fn bar () {}"); | 209 | assert_expansion(&rules, "foo! { = bar }", "fn bar () {}"); |
@@ -208,7 +212,8 @@ impl_froms!(TokenTree: Leaf, Subtree); | |||
208 | 212 | ||
209 | #[test] | 213 | #[test] |
210 | fn test_fail_match_pattern_by_last_token() { | 214 | fn test_fail_match_pattern_by_last_token() { |
211 | let macro_definition = r#" | 215 | let rules = create_rules( |
216 | r#" | ||
212 | macro_rules! foo { | 217 | macro_rules! foo { |
213 | ($ i:ident) => ( | 218 | ($ i:ident) => ( |
214 | mod $ i {} | 219 | mod $ i {} |
@@ -220,20 +225,35 @@ impl_froms!(TokenTree: Leaf, Subtree); | |||
220 | struct $ i; | 225 | struct $ i; |
221 | ) | 226 | ) |
222 | } | 227 | } |
223 | "#; | 228 | "#, |
224 | 229 | ); | |
225 | let source_file = ast::SourceFile::parse(macro_definition); | ||
226 | let macro_definition = source_file | ||
227 | .syntax() | ||
228 | .descendants() | ||
229 | .find_map(ast::MacroCall::cast) | ||
230 | .unwrap(); | ||
231 | |||
232 | let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap(); | ||
233 | let rules = crate::MacroRules::parse(&definition_tt).unwrap(); | ||
234 | 230 | ||
235 | assert_expansion(&rules, "foo! { foo }", "mod foo {}"); | 231 | assert_expansion(&rules, "foo! { foo }", "mod foo {}"); |
236 | assert_expansion(&rules, "foo! { bar = }", "fn bar () {}"); | 232 | assert_expansion(&rules, "foo! { bar = }", "fn bar () {}"); |
237 | assert_expansion(&rules, "foo! { Baz + }", "struct Baz ;"); | 233 | assert_expansion(&rules, "foo! { Baz + }", "struct Baz ;"); |
238 | } | 234 | } |
235 | |||
236 | #[test] | ||
237 | fn test_fail_match_pattern_by_word_token() { | ||
238 | let rules = create_rules( | ||
239 | r#" | ||
240 | macro_rules! foo { | ||
241 | ($ i:ident) => ( | ||
242 | mod $ i {} | ||
243 | ); | ||
244 | (spam $ i:ident) => ( | ||
245 | fn $ i() {} | ||
246 | ); | ||
247 | (eggs $ i:ident) => ( | ||
248 | struct $ i; | ||
249 | ) | ||
250 | } | ||
251 | "#, | ||
252 | ); | ||
253 | |||
254 | assert_expansion(&rules, "foo! { foo }", "mod foo {}"); | ||
255 | assert_expansion(&rules, "foo! { spam bar }", "fn bar () {}"); | ||
256 | assert_expansion(&rules, "foo! { eggs Baz }", "struct Baz ;"); | ||
257 | } | ||
258 | |||
239 | } | 259 | } |
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index 2945e7359..212e2ea92 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -126,6 +126,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Option<Bindings> | |||
126 | return None; | 126 | return None; |
127 | } | 127 | } |
128 | } | 128 | } |
129 | crate::Leaf::Ident(ident) => { | ||
130 | if input.eat_ident()?.text != ident.text { | ||
131 | return None; | ||
132 | } | ||
133 | } | ||
129 | _ => return None, | 134 | _ => return None, |
130 | }, | 135 | }, |
131 | crate::TokenTree::Repeat(crate::Repeat { | 136 | crate::TokenTree::Repeat(crate::Repeat { |