diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 14 | ||||
-rw-r--r-- | crates/ra_mbe/src/tests.rs | 665 | ||||
-rw-r--r-- | crates/ra_parser/src/lib.rs | 1 |
3 files changed, 283 insertions, 397 deletions
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 2c60430d1..ea2cac069 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -476,7 +476,7 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
476 | #[cfg(test)] | 476 | #[cfg(test)] |
477 | mod tests { | 477 | mod tests { |
478 | use super::*; | 478 | use super::*; |
479 | use crate::tests::{create_rules, expand}; | 479 | use crate::tests::parse_macro; |
480 | use ra_parser::TokenSource; | 480 | use ra_parser::TokenSource; |
481 | use ra_syntax::{ | 481 | use ra_syntax::{ |
482 | algo::{insert_children, InsertPosition}, | 482 | algo::{insert_children, InsertPosition}, |
@@ -485,7 +485,7 @@ mod tests { | |||
485 | 485 | ||
486 | #[test] | 486 | #[test] |
487 | fn convert_tt_token_source() { | 487 | fn convert_tt_token_source() { |
488 | let rules = create_rules( | 488 | let expansion = parse_macro( |
489 | r#" | 489 | r#" |
490 | macro_rules! literals { | 490 | macro_rules! literals { |
491 | ($i:ident) => { | 491 | ($i:ident) => { |
@@ -498,8 +498,8 @@ mod tests { | |||
498 | } | 498 | } |
499 | } | 499 | } |
500 | "#, | 500 | "#, |
501 | ); | 501 | ) |
502 | let expansion = expand(&rules, "literals!(foo);"); | 502 | .expand_tt("literals!(foo);"); |
503 | let tts = &[expansion.into()]; | 503 | let tts = &[expansion.into()]; |
504 | let buffer = tt::buffer::TokenBuffer::new(tts); | 504 | let buffer = tt::buffer::TokenBuffer::new(tts); |
505 | let mut tt_src = SubtreeTokenSource::new(&buffer); | 505 | let mut tt_src = SubtreeTokenSource::new(&buffer); |
@@ -527,7 +527,7 @@ mod tests { | |||
527 | 527 | ||
528 | #[test] | 528 | #[test] |
529 | fn stmts_token_trees_to_expr_is_err() { | 529 | fn stmts_token_trees_to_expr_is_err() { |
530 | let rules = create_rules( | 530 | let expansion = parse_macro( |
531 | r#" | 531 | r#" |
532 | macro_rules! stmts { | 532 | macro_rules! stmts { |
533 | () => { | 533 | () => { |
@@ -538,8 +538,8 @@ mod tests { | |||
538 | } | 538 | } |
539 | } | 539 | } |
540 | "#, | 540 | "#, |
541 | ); | 541 | ) |
542 | let expansion = expand(&rules, "stmts!();"); | 542 | .expand_tt("stmts!();"); |
543 | assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err()); | 543 | assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err()); |
544 | } | 544 | } |
545 | 545 | ||
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index b5a10a9d2..e640d115b 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | use std::fmt::Write; | ||
2 | |||
1 | use ra_parser::FragmentKind; | 3 | use ra_parser::FragmentKind; |
2 | use ra_syntax::{ast, AstNode, NodeOrToken, WalkEvent}; | 4 | use ra_syntax::{ast, AstNode, NodeOrToken, SyntaxKind::IDENT, SyntaxNode, WalkEvent, T}; |
3 | use test_utils::assert_eq_text; | 5 | use test_utils::assert_eq_text; |
4 | 6 | ||
5 | use super::*; | 7 | use super::*; |
@@ -61,13 +63,14 @@ mod rule_parsing { | |||
61 | 63 | ||
62 | #[test] | 64 | #[test] |
63 | fn test_token_id_shift() { | 65 | fn test_token_id_shift() { |
64 | let macro_definition = r#" | 66 | let expansion = parse_macro( |
67 | r#" | ||
65 | macro_rules! foobar { | 68 | macro_rules! foobar { |
66 | ($e:ident) => { foo bar $e } | 69 | ($e:ident) => { foo bar $e } |
67 | } | 70 | } |
68 | "#; | 71 | "#, |
69 | let rules = create_rules(macro_definition); | 72 | ) |
70 | let expansion = expand(&rules, "foobar!(baz);"); | 73 | .expand_tt("foobar!(baz);"); |
71 | 74 | ||
72 | fn get_id(t: &tt::TokenTree) -> Option<u32> { | 75 | fn get_id(t: &tt::TokenTree) -> Option<u32> { |
73 | if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t { | 76 | if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t { |
@@ -90,22 +93,23 @@ macro_rules! foobar { | |||
90 | 93 | ||
91 | #[test] | 94 | #[test] |
92 | fn test_token_map() { | 95 | fn test_token_map() { |
93 | use ra_parser::SyntaxKind::*; | 96 | let expanded = parse_macro( |
94 | use ra_syntax::T; | 97 | r#" |
95 | |||
96 | let macro_definition = r#" | ||
97 | macro_rules! foobar { | 98 | macro_rules! foobar { |
98 | ($e:ident) => { fn $e() {} } | 99 | ($e:ident) => { fn $e() {} } |
99 | } | 100 | } |
100 | "#; | 101 | "#, |
101 | let rules = create_rules(macro_definition); | 102 | ) |
102 | let (expansion, (token_map, content)) = expand_and_map(&rules, "foobar!(baz);"); | 103 | .expand_tt("foobar!(baz);"); |
104 | |||
105 | let (node, token_map) = token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap(); | ||
106 | let content = node.syntax_node().to_string(); | ||
103 | 107 | ||
104 | let get_text = |id, kind| -> String { | 108 | let get_text = |id, kind| -> String { |
105 | content[token_map.range_by_token(id).unwrap().by_kind(kind).unwrap()].to_string() | 109 | content[token_map.range_by_token(id).unwrap().by_kind(kind).unwrap()].to_string() |
106 | }; | 110 | }; |
107 | 111 | ||
108 | assert_eq!(expansion.token_trees.len(), 4); | 112 | assert_eq!(expanded.token_trees.len(), 4); |
109 | // {($e:ident) => { fn $e() {} }} | 113 | // {($e:ident) => { fn $e() {} }} |
110 | // 012345 67 8 9 T12 3 | 114 | // 012345 67 8 9 T12 3 |
111 | 115 | ||
@@ -116,7 +120,7 @@ macro_rules! foobar { | |||
116 | 120 | ||
117 | #[test] | 121 | #[test] |
118 | fn test_convert_tt() { | 122 | fn test_convert_tt() { |
119 | let macro_definition = r#" | 123 | parse_macro(r#" |
120 | macro_rules! impl_froms { | 124 | macro_rules! impl_froms { |
121 | ($e:ident: $($v:ident),*) => { | 125 | ($e:ident: $($v:ident),*) => { |
122 | $( | 126 | $( |
@@ -128,24 +132,17 @@ macro_rules! impl_froms { | |||
128 | )* | 132 | )* |
129 | } | 133 | } |
130 | } | 134 | } |
131 | "#; | 135 | "#) |
132 | 136 | .assert_expand_tt( | |
133 | let macro_invocation = r#" | 137 | "impl_froms!(TokenTree: Leaf, Subtree);", |
134 | impl_froms!(TokenTree: Leaf, Subtree); | 138 | "impl From <Leaf > for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree ::Leaf (it)}} \ |
135 | "#; | 139 | impl From <Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree ::Subtree (it)}}" |
136 | 140 | ); | |
137 | let rules = create_rules(macro_definition); | ||
138 | let expansion = expand(&rules, macro_invocation); | ||
139 | assert_eq!( | ||
140 | expansion.to_string(), | ||
141 | "impl From <Leaf > for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree ::Leaf (it)}} \ | ||
142 | impl From <Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree ::Subtree (it)}}" | ||
143 | ) | ||
144 | } | 141 | } |
145 | 142 | ||
146 | #[test] | 143 | #[test] |
147 | fn test_expr_order() { | 144 | fn test_expr_order() { |
148 | let rules = create_rules( | 145 | let expanded = parse_macro( |
149 | r#" | 146 | r#" |
150 | macro_rules! foo { | 147 | macro_rules! foo { |
151 | ($ i:expr) => { | 148 | ($ i:expr) => { |
@@ -153,11 +150,10 @@ fn test_expr_order() { | |||
153 | } | 150 | } |
154 | } | 151 | } |
155 | "#, | 152 | "#, |
156 | ); | 153 | ) |
157 | let expanded = expand(&rules, "foo! { 1 + 1}"); | 154 | .expand_items("foo! { 1 + 1}"); |
158 | let tree = token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node(); | ||
159 | 155 | ||
160 | let dump = format!("{:#?}", tree); | 156 | let dump = format!("{:#?}", expanded); |
161 | assert_eq_text!( | 157 | assert_eq_text!( |
162 | dump.trim(), | 158 | dump.trim(), |
163 | r#"MACRO_ITEMS@[0; 15) | 159 | r#"MACRO_ITEMS@[0; 15) |
@@ -189,7 +185,7 @@ fn test_expr_order() { | |||
189 | 185 | ||
190 | #[test] | 186 | #[test] |
191 | fn test_fail_match_pattern_by_first_token() { | 187 | fn test_fail_match_pattern_by_first_token() { |
192 | let rules = create_rules( | 188 | parse_macro( |
193 | r#" | 189 | r#" |
194 | macro_rules! foo { | 190 | macro_rules! foo { |
195 | ($ i:ident) => ( | 191 | ($ i:ident) => ( |
@@ -203,16 +199,15 @@ fn test_fail_match_pattern_by_first_token() { | |||
203 | ) | 199 | ) |
204 | } | 200 | } |
205 | "#, | 201 | "#, |
206 | ); | 202 | ) |
207 | 203 | .assert_expand_items("foo! { foo }", "mod foo {}") | |
208 | assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "mod foo {}"); | 204 | .assert_expand_items("foo! { = bar }", "fn bar () {}") |
209 | assert_expansion(MacroKind::Items, &rules, "foo! { = bar }", "fn bar () {}"); | 205 | .assert_expand_items("foo! { + Baz }", "struct Baz ;"); |
210 | assert_expansion(MacroKind::Items, &rules, "foo! { + Baz }", "struct Baz ;"); | ||
211 | } | 206 | } |
212 | 207 | ||
213 | #[test] | 208 | #[test] |
214 | fn test_fail_match_pattern_by_last_token() { | 209 | fn test_fail_match_pattern_by_last_token() { |
215 | let rules = create_rules( | 210 | parse_macro( |
216 | r#" | 211 | r#" |
217 | macro_rules! foo { | 212 | macro_rules! foo { |
218 | ($ i:ident) => ( | 213 | ($ i:ident) => ( |
@@ -226,16 +221,15 @@ fn test_fail_match_pattern_by_last_token() { | |||
226 | ) | 221 | ) |
227 | } | 222 | } |
228 | "#, | 223 | "#, |
229 | ); | 224 | ) |
230 | 225 | .assert_expand_items("foo! { foo }", "mod foo {}") | |
231 | assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "mod foo {}"); | 226 | .assert_expand_items("foo! { bar = }", "fn bar () {}") |
232 | assert_expansion(MacroKind::Items, &rules, "foo! { bar = }", "fn bar () {}"); | 227 | .assert_expand_items("foo! { Baz + }", "struct Baz ;"); |
233 | assert_expansion(MacroKind::Items, &rules, "foo! { Baz + }", "struct Baz ;"); | ||
234 | } | 228 | } |
235 | 229 | ||
236 | #[test] | 230 | #[test] |
237 | fn test_fail_match_pattern_by_word_token() { | 231 | fn test_fail_match_pattern_by_word_token() { |
238 | let rules = create_rules( | 232 | parse_macro( |
239 | r#" | 233 | r#" |
240 | macro_rules! foo { | 234 | macro_rules! foo { |
241 | ($ i:ident) => ( | 235 | ($ i:ident) => ( |
@@ -249,16 +243,15 @@ fn test_fail_match_pattern_by_word_token() { | |||
249 | ) | 243 | ) |
250 | } | 244 | } |
251 | "#, | 245 | "#, |
252 | ); | 246 | ) |
253 | 247 | .assert_expand_items("foo! { foo }", "mod foo {}") | |
254 | assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "mod foo {}"); | 248 | .assert_expand_items("foo! { spam bar }", "fn bar () {}") |
255 | assert_expansion(MacroKind::Items, &rules, "foo! { spam bar }", "fn bar () {}"); | 249 | .assert_expand_items("foo! { eggs Baz }", "struct Baz ;"); |
256 | assert_expansion(MacroKind::Items, &rules, "foo! { eggs Baz }", "struct Baz ;"); | ||
257 | } | 250 | } |
258 | 251 | ||
259 | #[test] | 252 | #[test] |
260 | fn test_match_group_pattern_by_separator_token() { | 253 | fn test_match_group_pattern_by_separator_token() { |
261 | let rules = create_rules( | 254 | parse_macro( |
262 | r#" | 255 | r#" |
263 | macro_rules! foo { | 256 | macro_rules! foo { |
264 | ($ ($ i:ident),*) => ($ ( | 257 | ($ ($ i:ident),*) => ($ ( |
@@ -273,16 +266,15 @@ fn test_match_group_pattern_by_separator_token() { | |||
273 | ) | 266 | ) |
274 | } | 267 | } |
275 | "#, | 268 | "#, |
276 | ); | 269 | ) |
277 | 270 | .assert_expand_items("foo! { foo, bar }", "mod foo {} mod bar {}") | |
278 | assert_expansion(MacroKind::Items, &rules, "foo! { foo, bar }", "mod foo {} mod bar {}"); | 271 | .assert_expand_items("foo! { foo# bar }", "fn foo () {} fn bar () {}") |
279 | assert_expansion(MacroKind::Items, &rules, "foo! { foo# bar }", "fn foo () {} fn bar () {}"); | 272 | .assert_expand_items("foo! { Foo,# Bar }", "struct Foo ; struct Bar ;"); |
280 | assert_expansion(MacroKind::Items, &rules, "foo! { Foo,# Bar }", "struct Foo ; struct Bar ;"); | ||
281 | } | 273 | } |
282 | 274 | ||
283 | #[test] | 275 | #[test] |
284 | fn test_match_group_pattern_with_multiple_defs() { | 276 | fn test_match_group_pattern_with_multiple_defs() { |
285 | let rules = create_rules( | 277 | parse_macro( |
286 | r#" | 278 | r#" |
287 | macro_rules! foo { | 279 | macro_rules! foo { |
288 | ($ ($ i:ident),*) => ( struct Bar { $ ( | 280 | ($ ($ i:ident),*) => ( struct Bar { $ ( |
@@ -290,19 +282,13 @@ fn test_match_group_pattern_with_multiple_defs() { | |||
290 | )*} ); | 282 | )*} ); |
291 | } | 283 | } |
292 | "#, | 284 | "#, |
293 | ); | 285 | ) |
294 | 286 | .assert_expand_items("foo! { foo, bar }", "struct Bar {fn foo {} fn bar {}}"); | |
295 | assert_expansion( | ||
296 | MacroKind::Items, | ||
297 | &rules, | ||
298 | "foo! { foo, bar }", | ||
299 | "struct Bar {fn foo {} fn bar {}}", | ||
300 | ); | ||
301 | } | 287 | } |
302 | 288 | ||
303 | #[test] | 289 | #[test] |
304 | fn test_match_group_pattern_with_multiple_statement() { | 290 | fn test_match_group_pattern_with_multiple_statement() { |
305 | let rules = create_rules( | 291 | parse_macro( |
306 | r#" | 292 | r#" |
307 | macro_rules! foo { | 293 | macro_rules! foo { |
308 | ($ ($ i:ident),*) => ( fn baz { $ ( | 294 | ($ ($ i:ident),*) => ( fn baz { $ ( |
@@ -310,14 +296,13 @@ fn test_match_group_pattern_with_multiple_statement() { | |||
310 | )*} ); | 296 | )*} ); |
311 | } | 297 | } |
312 | "#, | 298 | "#, |
313 | ); | 299 | ) |
314 | 300 | .assert_expand_items("foo! { foo, bar }", "fn baz {foo () ; bar () ;}"); | |
315 | assert_expansion(MacroKind::Items, &rules, "foo! { foo, bar }", "fn baz {foo () ; bar () ;}"); | ||
316 | } | 301 | } |
317 | 302 | ||
318 | #[test] | 303 | #[test] |
319 | fn test_match_group_pattern_with_multiple_statement_without_semi() { | 304 | fn test_match_group_pattern_with_multiple_statement_without_semi() { |
320 | let rules = create_rules( | 305 | parse_macro( |
321 | r#" | 306 | r#" |
322 | macro_rules! foo { | 307 | macro_rules! foo { |
323 | ($ ($ i:ident),*) => ( fn baz { $ ( | 308 | ($ ($ i:ident),*) => ( fn baz { $ ( |
@@ -325,14 +310,13 @@ fn test_match_group_pattern_with_multiple_statement_without_semi() { | |||
325 | );*} ); | 310 | );*} ); |
326 | } | 311 | } |
327 | "#, | 312 | "#, |
328 | ); | 313 | ) |
329 | 314 | .assert_expand_items("foo! { foo, bar }", "fn baz {foo () ;bar ()}"); | |
330 | assert_expansion(MacroKind::Items, &rules, "foo! { foo, bar }", "fn baz {foo () ;bar ()}"); | ||
331 | } | 315 | } |
332 | 316 | ||
333 | #[test] | 317 | #[test] |
334 | fn test_match_group_empty_fixed_token() { | 318 | fn test_match_group_empty_fixed_token() { |
335 | let rules = create_rules( | 319 | parse_macro( |
336 | r#" | 320 | r#" |
337 | macro_rules! foo { | 321 | macro_rules! foo { |
338 | ($ ($ i:ident)* #abc) => ( fn baz { $ ( | 322 | ($ ($ i:ident)* #abc) => ( fn baz { $ ( |
@@ -340,69 +324,59 @@ fn test_match_group_empty_fixed_token() { | |||
340 | )*} ); | 324 | )*} ); |
341 | } | 325 | } |
342 | "#, | 326 | "#, |
343 | ); | 327 | ) |
344 | 328 | .assert_expand_items("foo! {#abc}", "fn baz {}"); | |
345 | assert_expansion(MacroKind::Items, &rules, "foo! {#abc}", "fn baz {}"); | ||
346 | } | 329 | } |
347 | 330 | ||
348 | #[test] | 331 | #[test] |
349 | fn test_match_group_in_subtree() { | 332 | fn test_match_group_in_subtree() { |
350 | let rules = create_rules( | 333 | parse_macro( |
351 | r#" | 334 | r#" |
352 | macro_rules! foo { | 335 | macro_rules! foo { |
353 | (fn $name:ident {$($i:ident)*} ) => ( fn $name() { $ ( | 336 | (fn $name:ident {$($i:ident)*} ) => ( fn $name() { $ ( |
354 | $ i (); | 337 | $ i (); |
355 | )*} ); | 338 | )*} ); |
356 | }"#, | 339 | }"#, |
357 | ); | 340 | ) |
358 | 341 | .assert_expand_items("foo! {fn baz {a b} }", "fn baz () {a () ; b () ;}"); | |
359 | assert_expansion(MacroKind::Items, &rules, "foo! {fn baz {a b} }", "fn baz () {a () ; b () ;}"); | ||
360 | } | 342 | } |
361 | 343 | ||
362 | #[test] | 344 | #[test] |
363 | fn test_match_group_with_multichar_sep() { | 345 | fn test_match_group_with_multichar_sep() { |
364 | let rules = create_rules( | 346 | parse_macro( |
365 | r#" | 347 | r#" |
366 | macro_rules! foo { | 348 | macro_rules! foo { |
367 | (fn $name:ident {$($i:literal)*} ) => ( fn $name() -> bool { $($i)&&*} ); | 349 | (fn $name:ident {$($i:literal)*} ) => ( fn $name() -> bool { $($i)&&*} ); |
368 | }"#, | 350 | }"#, |
369 | ); | 351 | ) |
370 | 352 | .assert_expand_items("foo! (fn baz {true true} );", "fn baz () -> bool {true &&true}"); | |
371 | assert_expansion( | ||
372 | MacroKind::Items, | ||
373 | &rules, | ||
374 | "foo! (fn baz {true true} );", | ||
375 | "fn baz () -> bool {true &&true}", | ||
376 | ); | ||
377 | } | 353 | } |
378 | 354 | ||
379 | #[test] | 355 | #[test] |
380 | fn test_match_group_zero_match() { | 356 | fn test_match_group_zero_match() { |
381 | let rules = create_rules( | 357 | parse_macro( |
382 | r#" | 358 | r#" |
383 | macro_rules! foo { | 359 | macro_rules! foo { |
384 | ( $($i:ident)* ) => (); | 360 | ( $($i:ident)* ) => (); |
385 | }"#, | 361 | }"#, |
386 | ); | 362 | ) |
387 | 363 | .assert_expand_items("foo! ();", ""); | |
388 | assert_expansion(MacroKind::Items, &rules, "foo! ();", ""); | ||
389 | } | 364 | } |
390 | 365 | ||
391 | #[test] | 366 | #[test] |
392 | fn test_match_group_in_group() { | 367 | fn test_match_group_in_group() { |
393 | let rules = create_rules( | 368 | parse_macro( |
394 | r#" | 369 | r#" |
395 | macro_rules! foo { | 370 | macro_rules! foo { |
396 | { $( ( $($i:ident)* ) )* } => ( $( ( $($i)* ) )* ); | 371 | { $( ( $($i:ident)* ) )* } => ( $( ( $($i)* ) )* ); |
397 | }"#, | 372 | }"#, |
398 | ); | 373 | ) |
399 | 374 | .assert_expand_items("foo! ( (a b) );", "(a b)"); | |
400 | assert_expansion(MacroKind::Items, &rules, "foo! ( (a b) );", "(a b)"); | ||
401 | } | 375 | } |
402 | 376 | ||
403 | #[test] | 377 | #[test] |
404 | fn test_expand_to_item_list() { | 378 | fn test_expand_to_item_list() { |
405 | let rules = create_rules( | 379 | let tree = parse_macro( |
406 | " | 380 | " |
407 | macro_rules! structs { | 381 | macro_rules! structs { |
408 | ($($i:ident),*) => { | 382 | ($($i:ident),*) => { |
@@ -410,9 +384,8 @@ fn test_expand_to_item_list() { | |||
410 | } | 384 | } |
411 | } | 385 | } |
412 | ", | 386 | ", |
413 | ); | 387 | ) |
414 | let expansion = expand(&rules, "structs!(Foo, Bar);"); | 388 | .expand_items("structs!(Foo, Bar);"); |
415 | let tree = token_tree_to_syntax_node(&expansion, FragmentKind::Items).unwrap().0.syntax_node(); | ||
416 | assert_eq!( | 389 | assert_eq!( |
417 | format!("{:#?}", tree).trim(), | 390 | format!("{:#?}", tree).trim(), |
418 | r#" | 391 | r#" |
@@ -469,7 +442,7 @@ fn test_expand_literals_to_token_tree() { | |||
469 | unreachable!("It is not a literal"); | 442 | unreachable!("It is not a literal"); |
470 | } | 443 | } |
471 | 444 | ||
472 | let rules = create_rules( | 445 | let expansion = parse_macro( |
473 | r#" | 446 | r#" |
474 | macro_rules! literals { | 447 | macro_rules! literals { |
475 | ($i:ident) => { | 448 | ($i:ident) => { |
@@ -482,8 +455,8 @@ fn test_expand_literals_to_token_tree() { | |||
482 | } | 455 | } |
483 | } | 456 | } |
484 | "#, | 457 | "#, |
485 | ); | 458 | ) |
486 | let expansion = expand(&rules, "literals!(foo);"); | 459 | .expand_tt("literals!(foo);"); |
487 | let stm_tokens = &to_subtree(&expansion.token_trees[0]).token_trees; | 460 | let stm_tokens = &to_subtree(&expansion.token_trees[0]).token_trees; |
488 | 461 | ||
489 | // [let] [a] [=] ['c'] [;] | 462 | // [let] [a] [=] ['c'] [;] |
@@ -498,7 +471,7 @@ fn test_expand_literals_to_token_tree() { | |||
498 | 471 | ||
499 | #[test] | 472 | #[test] |
500 | fn test_two_idents() { | 473 | fn test_two_idents() { |
501 | let rules = create_rules( | 474 | parse_macro( |
502 | r#" | 475 | r#" |
503 | macro_rules! foo { | 476 | macro_rules! foo { |
504 | ($ i:ident, $ j:ident) => { | 477 | ($ i:ident, $ j:ident) => { |
@@ -506,18 +479,13 @@ fn test_two_idents() { | |||
506 | } | 479 | } |
507 | } | 480 | } |
508 | "#, | 481 | "#, |
509 | ); | 482 | ) |
510 | assert_expansion( | 483 | .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}"); |
511 | MacroKind::Items, | ||
512 | &rules, | ||
513 | "foo! { foo, bar }", | ||
514 | "fn foo () {let a = foo ; let b = bar ;}", | ||
515 | ); | ||
516 | } | 484 | } |
517 | 485 | ||
518 | #[test] | 486 | #[test] |
519 | fn test_tt_to_stmts() { | 487 | fn test_tt_to_stmts() { |
520 | let rules = create_rules( | 488 | let stmts = parse_macro( |
521 | r#" | 489 | r#" |
522 | macro_rules! foo { | 490 | macro_rules! foo { |
523 | () => { | 491 | () => { |
@@ -527,11 +495,8 @@ fn test_tt_to_stmts() { | |||
527 | } | 495 | } |
528 | } | 496 | } |
529 | "#, | 497 | "#, |
530 | ); | 498 | ) |
531 | 499 | .expand_statements("foo!{}"); | |
532 | let expanded = expand(&rules, "foo!{}"); | ||
533 | let stmts = | ||
534 | token_tree_to_syntax_node(&expanded, FragmentKind::Statements).unwrap().0.syntax_node(); | ||
535 | 500 | ||
536 | assert_eq!( | 501 | assert_eq!( |
537 | format!("{:#?}", stmts).trim(), | 502 | format!("{:#?}", stmts).trim(), |
@@ -571,7 +536,7 @@ fn test_tt_to_stmts() { | |||
571 | 536 | ||
572 | #[test] | 537 | #[test] |
573 | fn test_match_literal() { | 538 | fn test_match_literal() { |
574 | let rules = create_rules( | 539 | parse_macro( |
575 | r#" | 540 | r#" |
576 | macro_rules! foo { | 541 | macro_rules! foo { |
577 | ('(') => { | 542 | ('(') => { |
@@ -579,8 +544,8 @@ fn test_match_literal() { | |||
579 | } | 544 | } |
580 | } | 545 | } |
581 | "#, | 546 | "#, |
582 | ); | 547 | ) |
583 | assert_expansion(MacroKind::Items, &rules, "foo! ['('];", "fn foo () {}"); | 548 | .assert_expand_items("foo! ['('];", "fn foo () {}"); |
584 | } | 549 | } |
585 | 550 | ||
586 | // The following tests are port from intellij-rust directly | 551 | // The following tests are port from intellij-rust directly |
@@ -588,7 +553,7 @@ fn test_match_literal() { | |||
588 | 553 | ||
589 | #[test] | 554 | #[test] |
590 | fn test_path() { | 555 | fn test_path() { |
591 | let rules = create_rules( | 556 | parse_macro( |
592 | r#" | 557 | r#" |
593 | macro_rules! foo { | 558 | macro_rules! foo { |
594 | ($ i:path) => { | 559 | ($ i:path) => { |
@@ -596,11 +561,9 @@ fn test_path() { | |||
596 | } | 561 | } |
597 | } | 562 | } |
598 | "#, | 563 | "#, |
599 | ); | 564 | ) |
600 | assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "fn foo () {let a = foo ;}"); | 565 | .assert_expand_items("foo! { foo }", "fn foo () {let a = foo ;}") |
601 | assert_expansion( | 566 | .assert_expand_items( |
602 | MacroKind::Items, | ||
603 | &rules, | ||
604 | "foo! { bar::<u8>::baz::<u8> }", | 567 | "foo! { bar::<u8>::baz::<u8> }", |
605 | "fn foo () {let a = bar ::< u8 >:: baz ::< u8 > ;}", | 568 | "fn foo () {let a = bar ::< u8 >:: baz ::< u8 > ;}", |
606 | ); | 569 | ); |
@@ -608,7 +571,7 @@ fn test_path() { | |||
608 | 571 | ||
609 | #[test] | 572 | #[test] |
610 | fn test_two_paths() { | 573 | fn test_two_paths() { |
611 | let rules = create_rules( | 574 | parse_macro( |
612 | r#" | 575 | r#" |
613 | macro_rules! foo { | 576 | macro_rules! foo { |
614 | ($ i:path, $ j:path) => { | 577 | ($ i:path, $ j:path) => { |
@@ -616,18 +579,13 @@ fn test_two_paths() { | |||
616 | } | 579 | } |
617 | } | 580 | } |
618 | "#, | 581 | "#, |
619 | ); | 582 | ) |
620 | assert_expansion( | 583 | .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}"); |
621 | MacroKind::Items, | ||
622 | &rules, | ||
623 | "foo! { foo, bar }", | ||
624 | "fn foo () {let a = foo ; let b = bar ;}", | ||
625 | ); | ||
626 | } | 584 | } |
627 | 585 | ||
628 | #[test] | 586 | #[test] |
629 | fn test_path_with_path() { | 587 | fn test_path_with_path() { |
630 | let rules = create_rules( | 588 | parse_macro( |
631 | r#" | 589 | r#" |
632 | macro_rules! foo { | 590 | macro_rules! foo { |
633 | ($ i:path) => { | 591 | ($ i:path) => { |
@@ -635,13 +593,13 @@ fn test_path_with_path() { | |||
635 | } | 593 | } |
636 | } | 594 | } |
637 | "#, | 595 | "#, |
638 | ); | 596 | ) |
639 | assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "fn foo () {let a = foo :: bar ;}"); | 597 | .assert_expand_items("foo! { foo }", "fn foo () {let a = foo :: bar ;}"); |
640 | } | 598 | } |
641 | 599 | ||
642 | #[test] | 600 | #[test] |
643 | fn test_expr() { | 601 | fn test_expr() { |
644 | let rules = create_rules( | 602 | parse_macro( |
645 | r#" | 603 | r#" |
646 | macro_rules! foo { | 604 | macro_rules! foo { |
647 | ($ i:expr) => { | 605 | ($ i:expr) => { |
@@ -649,11 +607,8 @@ fn test_expr() { | |||
649 | } | 607 | } |
650 | } | 608 | } |
651 | "#, | 609 | "#, |
652 | ); | 610 | ) |
653 | 611 | .assert_expand_items( | |
654 | assert_expansion( | ||
655 | MacroKind::Items, | ||
656 | &rules, | ||
657 | "foo! { 2 + 2 * baz(3).quux() }", | 612 | "foo! { 2 + 2 * baz(3).quux() }", |
658 | "fn bar () {2 + 2 * baz (3) . quux () ;}", | 613 | "fn bar () {2 + 2 * baz (3) . quux () ;}", |
659 | ); | 614 | ); |
@@ -661,7 +616,7 @@ fn test_expr() { | |||
661 | 616 | ||
662 | #[test] | 617 | #[test] |
663 | fn test_last_expr() { | 618 | fn test_last_expr() { |
664 | let rules = create_rules( | 619 | parse_macro( |
665 | r#" | 620 | r#" |
666 | macro_rules! vec { | 621 | macro_rules! vec { |
667 | ($($item:expr),*) => { | 622 | ($($item:expr),*) => { |
@@ -675,10 +630,8 @@ fn test_last_expr() { | |||
675 | }; | 630 | }; |
676 | } | 631 | } |
677 | "#, | 632 | "#, |
678 | ); | 633 | ) |
679 | assert_expansion( | 634 | .assert_expand_items( |
680 | MacroKind::Items, | ||
681 | &rules, | ||
682 | "vec!(1,2,3);", | 635 | "vec!(1,2,3);", |
683 | "{let mut v = Vec :: new () ; v . push (1) ; v . push (2) ; v . push (3) ; v}", | 636 | "{let mut v = Vec :: new () ; v . push (1) ; v . push (2) ; v . push (3) ; v}", |
684 | ); | 637 | ); |
@@ -686,7 +639,7 @@ fn test_last_expr() { | |||
686 | 639 | ||
687 | #[test] | 640 | #[test] |
688 | fn test_ty() { | 641 | fn test_ty() { |
689 | let rules = create_rules( | 642 | parse_macro( |
690 | r#" | 643 | r#" |
691 | macro_rules! foo { | 644 | macro_rules! foo { |
692 | ($ i:ty) => ( | 645 | ($ i:ty) => ( |
@@ -694,18 +647,13 @@ fn test_ty() { | |||
694 | ) | 647 | ) |
695 | } | 648 | } |
696 | "#, | 649 | "#, |
697 | ); | 650 | ) |
698 | assert_expansion( | 651 | .assert_expand_items("foo! { Baz<u8> }", "fn bar () -> Baz < u8 > {unimplemented ! ()}"); |
699 | MacroKind::Items, | ||
700 | &rules, | ||
701 | "foo! { Baz<u8> }", | ||
702 | "fn bar () -> Baz < u8 > {unimplemented ! ()}", | ||
703 | ); | ||
704 | } | 652 | } |
705 | 653 | ||
706 | #[test] | 654 | #[test] |
707 | fn test_ty_with_complex_type() { | 655 | fn test_ty_with_complex_type() { |
708 | let rules = create_rules( | 656 | parse_macro( |
709 | r#" | 657 | r#" |
710 | macro_rules! foo { | 658 | macro_rules! foo { |
711 | ($ i:ty) => ( | 659 | ($ i:ty) => ( |
@@ -713,20 +661,14 @@ fn test_ty_with_complex_type() { | |||
713 | ) | 661 | ) |
714 | } | 662 | } |
715 | "#, | 663 | "#, |
716 | ); | 664 | ) |
717 | |||
718 | // Reference lifetime struct with generic type | 665 | // Reference lifetime struct with generic type |
719 | assert_expansion( | 666 | .assert_expand_items( |
720 | MacroKind::Items, | ||
721 | &rules, | ||
722 | "foo! { &'a Baz<u8> }", | 667 | "foo! { &'a Baz<u8> }", |
723 | "fn bar () -> & 'a Baz < u8 > {unimplemented ! ()}", | 668 | "fn bar () -> & 'a Baz < u8 > {unimplemented ! ()}", |
724 | ); | 669 | ) |
725 | |||
726 | // extern "Rust" func type | 670 | // extern "Rust" func type |
727 | assert_expansion( | 671 | .assert_expand_items( |
728 | MacroKind::Items, | ||
729 | &rules, | ||
730 | r#"foo! { extern "Rust" fn() -> Ret }"#, | 672 | r#"foo! { extern "Rust" fn() -> Ret }"#, |
731 | r#"fn bar () -> extern "Rust" fn () -> Ret {unimplemented ! ()}"#, | 673 | r#"fn bar () -> extern "Rust" fn () -> Ret {unimplemented ! ()}"#, |
732 | ); | 674 | ); |
@@ -734,19 +676,19 @@ fn test_ty_with_complex_type() { | |||
734 | 676 | ||
735 | #[test] | 677 | #[test] |
736 | fn test_pat_() { | 678 | fn test_pat_() { |
737 | let rules = create_rules( | 679 | parse_macro( |
738 | r#" | 680 | r#" |
739 | macro_rules! foo { | 681 | macro_rules! foo { |
740 | ($ i:pat) => { fn foo() { let $ i; } } | 682 | ($ i:pat) => { fn foo() { let $ i; } } |
741 | } | 683 | } |
742 | "#, | 684 | "#, |
743 | ); | 685 | ) |
744 | assert_expansion(MacroKind::Items, &rules, "foo! { (a, b) }", "fn foo () {let (a , b) ;}"); | 686 | .assert_expand_items("foo! { (a, b) }", "fn foo () {let (a , b) ;}"); |
745 | } | 687 | } |
746 | 688 | ||
747 | #[test] | 689 | #[test] |
748 | fn test_stmt() { | 690 | fn test_stmt() { |
749 | let rules = create_rules( | 691 | parse_macro( |
750 | r#" | 692 | r#" |
751 | macro_rules! foo { | 693 | macro_rules! foo { |
752 | ($ i:stmt) => ( | 694 | ($ i:stmt) => ( |
@@ -754,14 +696,14 @@ fn test_stmt() { | |||
754 | ) | 696 | ) |
755 | } | 697 | } |
756 | "#, | 698 | "#, |
757 | ); | 699 | ) |
758 | assert_expansion(MacroKind::Items, &rules, "foo! { 2 }", "fn bar () {2 ;}"); | 700 | .assert_expand_items("foo! { 2 }", "fn bar () {2 ;}") |
759 | assert_expansion(MacroKind::Items, &rules, "foo! { let a = 0 }", "fn bar () {let a = 0 ;}"); | 701 | .assert_expand_items("foo! { let a = 0 }", "fn bar () {let a = 0 ;}"); |
760 | } | 702 | } |
761 | 703 | ||
762 | #[test] | 704 | #[test] |
763 | fn test_single_item() { | 705 | fn test_single_item() { |
764 | let rules = create_rules( | 706 | parse_macro( |
765 | r#" | 707 | r#" |
766 | macro_rules! foo { | 708 | macro_rules! foo { |
767 | ($ i:item) => ( | 709 | ($ i:item) => ( |
@@ -769,13 +711,13 @@ fn test_single_item() { | |||
769 | ) | 711 | ) |
770 | } | 712 | } |
771 | "#, | 713 | "#, |
772 | ); | 714 | ) |
773 | assert_expansion(MacroKind::Items, &rules, "foo! {mod c {}}", "mod c {}"); | 715 | .assert_expand_items("foo! {mod c {}}", "mod c {}"); |
774 | } | 716 | } |
775 | 717 | ||
776 | #[test] | 718 | #[test] |
777 | fn test_all_items() { | 719 | fn test_all_items() { |
778 | let rules = create_rules( | 720 | parse_macro( |
779 | r#" | 721 | r#" |
780 | macro_rules! foo { | 722 | macro_rules! foo { |
781 | ($ ($ i:item)*) => ($ ( | 723 | ($ ($ i:item)*) => ($ ( |
@@ -783,10 +725,8 @@ fn test_all_items() { | |||
783 | )*) | 725 | )*) |
784 | } | 726 | } |
785 | "#, | 727 | "#, |
786 | ); | 728 | ). |
787 | assert_expansion( | 729 | assert_expand_items( |
788 | MacroKind::Items, | ||
789 | &rules, | ||
790 | r#" | 730 | r#" |
791 | foo! { | 731 | foo! { |
792 | extern crate a; | 732 | extern crate a; |
@@ -810,19 +750,19 @@ fn test_all_items() { | |||
810 | 750 | ||
811 | #[test] | 751 | #[test] |
812 | fn test_block() { | 752 | fn test_block() { |
813 | let rules = create_rules( | 753 | parse_macro( |
814 | r#" | 754 | r#" |
815 | macro_rules! foo { | 755 | macro_rules! foo { |
816 | ($ i:block) => { fn foo() $ i } | 756 | ($ i:block) => { fn foo() $ i } |
817 | } | 757 | } |
818 | "#, | 758 | "#, |
819 | ); | 759 | ) |
820 | assert_expansion(MacroKind::Stmts, &rules, "foo! { { 1; } }", "fn foo () {1 ;}"); | 760 | .assert_expand_statements("foo! { { 1; } }", "fn foo () {1 ;}"); |
821 | } | 761 | } |
822 | 762 | ||
823 | #[test] | 763 | #[test] |
824 | fn test_meta() { | 764 | fn test_meta() { |
825 | let rules = create_rules( | 765 | parse_macro( |
826 | r#" | 766 | r#" |
827 | macro_rules! foo { | 767 | macro_rules! foo { |
828 | ($ i:meta) => ( | 768 | ($ i:meta) => ( |
@@ -831,10 +771,8 @@ fn test_meta() { | |||
831 | ) | 771 | ) |
832 | } | 772 | } |
833 | "#, | 773 | "#, |
834 | ); | 774 | ) |
835 | assert_expansion( | 775 | .assert_expand_items( |
836 | MacroKind::Items, | ||
837 | &rules, | ||
838 | r#"foo! { cfg(target_os = "windows") }"#, | 776 | r#"foo! { cfg(target_os = "windows") }"#, |
839 | r#"# [cfg (target_os = "windows")] fn bar () {}"#, | 777 | r#"# [cfg (target_os = "windows")] fn bar () {}"#, |
840 | ); | 778 | ); |
@@ -842,7 +780,7 @@ fn test_meta() { | |||
842 | 780 | ||
843 | #[test] | 781 | #[test] |
844 | fn test_meta_doc_comments() { | 782 | fn test_meta_doc_comments() { |
845 | let rules = create_rules( | 783 | parse_macro( |
846 | r#" | 784 | r#" |
847 | macro_rules! foo { | 785 | macro_rules! foo { |
848 | ($(#[$ i:meta])+) => ( | 786 | ($(#[$ i:meta])+) => ( |
@@ -851,10 +789,8 @@ fn test_meta_doc_comments() { | |||
851 | ) | 789 | ) |
852 | } | 790 | } |
853 | "#, | 791 | "#, |
854 | ); | 792 | ). |
855 | assert_expansion( | 793 | assert_expand_items( |
856 | MacroKind::Items, | ||
857 | &rules, | ||
858 | r#"foo! { | 794 | r#"foo! { |
859 | /// Single Line Doc 1 | 795 | /// Single Line Doc 1 |
860 | /** | 796 | /** |
@@ -867,69 +803,68 @@ fn test_meta_doc_comments() { | |||
867 | 803 | ||
868 | #[test] | 804 | #[test] |
869 | fn test_tt_block() { | 805 | fn test_tt_block() { |
870 | let rules = create_rules( | 806 | parse_macro( |
871 | r#" | 807 | r#" |
872 | macro_rules! foo { | 808 | macro_rules! foo { |
873 | ($ i:tt) => { fn foo() $ i } | 809 | ($ i:tt) => { fn foo() $ i } |
874 | } | 810 | } |
875 | "#, | 811 | "#, |
876 | ); | 812 | ) |
877 | assert_expansion(MacroKind::Items, &rules, r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#); | 813 | .assert_expand_items(r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#); |
878 | } | 814 | } |
879 | 815 | ||
880 | #[test] | 816 | #[test] |
881 | fn test_tt_group() { | 817 | fn test_tt_group() { |
882 | let rules = create_rules( | 818 | parse_macro( |
883 | r#" | 819 | r#" |
884 | macro_rules! foo { | 820 | macro_rules! foo { |
885 | ($($ i:tt)*) => { $($ i)* } | 821 | ($($ i:tt)*) => { $($ i)* } |
886 | } | 822 | } |
887 | "#, | 823 | "#, |
888 | ); | 824 | ) |
889 | assert_expansion(MacroKind::Items, &rules, r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); | 825 | .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); |
890 | } | 826 | } |
891 | #[test] | 827 | #[test] |
892 | fn test_lifetime() { | 828 | fn test_lifetime() { |
893 | let rules = create_rules( | 829 | parse_macro( |
894 | r#" | 830 | r#" |
895 | macro_rules! foo { | 831 | macro_rules! foo { |
896 | ($ lt:lifetime) => { struct Ref<$ lt>{ s: &$ lt str } } | 832 | ($ lt:lifetime) => { struct Ref<$ lt>{ s: &$ lt str } } |
897 | } | 833 | } |
898 | "#, | 834 | "#, |
899 | ); | 835 | ) |
900 | assert_expansion(MacroKind::Items, &rules, r#"foo!{'a}"#, r#"struct Ref <'a > {s : &'a str}"#); | 836 | .assert_expand_items(r#"foo!{'a}"#, r#"struct Ref <'a > {s : &'a str}"#); |
901 | } | 837 | } |
902 | 838 | ||
903 | #[test] | 839 | #[test] |
904 | fn test_literal() { | 840 | fn test_literal() { |
905 | let rules = create_rules( | 841 | parse_macro( |
906 | r#" | 842 | r#" |
907 | macro_rules! foo { | 843 | macro_rules! foo { |
908 | ($ type:ty $ lit:literal) => { const VALUE: $ type = $ lit;}; | 844 | ($ type:ty $ lit:literal) => { const VALUE: $ type = $ lit;}; |
909 | } | 845 | } |
910 | "#, | 846 | "#, |
911 | ); | 847 | ) |
912 | assert_expansion(MacroKind::Items, &rules, r#"foo!(u8 0);"#, r#"const VALUE : u8 = 0 ;"#); | 848 | .assert_expand_items(r#"foo!(u8 0);"#, r#"const VALUE : u8 = 0 ;"#); |
913 | } | 849 | } |
914 | 850 | ||
915 | #[test] | 851 | #[test] |
916 | fn test_vis() { | 852 | fn test_vis() { |
917 | let rules = create_rules( | 853 | parse_macro( |
918 | r#" | 854 | r#" |
919 | macro_rules! foo { | 855 | macro_rules! foo { |
920 | ($ vis:vis $ name:ident) => { $ vis fn $ name() {}}; | 856 | ($ vis:vis $ name:ident) => { $ vis fn $ name() {}}; |
921 | } | 857 | } |
922 | "#, | 858 | "#, |
923 | ); | 859 | ) |
924 | assert_expansion(MacroKind::Items, &rules, r#"foo!(pub foo);"#, r#"pub fn foo () {}"#); | 860 | .assert_expand_items(r#"foo!(pub foo);"#, r#"pub fn foo () {}"#) |
925 | 861 | // test optional cases | |
926 | // test optional casse | 862 | .assert_expand_items(r#"foo!(foo);"#, r#"fn foo () {}"#); |
927 | assert_expansion(MacroKind::Items, &rules, r#"foo!(foo);"#, r#"fn foo () {}"#); | ||
928 | } | 863 | } |
929 | 864 | ||
930 | #[test] | 865 | #[test] |
931 | fn test_inner_macro_rules() { | 866 | fn test_inner_macro_rules() { |
932 | let rules = create_rules( | 867 | parse_macro( |
933 | r#" | 868 | r#" |
934 | macro_rules! foo { | 869 | macro_rules! foo { |
935 | ($a:ident, $b:ident, $c:tt) => { | 870 | ($a:ident, $b:ident, $c:tt) => { |
@@ -945,10 +880,8 @@ macro_rules! foo { | |||
945 | } | 880 | } |
946 | } | 881 | } |
947 | "#, | 882 | "#, |
948 | ); | 883 | ). |
949 | assert_expansion( | 884 | assert_expand_items( |
950 | MacroKind::Items, | ||
951 | &rules, | ||
952 | r#"foo!(x,y, 1);"#, | 885 | r#"foo!(x,y, 1);"#, |
953 | r#"macro_rules ! bar {($ bi : ident) => {fn $ bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#, | 886 | r#"macro_rules ! bar {($ bi : ident) => {fn $ bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#, |
954 | ); | 887 | ); |
@@ -957,7 +890,7 @@ macro_rules! foo { | |||
957 | // The following tests are based on real world situations | 890 | // The following tests are based on real world situations |
958 | #[test] | 891 | #[test] |
959 | fn test_vec() { | 892 | fn test_vec() { |
960 | let rules = create_rules( | 893 | let fixture = parse_macro( |
961 | r#" | 894 | r#" |
962 | macro_rules! vec { | 895 | macro_rules! vec { |
963 | ($($item:expr),*) => { | 896 | ($($item:expr),*) => { |
@@ -972,16 +905,14 @@ fn test_vec() { | |||
972 | } | 905 | } |
973 | "#, | 906 | "#, |
974 | ); | 907 | ); |
975 | assert_expansion(MacroKind::Items, &rules, r#"vec!();"#, r#"{let mut v = Vec :: new () ; v}"#); | 908 | fixture |
976 | assert_expansion( | 909 | .assert_expand_items(r#"vec!();"#, r#"{let mut v = Vec :: new () ; v}"#) |
977 | MacroKind::Items, | 910 | .assert_expand_items( |
978 | &rules, | 911 | r#"vec![1u32,2];"#, |
979 | r#"vec![1u32,2];"#, | 912 | r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#, |
980 | r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#, | 913 | ); |
981 | ); | ||
982 | 914 | ||
983 | let expansion = expand(&rules, r#"vec![1u32,2];"#); | 915 | let tree = fixture.expand_expr(r#"vec![1u32,2];"#); |
984 | let tree = token_tree_to_syntax_node(&expansion, FragmentKind::Expr).unwrap().0.syntax_node(); | ||
985 | 916 | ||
986 | assert_eq!( | 917 | assert_eq!( |
987 | format!("{:#?}", tree).trim(), | 918 | format!("{:#?}", tree).trim(), |
@@ -1055,7 +986,7 @@ fn test_vec() { | |||
1055 | fn test_winapi_struct() { | 986 | fn test_winapi_struct() { |
1056 | // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366 | 987 | // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366 |
1057 | 988 | ||
1058 | let rules = create_rules( | 989 | parse_macro( |
1059 | r#" | 990 | r#" |
1060 | macro_rules! STRUCT { | 991 | macro_rules! STRUCT { |
1061 | ($(#[$attrs:meta])* struct $name:ident { | 992 | ($(#[$attrs:meta])* struct $name:ident { |
@@ -1077,17 +1008,19 @@ macro_rules! STRUCT { | |||
1077 | ); | 1008 | ); |
1078 | } | 1009 | } |
1079 | "#, | 1010 | "#, |
1080 | ); | 1011 | ). |
1081 | // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs | 1012 | // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs |
1082 | assert_expansion(MacroKind::Items, &rules, r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#, | 1013 | assert_expand_items(r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#, |
1083 | "# [repr (C)] # [derive (Copy)] pub struct D3DVSHADERCAPS2_0 {pub Caps : u8 ,} impl Clone for D3DVSHADERCAPS2_0 {# [inline] fn clone (& self) -> D3DVSHADERCAPS2_0 {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DVSHADERCAPS2_0 {# [inline] fn default () -> D3DVSHADERCAPS2_0 {unsafe {$crate :: _core :: mem :: zeroed ()}}}"); | 1014 | "# [repr (C)] # [derive (Copy)] pub struct D3DVSHADERCAPS2_0 {pub Caps : u8 ,} impl Clone for D3DVSHADERCAPS2_0 {# [inline] fn clone (& self) -> D3DVSHADERCAPS2_0 {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DVSHADERCAPS2_0 {# [inline] fn default () -> D3DVSHADERCAPS2_0 {unsafe {$crate :: _core :: mem :: zeroed ()}}}" |
1084 | assert_expansion(MacroKind::Items, &rules, r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#, | 1015 | ) |
1085 | "# [repr (C)] # [derive (Copy)] # [cfg_attr (target_arch = \"x86\" , repr (packed))] pub struct D3DCONTENTPROTECTIONCAPS {pub Caps : u8 ,} impl Clone for D3DCONTENTPROTECTIONCAPS {# [inline] fn clone (& self) -> D3DCONTENTPROTECTIONCAPS {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DCONTENTPROTECTIONCAPS {# [inline] fn default () -> D3DCONTENTPROTECTIONCAPS {unsafe {$crate :: _core :: mem :: zeroed ()}}}"); | 1016 | .assert_expand_items(r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#, |
1017 | "# [repr (C)] # [derive (Copy)] # [cfg_attr (target_arch = \"x86\" , repr (packed))] pub struct D3DCONTENTPROTECTIONCAPS {pub Caps : u8 ,} impl Clone for D3DCONTENTPROTECTIONCAPS {# [inline] fn clone (& self) -> D3DCONTENTPROTECTIONCAPS {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DCONTENTPROTECTIONCAPS {# [inline] fn default () -> D3DCONTENTPROTECTIONCAPS {unsafe {$crate :: _core :: mem :: zeroed ()}}}" | ||
1018 | ); | ||
1086 | } | 1019 | } |
1087 | 1020 | ||
1088 | #[test] | 1021 | #[test] |
1089 | fn test_int_base() { | 1022 | fn test_int_base() { |
1090 | let rules = create_rules( | 1023 | parse_macro( |
1091 | r#" | 1024 | r#" |
1092 | macro_rules! int_base { | 1025 | macro_rules! int_base { |
1093 | ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { | 1026 | ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { |
@@ -1100,17 +1033,15 @@ macro_rules! int_base { | |||
1100 | } | 1033 | } |
1101 | } | 1034 | } |
1102 | "#, | 1035 | "#, |
1103 | ); | 1036 | ).assert_expand_items(r#" int_base!{Binary for isize as usize -> Binary}"#, |
1104 | |||
1105 | assert_expansion(MacroKind::Items, &rules, r#" int_base!{Binary for isize as usize -> Binary}"#, | ||
1106 | "# [stable (feature = \"rust1\" , since = \"1.0.0\")] impl fmt ::Binary for isize {fn fmt (& self , f : & mut fmt :: Formatter < \'_ >) -> fmt :: Result {Binary . fmt_int (* self as usize , f)}}" | 1037 | "# [stable (feature = \"rust1\" , since = \"1.0.0\")] impl fmt ::Binary for isize {fn fmt (& self , f : & mut fmt :: Formatter < \'_ >) -> fmt :: Result {Binary . fmt_int (* self as usize , f)}}" |
1107 | ); | 1038 | ); |
1108 | } | 1039 | } |
1109 | 1040 | ||
1110 | #[test] | 1041 | #[test] |
1111 | fn test_generate_pattern_iterators() { | 1042 | fn test_generate_pattern_iterators() { |
1112 | // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs | 1043 | // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs |
1113 | let rules = create_rules( | 1044 | parse_macro( |
1114 | r#" | 1045 | r#" |
1115 | macro_rules! generate_pattern_iterators { | 1046 | macro_rules! generate_pattern_iterators { |
1116 | { double ended; with $(#[$common_stability_attribute:meta])*, | 1047 | { double ended; with $(#[$common_stability_attribute:meta])*, |
@@ -1121,11 +1052,7 @@ macro_rules! generate_pattern_iterators { | |||
1121 | } | 1052 | } |
1122 | } | 1053 | } |
1123 | "#, | 1054 | "#, |
1124 | ); | 1055 | ).assert_expand_items( |
1125 | |||
1126 | assert_expansion( | ||
1127 | MacroKind::Items, | ||
1128 | &rules, | ||
1129 | r#"generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str );"#, | 1056 | r#"generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str );"#, |
1130 | "fn foo () {}", | 1057 | "fn foo () {}", |
1131 | ); | 1058 | ); |
@@ -1134,7 +1061,7 @@ macro_rules! generate_pattern_iterators { | |||
1134 | #[test] | 1061 | #[test] |
1135 | fn test_impl_fn_for_zst() { | 1062 | fn test_impl_fn_for_zst() { |
1136 | // from https://github.com/rust-lang/rust/blob/5d20ff4d2718c820632b38c1e49d4de648a9810b/src/libcore/internal_macros.rs | 1063 | // from https://github.com/rust-lang/rust/blob/5d20ff4d2718c820632b38c1e49d4de648a9810b/src/libcore/internal_macros.rs |
1137 | let rules = create_rules( | 1064 | parse_macro( |
1138 | r#" | 1065 | r#" |
1139 | macro_rules! impl_fn_for_zst { | 1066 | macro_rules! impl_fn_for_zst { |
1140 | { $( $( #[$attr: meta] )* | 1067 | { $( $( #[$attr: meta] )* |
@@ -1175,9 +1102,7 @@ $body: block; )+ | |||
1175 | } | 1102 | } |
1176 | } | 1103 | } |
1177 | "#, | 1104 | "#, |
1178 | ); | 1105 | ).assert_expand_items(r#" |
1179 | |||
1180 | assert_expansion(MacroKind::Items, &rules, r#" | ||
1181 | impl_fn_for_zst ! { | 1106 | impl_fn_for_zst ! { |
1182 | # [ derive ( Clone ) ] | 1107 | # [ derive ( Clone ) ] |
1183 | struct CharEscapeDebugContinue impl Fn = | c : char | -> char :: EscapeDebug { | 1108 | struct CharEscapeDebugContinue impl Fn = | c : char | -> char :: EscapeDebug { |
@@ -1194,13 +1119,14 @@ impl_fn_for_zst ! { | |||
1194 | } ; | 1119 | } ; |
1195 | } | 1120 | } |
1196 | "#, | 1121 | "#, |
1197 | "# [derive (Clone)] struct CharEscapeDebugContinue ; impl Fn < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDebug {{c . escape_debug_ext (false)}}} impl FnMut < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDebugContinue {type Output = char :: EscapeDebug ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeUnicode ; impl Fn < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeUnicode {{c . escape_unicode ()}}} impl FnMut < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeUnicode {type Output = char :: EscapeUnicode ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeDefault ; impl Fn < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDefault {{c . escape_default ()}}} impl FnMut < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDefault {type Output = char :: EscapeDefault ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (& self , (c ,))}}"); | 1122 | "# [derive (Clone)] struct CharEscapeDebugContinue ; impl Fn < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDebug {{c . escape_debug_ext (false)}}} impl FnMut < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDebugContinue {type Output = char :: EscapeDebug ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeUnicode ; impl Fn < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeUnicode {{c . escape_unicode ()}}} impl FnMut < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeUnicode {type Output = char :: EscapeUnicode ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeDefault ; impl Fn < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDefault {{c . escape_default ()}}} impl FnMut < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDefault {type Output = char :: EscapeDefault ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (& self , (c ,))}}" |
1123 | ); | ||
1198 | } | 1124 | } |
1199 | 1125 | ||
1200 | #[test] | 1126 | #[test] |
1201 | fn test_impl_nonzero_fmt() { | 1127 | fn test_impl_nonzero_fmt() { |
1202 | // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12 | 1128 | // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12 |
1203 | let rules = create_rules( | 1129 | parse_macro( |
1204 | r#" | 1130 | r#" |
1205 | macro_rules! impl_nonzero_fmt { | 1131 | macro_rules! impl_nonzero_fmt { |
1206 | ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { | 1132 | ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { |
@@ -1208,11 +1134,7 @@ fn test_impl_nonzero_fmt() { | |||
1208 | } | 1134 | } |
1209 | } | 1135 | } |
1210 | "#, | 1136 | "#, |
1211 | ); | 1137 | ).assert_expand_items( |
1212 | |||
1213 | assert_expansion( | ||
1214 | MacroKind::Items, | ||
1215 | &rules, | ||
1216 | r#"impl_nonzero_fmt! { # [stable(feature= "nonzero",since="1.28.0")] (Debug,Display,Binary,Octal,LowerHex,UpperHex) for NonZeroU8}"#, | 1138 | r#"impl_nonzero_fmt! { # [stable(feature= "nonzero",since="1.28.0")] (Debug,Display,Binary,Octal,LowerHex,UpperHex) for NonZeroU8}"#, |
1217 | "fn foo () {}", | 1139 | "fn foo () {}", |
1218 | ); | 1140 | ); |
@@ -1221,7 +1143,7 @@ fn test_impl_nonzero_fmt() { | |||
1221 | #[test] | 1143 | #[test] |
1222 | fn test_cfg_if_items() { | 1144 | fn test_cfg_if_items() { |
1223 | // from https://github.com/rust-lang/rust/blob/33fe1131cadba69d317156847be9a402b89f11bb/src/libstd/macros.rs#L986 | 1145 | // from https://github.com/rust-lang/rust/blob/33fe1131cadba69d317156847be9a402b89f11bb/src/libstd/macros.rs#L986 |
1224 | let rules = create_rules( | 1146 | parse_macro( |
1225 | r#" | 1147 | r#" |
1226 | macro_rules! __cfg_if_items { | 1148 | macro_rules! __cfg_if_items { |
1227 | (($($not:meta,)*) ; ) => {}; | 1149 | (($($not:meta,)*) ; ) => {}; |
@@ -1230,11 +1152,7 @@ fn test_cfg_if_items() { | |||
1230 | } | 1152 | } |
1231 | } | 1153 | } |
1232 | "#, | 1154 | "#, |
1233 | ); | 1155 | ).assert_expand_items( |
1234 | |||
1235 | assert_expansion( | ||
1236 | MacroKind::Items, | ||
1237 | &rules, | ||
1238 | r#"__cfg_if_items ! { ( rustdoc , ) ; ( ( ) ( # [ cfg ( any ( target_os = "redox" , unix ) ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as unix ; # [ cfg ( windows ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as windows ; # [ cfg ( any ( target_os = "linux" , target_os = "l4re" ) ) ] pub mod linux ; ) ) , }"#, | 1156 | r#"__cfg_if_items ! { ( rustdoc , ) ; ( ( ) ( # [ cfg ( any ( target_os = "redox" , unix ) ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as unix ; # [ cfg ( windows ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as windows ; # [ cfg ( any ( target_os = "linux" , target_os = "l4re" ) ) ] pub mod linux ; ) ) , }"#, |
1239 | "__cfg_if_items ! {(rustdoc ,) ;}", | 1157 | "__cfg_if_items ! {(rustdoc ,) ;}", |
1240 | ); | 1158 | ); |
@@ -1243,7 +1161,7 @@ fn test_cfg_if_items() { | |||
1243 | #[test] | 1161 | #[test] |
1244 | fn test_cfg_if_main() { | 1162 | fn test_cfg_if_main() { |
1245 | // from https://github.com/rust-lang/rust/blob/3d211248393686e0f73851fc7548f6605220fbe1/src/libpanic_unwind/macros.rs#L9 | 1163 | // from https://github.com/rust-lang/rust/blob/3d211248393686e0f73851fc7548f6605220fbe1/src/libpanic_unwind/macros.rs#L9 |
1246 | let rules = create_rules( | 1164 | parse_macro( |
1247 | r#" | 1165 | r#" |
1248 | macro_rules! cfg_if { | 1166 | macro_rules! cfg_if { |
1249 | ($( | 1167 | ($( |
@@ -1264,9 +1182,7 @@ fn test_cfg_if_main() { | |||
1264 | }; | 1182 | }; |
1265 | } | 1183 | } |
1266 | "#, | 1184 | "#, |
1267 | ); | 1185 | ).assert_expand_items(r#" |
1268 | |||
1269 | assert_expansion(MacroKind::Items, &rules, r#" | ||
1270 | cfg_if ! { | 1186 | cfg_if ! { |
1271 | if # [ cfg ( target_env = "msvc" ) ] { | 1187 | if # [ cfg ( target_env = "msvc" ) ] { |
1272 | // no extra unwinder support needed | 1188 | // no extra unwinder support needed |
@@ -1278,11 +1194,8 @@ cfg_if ! { | |||
1278 | } | 1194 | } |
1279 | } | 1195 | } |
1280 | "#, | 1196 | "#, |
1281 | "__cfg_if_items ! {() ; ((target_env = \"msvc\") ()) , ((all (target_arch = \"wasm32\" , not (target_os = \"emscripten\"))) ()) , (() (mod libunwind ; pub use libunwind :: * ;)) ,}"); | 1197 | "__cfg_if_items ! {() ; ((target_env = \"msvc\") ()) , ((all (target_arch = \"wasm32\" , not (target_os = \"emscripten\"))) ()) , (() (mod libunwind ; pub use libunwind :: * ;)) ,}" |
1282 | 1198 | ).assert_expand_items( | |
1283 | assert_expansion( | ||
1284 | MacroKind::Items, | ||
1285 | &rules, | ||
1286 | r#" | 1199 | r#" |
1287 | cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , target_os = "illumos" ) ) ) ) ) ) , } | 1200 | cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , target_os = "illumos" ) ) ) ) ) ) , } |
1288 | "#, | 1201 | "#, |
@@ -1293,7 +1206,7 @@ cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , | |||
1293 | #[test] | 1206 | #[test] |
1294 | fn test_proptest_arbitrary() { | 1207 | fn test_proptest_arbitrary() { |
1295 | // from https://github.com/AltSysrq/proptest/blob/d1c4b049337d2f75dd6f49a095115f7c532e5129/proptest/src/arbitrary/macros.rs#L16 | 1208 | // from https://github.com/AltSysrq/proptest/blob/d1c4b049337d2f75dd6f49a095115f7c532e5129/proptest/src/arbitrary/macros.rs#L16 |
1296 | let rules = create_rules( | 1209 | parse_macro( |
1297 | r#" | 1210 | r#" |
1298 | macro_rules! arbitrary { | 1211 | macro_rules! arbitrary { |
1299 | ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty; | 1212 | ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty; |
@@ -1308,22 +1221,21 @@ macro_rules! arbitrary { | |||
1308 | }; | 1221 | }; |
1309 | 1222 | ||
1310 | }"#, | 1223 | }"#, |
1311 | ); | 1224 | ).assert_expand_items(r#"arbitrary ! ( [ A : Arbitrary ] |
1312 | |||
1313 | assert_expansion(MacroKind::Items, &rules, r#"arbitrary ! ( [ A : Arbitrary ] | ||
1314 | Vec < A > , | 1225 | Vec < A > , |
1315 | VecStrategy < A :: Strategy > , | 1226 | VecStrategy < A :: Strategy > , |
1316 | RangedParams1 < A :: Parameters > ; | 1227 | RangedParams1 < A :: Parameters > ; |
1317 | args => { let product_unpack ! [ range , a ] = args ; vec ( any_with :: < A > ( a ) , range ) } | 1228 | args => { let product_unpack ! [ range , a ] = args ; vec ( any_with :: < A > ( a ) , range ) } |
1318 | ) ;"#, | 1229 | ) ;"#, |
1319 | "impl <A : Arbitrary > $crate :: arbitrary :: Arbitrary for Vec < A > {type Parameters = RangedParams1 < A :: Parameters > ; type Strategy = VecStrategy < A :: Strategy > ; fn arbitrary_with (args : Self :: Parameters) -> Self :: Strategy {{let product_unpack ! [range , a] = args ; vec (any_with :: < A > (a) , range)}}}"); | 1230 | "impl <A : Arbitrary > $crate :: arbitrary :: Arbitrary for Vec < A > {type Parameters = RangedParams1 < A :: Parameters > ; type Strategy = VecStrategy < A :: Strategy > ; fn arbitrary_with (args : Self :: Parameters) -> Self :: Strategy {{let product_unpack ! [range , a] = args ; vec (any_with :: < A > (a) , range)}}}" |
1231 | ); | ||
1320 | } | 1232 | } |
1321 | 1233 | ||
1322 | #[test] | 1234 | #[test] |
1323 | fn test_old_ridl() { | 1235 | fn test_old_ridl() { |
1324 | // This is from winapi 2.8, which do not have a link from github | 1236 | // This is from winapi 2.8, which do not have a link from github |
1325 | // | 1237 | // |
1326 | let rules = create_rules( | 1238 | let expanded = parse_macro( |
1327 | r#" | 1239 | r#" |
1328 | #[macro_export] | 1240 | #[macro_export] |
1329 | macro_rules! RIDL { | 1241 | macro_rules! RIDL { |
@@ -1339,21 +1251,17 @@ macro_rules! RIDL { | |||
1339 | } | 1251 | } |
1340 | }; | 1252 | }; |
1341 | }"#, | 1253 | }"#, |
1342 | ); | 1254 | ).expand_tt(r#" |
1255 | RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) { | ||
1256 | fn GetDataSize(&mut self) -> UINT | ||
1257 | }}"#); | ||
1343 | 1258 | ||
1344 | let expanded = expand( | ||
1345 | &rules, | ||
1346 | r#" | ||
1347 | RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) { | ||
1348 | fn GetDataSize(&mut self) -> UINT | ||
1349 | }}"#, | ||
1350 | ); | ||
1351 | assert_eq!(expanded.to_string(), "impl ID3D11Asynchronous {pub unsafe fn GetDataSize (& mut self) -> UINT {((* self . lpVtbl) .GetDataSize) (self)}}"); | 1259 | assert_eq!(expanded.to_string(), "impl ID3D11Asynchronous {pub unsafe fn GetDataSize (& mut self) -> UINT {((* self . lpVtbl) .GetDataSize) (self)}}"); |
1352 | } | 1260 | } |
1353 | 1261 | ||
1354 | #[test] | 1262 | #[test] |
1355 | fn test_quick_error() { | 1263 | fn test_quick_error() { |
1356 | let rules = create_rules( | 1264 | let expanded = parse_macro( |
1357 | r#" | 1265 | r#" |
1358 | macro_rules! quick_error { | 1266 | macro_rules! quick_error { |
1359 | 1267 | ||
@@ -1376,10 +1284,8 @@ macro_rules! quick_error { | |||
1376 | 1284 | ||
1377 | } | 1285 | } |
1378 | "#, | 1286 | "#, |
1379 | ); | 1287 | ) |
1380 | 1288 | .expand_tt( | |
1381 | let expanded = expand( | ||
1382 | &rules, | ||
1383 | r#" | 1289 | r#" |
1384 | quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [ | 1290 | quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [ |
1385 | => One : UNIT [] {} | 1291 | => One : UNIT [] {} |
@@ -1393,7 +1299,7 @@ quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [ | |||
1393 | 1299 | ||
1394 | #[test] | 1300 | #[test] |
1395 | fn test_empty_repeat_vars_in_empty_repeat_vars() { | 1301 | fn test_empty_repeat_vars_in_empty_repeat_vars() { |
1396 | let rules = create_rules( | 1302 | parse_macro( |
1397 | r#" | 1303 | r#" |
1398 | macro_rules! delegate_impl { | 1304 | macro_rules! delegate_impl { |
1399 | ([$self_type:ident, $self_wrap:ty, $self_map:ident] | 1305 | ([$self_type:ident, $self_wrap:ty, $self_map:ident] |
@@ -1440,11 +1346,7 @@ macro_rules! delegate_impl { | |||
1440 | } | 1346 | } |
1441 | } | 1347 | } |
1442 | "#, | 1348 | "#, |
1443 | ); | 1349 | ).assert_expand_items( |
1444 | |||
1445 | assert_expansion( | ||
1446 | MacroKind::Items, | ||
1447 | &rules, | ||
1448 | r#"delegate_impl ! {[G , & 'a mut G , deref] pub trait Data : GraphBase {@ section type type NodeWeight ;}}"#, | 1350 | r#"delegate_impl ! {[G , & 'a mut G , deref] pub trait Data : GraphBase {@ section type type NodeWeight ;}}"#, |
1449 | "impl <> Data for & \'a mut G where G : Data {}", | 1351 | "impl <> Data for & \'a mut G where G : Data {}", |
1450 | ); | 1352 | ); |
@@ -1452,7 +1354,7 @@ macro_rules! delegate_impl { | |||
1452 | 1354 | ||
1453 | #[test] | 1355 | #[test] |
1454 | fn expr_interpolation() { | 1356 | fn expr_interpolation() { |
1455 | let rules = create_rules( | 1357 | let expanded = parse_macro( |
1456 | r#" | 1358 | r#" |
1457 | macro_rules! id { | 1359 | macro_rules! id { |
1458 | ($expr:expr) => { | 1360 | ($expr:expr) => { |
@@ -1460,118 +1362,101 @@ fn expr_interpolation() { | |||
1460 | } | 1362 | } |
1461 | } | 1363 | } |
1462 | "#, | 1364 | "#, |
1463 | ); | 1365 | ) |
1366 | .expand_expr("id!(x + foo);"); | ||
1464 | 1367 | ||
1465 | let expanded = expand(&rules, "id!(x + foo);"); | ||
1466 | let expanded = | ||
1467 | token_tree_to_syntax_node(&expanded, FragmentKind::Expr).unwrap().0.syntax_node(); | ||
1468 | assert_eq!(expanded.to_string(), "map(x+foo)"); | 1368 | assert_eq!(expanded.to_string(), "map(x+foo)"); |
1469 | } | 1369 | } |
1470 | 1370 | ||
1471 | pub(crate) fn create_rules(macro_definition: &str) -> MacroRules { | 1371 | pub(crate) struct MacroFixture { |
1472 | let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); | 1372 | rules: MacroRules, |
1473 | let macro_definition = | ||
1474 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | ||
1475 | |||
1476 | let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()).unwrap(); | ||
1477 | crate::MacroRules::parse(&definition_tt).unwrap() | ||
1478 | } | 1373 | } |
1479 | 1374 | ||
1480 | pub(crate) fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree { | 1375 | impl MacroFixture { |
1481 | let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); | 1376 | pub(crate) fn expand_tt(&self, invocation: &str) -> tt::Subtree { |
1482 | let macro_invocation = | 1377 | let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); |
1483 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | 1378 | let macro_invocation = |
1484 | 1379 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | |
1485 | let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); | ||
1486 | 1380 | ||
1487 | rules.expand(&invocation_tt).unwrap() | 1381 | let (invocation_tt, _) = |
1488 | } | 1382 | ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); |
1489 | 1383 | ||
1490 | pub(crate) fn expand_and_map( | 1384 | self.rules.expand(&invocation_tt).unwrap() |
1491 | rules: &MacroRules, | 1385 | } |
1492 | invocation: &str, | ||
1493 | ) -> (tt::Subtree, (TokenMap, String)) { | ||
1494 | let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); | ||
1495 | let macro_invocation = | ||
1496 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | ||
1497 | 1386 | ||
1498 | let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); | 1387 | fn expand_items(&self, invocation: &str) -> SyntaxNode { |
1499 | let expanded = rules.expand(&invocation_tt).unwrap(); | 1388 | let expanded = self.expand_tt(invocation); |
1389 | token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node() | ||
1390 | } | ||
1500 | 1391 | ||
1501 | let (node, expanded_token_tree) = | 1392 | fn expand_statements(&self, invocation: &str) -> SyntaxNode { |
1502 | token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap(); | 1393 | let expanded = self.expand_tt(invocation); |
1394 | token_tree_to_syntax_node(&expanded, FragmentKind::Statements).unwrap().0.syntax_node() | ||
1395 | } | ||
1503 | 1396 | ||
1504 | (expanded, (expanded_token_tree, node.syntax_node().to_string())) | 1397 | fn expand_expr(&self, invocation: &str) -> SyntaxNode { |
1505 | } | 1398 | let expanded = self.expand_tt(invocation); |
1399 | token_tree_to_syntax_node(&expanded, FragmentKind::Expr).unwrap().0.syntax_node() | ||
1400 | } | ||
1506 | 1401 | ||
1507 | pub(crate) enum MacroKind { | 1402 | fn assert_expand_tt(&self, invocation: &str, expected: &str) { |
1508 | Items, | 1403 | let expansion = self.expand_tt(invocation); |
1509 | Stmts, | 1404 | assert_eq!(expansion.to_string(), expected); |
1510 | } | 1405 | } |
1511 | 1406 | ||
1512 | pub(crate) fn assert_expansion( | 1407 | fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture { |
1513 | kind: MacroKind, | 1408 | self.assert_expansion(FragmentKind::Items, invocation, expected); |
1514 | rules: &MacroRules, | 1409 | self |
1515 | invocation: &str, | 1410 | } |
1516 | expected: &str, | ||
1517 | ) -> tt::Subtree { | ||
1518 | let expanded = expand(rules, invocation); | ||
1519 | assert_eq!(expanded.to_string(), expected); | ||
1520 | 1411 | ||
1521 | let expected = expected.replace("$crate", "C_C__C"); | 1412 | fn assert_expand_statements(&self, invocation: &str, expected: &str) -> &MacroFixture { |
1413 | self.assert_expansion(FragmentKind::Statements, invocation, expected); | ||
1414 | self | ||
1415 | } | ||
1522 | 1416 | ||
1523 | // wrap the given text to a macro call | 1417 | fn assert_expansion(&self, kind: FragmentKind, invocation: &str, expected: &str) { |
1524 | let expected = { | 1418 | let expanded = self.expand_tt(invocation); |
1525 | let wrapped = format!("wrap_macro!( {} )", expected); | 1419 | assert_eq!(expanded.to_string(), expected); |
1526 | let wrapped = ast::SourceFile::parse(&wrapped); | 1420 | |
1527 | let wrapped = wrapped.tree().syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 1421 | let expected = expected.replace("$crate", "C_C__C"); |
1528 | let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0; | 1422 | |
1529 | wrapped.delimiter = None; | 1423 | // wrap the given text to a macro call |
1530 | wrapped | 1424 | let expected = { |
1531 | }; | 1425 | let wrapped = format!("wrap_macro!( {} )", expected); |
1532 | let (expanded_tree, expected_tree) = match kind { | 1426 | let wrapped = ast::SourceFile::parse(&wrapped); |
1533 | MacroKind::Items => { | 1427 | let wrapped = |
1534 | let expanded_tree = | 1428 | wrapped.tree().syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
1535 | token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node(); | 1429 | let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0; |
1536 | let expected_tree = | 1430 | wrapped.delimiter = None; |
1537 | token_tree_to_syntax_node(&expected, FragmentKind::Items).unwrap().0.syntax_node(); | 1431 | wrapped |
1538 | 1432 | }; | |
1539 | ( | ||
1540 | debug_dump_ignore_spaces(&expanded_tree).trim().to_string(), | ||
1541 | debug_dump_ignore_spaces(&expected_tree).trim().to_string(), | ||
1542 | ) | ||
1543 | } | ||
1544 | 1433 | ||
1545 | MacroKind::Stmts => { | 1434 | let expanded_tree = token_tree_to_syntax_node(&expanded, kind).unwrap().0.syntax_node(); |
1546 | let expanded_tree = token_tree_to_syntax_node(&expanded, FragmentKind::Statements) | 1435 | let expanded_tree = debug_dump_ignore_spaces(&expanded_tree).trim().to_string(); |
1547 | .unwrap() | ||
1548 | .0 | ||
1549 | .syntax_node(); | ||
1550 | let expected_tree = token_tree_to_syntax_node(&expected, FragmentKind::Statements) | ||
1551 | .unwrap() | ||
1552 | .0 | ||
1553 | .syntax_node(); | ||
1554 | |||
1555 | ( | ||
1556 | debug_dump_ignore_spaces(&expanded_tree).trim().to_string(), | ||
1557 | debug_dump_ignore_spaces(&expected_tree).trim().to_string(), | ||
1558 | ) | ||
1559 | } | ||
1560 | }; | ||
1561 | 1436 | ||
1562 | let expected_tree = expected_tree.replace("C_C__C", "$crate"); | 1437 | let expected_tree = token_tree_to_syntax_node(&expected, kind).unwrap().0.syntax_node(); |
1563 | assert_eq!( | 1438 | let expected_tree = debug_dump_ignore_spaces(&expected_tree).trim().to_string(); |
1564 | expanded_tree, expected_tree, | ||
1565 | "\nleft:\n{}\nright:\n{}", | ||
1566 | expanded_tree, expected_tree, | ||
1567 | ); | ||
1568 | 1439 | ||
1569 | expanded | 1440 | let expected_tree = expected_tree.replace("C_C__C", "$crate"); |
1441 | assert_eq!( | ||
1442 | expanded_tree, expected_tree, | ||
1443 | "\nleft:\n{}\nright:\n{}", | ||
1444 | expanded_tree, expected_tree, | ||
1445 | ); | ||
1446 | } | ||
1570 | } | 1447 | } |
1571 | 1448 | ||
1572 | pub fn debug_dump_ignore_spaces(node: &ra_syntax::SyntaxNode) -> String { | 1449 | pub(crate) fn parse_macro(macro_definition: &str) -> MacroFixture { |
1573 | use std::fmt::Write; | 1450 | let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); |
1451 | let macro_definition = | ||
1452 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | ||
1453 | |||
1454 | let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()).unwrap(); | ||
1455 | let rules = MacroRules::parse(&definition_tt).unwrap(); | ||
1456 | MacroFixture { rules } | ||
1457 | } | ||
1574 | 1458 | ||
1459 | fn debug_dump_ignore_spaces(node: &ra_syntax::SyntaxNode) -> String { | ||
1575 | let mut level = 0; | 1460 | let mut level = 0; |
1576 | let mut buf = String::new(); | 1461 | let mut buf = String::new(); |
1577 | macro_rules! indent { | 1462 | macro_rules! indent { |
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs index 45241e566..65134277e 100644 --- a/crates/ra_parser/src/lib.rs +++ b/crates/ra_parser/src/lib.rs | |||
@@ -83,6 +83,7 @@ pub fn parse(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | |||
83 | parse_from_tokens(token_source, tree_sink, grammar::root); | 83 | parse_from_tokens(token_source, tree_sink, grammar::root); |
84 | } | 84 | } |
85 | 85 | ||
86 | #[derive(Clone, Copy)] | ||
86 | pub enum FragmentKind { | 87 | pub enum FragmentKind { |
87 | Path, | 88 | Path, |
88 | Expr, | 89 | Expr, |