aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-12-19 15:27:45 +0000
committerGitHub <[email protected]>2019-12-19 15:27:45 +0000
commit1e32412e28d6668af5c6fe85b4fc921fb1de9a98 (patch)
treeb82af260fc89c4de8a9de300bc9a61e272a1329f
parente17dcc45a679c025e79639bd2d22c3b0f20953f9 (diff)
parent6edc54a1e6a48f6fe3191c549befe91674342d9a (diff)
Merge #2596
2596: Refactor macro tests r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs14
-rw-r--r--crates/ra_mbe/src/tests.rs665
-rw-r--r--crates/ra_parser/src/lib.rs1
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)]
477mod tests { 477mod 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 @@
1use std::fmt::Write;
2
1use ra_parser::FragmentKind; 3use ra_parser::FragmentKind;
2use ra_syntax::{ast, AstNode, NodeOrToken, WalkEvent}; 4use ra_syntax::{ast, AstNode, NodeOrToken, SyntaxKind::IDENT, SyntaxNode, WalkEvent, T};
3use test_utils::assert_eq_text; 5use test_utils::assert_eq_text;
4 6
5use super::*; 7use super::*;
@@ -61,13 +63,14 @@ mod rule_parsing {
61 63
62#[test] 64#[test]
63fn test_token_id_shift() { 65fn test_token_id_shift() {
64 let macro_definition = r#" 66 let expansion = parse_macro(
67 r#"
65macro_rules! foobar { 68macro_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]
92fn test_token_map() { 95fn 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#"
97macro_rules! foobar { 98macro_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]
118fn test_convert_tt() { 122fn test_convert_tt() {
119 let macro_definition = r#" 123 parse_macro(r#"
120macro_rules! impl_froms { 124macro_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);",
134impl_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]
147fn test_expr_order() { 144fn 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]
191fn test_fail_match_pattern_by_first_token() { 187fn 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]
214fn test_fail_match_pattern_by_last_token() { 209fn 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]
237fn test_fail_match_pattern_by_word_token() { 231fn 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]
260fn test_match_group_pattern_by_separator_token() { 253fn 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]
284fn test_match_group_pattern_with_multiple_defs() { 276fn 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]
304fn test_match_group_pattern_with_multiple_statement() { 290fn 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]
319fn test_match_group_pattern_with_multiple_statement_without_semi() { 304fn 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]
334fn test_match_group_empty_fixed_token() { 318fn 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]
349fn test_match_group_in_subtree() { 332fn 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]
363fn test_match_group_with_multichar_sep() { 345fn 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]
380fn test_match_group_zero_match() { 356fn 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]
392fn test_match_group_in_group() { 367fn 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]
404fn test_expand_to_item_list() { 378fn 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]
500fn test_two_idents() { 473fn 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]
519fn test_tt_to_stmts() { 487fn 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]
573fn test_match_literal() { 538fn 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]
590fn test_path() { 555fn 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]
610fn test_two_paths() { 573fn 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]
629fn test_path_with_path() { 587fn 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]
643fn test_expr() { 601fn 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]
663fn test_last_expr() { 618fn 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]
688fn test_ty() { 641fn 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]
707fn test_ty_with_complex_type() { 655fn 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]
736fn test_pat_() { 678fn 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]
748fn test_stmt() { 690fn 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]
763fn test_single_item() { 705fn 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]
777fn test_all_items() { 719fn 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]
812fn test_block() { 752fn 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]
824fn test_meta() { 764fn 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]
844fn test_meta_doc_comments() { 782fn 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]
869fn test_tt_block() { 805fn 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]
881fn test_tt_group() { 817fn 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]
892fn test_lifetime() { 828fn 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]
904fn test_literal() { 840fn 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]
916fn test_vis() { 852fn 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]
931fn test_inner_macro_rules() { 866fn test_inner_macro_rules() {
932 let rules = create_rules( 867 parse_macro(
933 r#" 868 r#"
934macro_rules! foo { 869macro_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]
959fn test_vec() { 892fn 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() {
1055fn test_winapi_struct() { 986fn 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#"
1060macro_rules! STRUCT { 991macro_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]
1089fn test_int_base() { 1022fn test_int_base() {
1090 let rules = create_rules( 1023 parse_macro(
1091 r#" 1024 r#"
1092macro_rules! int_base { 1025macro_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]
1111fn test_generate_pattern_iterators() { 1042fn 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#"
1115macro_rules! generate_pattern_iterators { 1046macro_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]
1135fn test_impl_fn_for_zst() { 1062fn 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#"
1139macro_rules! impl_fn_for_zst { 1066macro_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#"
1181impl_fn_for_zst ! { 1106impl_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]
1201fn test_impl_nonzero_fmt() { 1127fn 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]
1222fn test_cfg_if_items() { 1144fn 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]
1244fn test_cfg_if_main() { 1162fn 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#"
1270cfg_if ! { 1186cfg_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#"
1287cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , target_os = "illumos" ) ) ) ) ) ) , } 1200cfg_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]
1294fn test_proptest_arbitrary() { 1207fn 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#"
1298macro_rules! arbitrary { 1211macro_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]
1323fn test_old_ridl() { 1235fn 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]
1329macro_rules! RIDL { 1241macro_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#"
1347RIDL!{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]
1355fn test_quick_error() { 1263fn test_quick_error() {
1356 let rules = create_rules( 1264 let expanded = parse_macro(
1357 r#" 1265 r#"
1358macro_rules! quick_error { 1266macro_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#"
1384quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [ 1290quick_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]
1395fn test_empty_repeat_vars_in_empty_repeat_vars() { 1301fn test_empty_repeat_vars_in_empty_repeat_vars() {
1396 let rules = create_rules( 1302 parse_macro(
1397 r#" 1303 r#"
1398macro_rules! delegate_impl { 1304macro_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]
1454fn expr_interpolation() { 1356fn 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
1471pub(crate) fn create_rules(macro_definition: &str) -> MacroRules { 1371pub(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(&macro_definition.token_tree().unwrap()).unwrap();
1477 crate::MacroRules::parse(&definition_tt).unwrap()
1478} 1373}
1479 1374
1480pub(crate) fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree { 1375impl 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(&macro_invocation.token_tree().unwrap()).unwrap();
1486 1380
1487 rules.expand(&invocation_tt).unwrap() 1381 let (invocation_tt, _) =
1488} 1382 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap();
1489 1383
1490pub(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(&macro_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
1507pub(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
1512pub(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
1572pub fn debug_dump_ignore_spaces(node: &ra_syntax::SyntaxNode) -> String { 1449pub(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(&macro_definition.token_tree().unwrap()).unwrap();
1455 let rules = MacroRules::parse(&definition_tt).unwrap();
1456 MacroFixture { rules }
1457}
1574 1458
1459fn 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)]
86pub enum FragmentKind { 87pub enum FragmentKind {
87 Path, 88 Path,
88 Expr, 89 Expr,