]> git.lizzy.rs Git - rust.git/blob - crates/mbe/src/tests.rs
Simplify mbe match error.
[rust.git] / crates / mbe / src / tests.rs
1 use std::fmt::Write;
2
3 use ::parser::FragmentKind;
4 use syntax::{
5     ast, AstNode, NodeOrToken,
6     SyntaxKind::{ERROR, IDENT},
7     SyntaxNode, WalkEvent, T,
8 };
9 use test_utils::{assert_eq_text, mark};
10
11 use super::*;
12
13 mod rule_parsing {
14     use syntax::{ast, AstNode};
15
16     use crate::ast_to_token_tree;
17
18     use super::*;
19
20     #[test]
21     fn test_valid_arms() {
22         fn check(macro_body: &str) {
23             let m = parse_macro_arm(macro_body);
24             m.unwrap();
25         }
26
27         check("($i:ident) => ()");
28         check("($($i:ident)*) => ($_)");
29         check("($($true:ident)*) => ($true)");
30         check("($($false:ident)*) => ($false)");
31         check("($) => ($)");
32     }
33
34     #[test]
35     fn test_invalid_arms() {
36         fn check(macro_body: &str, err: ParseError) {
37             let m = parse_macro_arm(macro_body);
38             assert_eq!(m, Err(err.into()));
39         }
40         check("invalid", ParseError::Expected("expected subtree".into()));
41
42         check("$i:ident => ()", ParseError::Expected("expected subtree".into()));
43         check("($i:ident) ()", ParseError::Expected("expected `=`".into()));
44         check("($($i:ident)_) => ()", ParseError::InvalidRepeat);
45
46         check("($i) => ($i)", ParseError::UnexpectedToken("bad fragment specifier 1".into()));
47         check("($i:) => ($i)", ParseError::UnexpectedToken("bad fragment specifier 1".into()));
48     }
49
50     fn parse_macro_arm(arm_definition: &str) -> Result<crate::MacroRules, ParseError> {
51         let macro_definition = format!(" macro_rules! m {{ {} }} ", arm_definition);
52         let source_file = ast::SourceFile::parse(&macro_definition).ok().unwrap();
53         let macro_definition =
54             source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
55
56         let (definition_tt, _) =
57             ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
58         crate::MacroRules::parse(&definition_tt)
59     }
60 }
61
62 // Good first issue (although a slightly challenging one):
63 //
64 // * Pick a random test from here
65 //   https://github.com/intellij-rust/intellij-rust/blob/c4e9feee4ad46e7953b1948c112533360b6087bb/src/test/kotlin/org/rust/lang/core/macros/RsMacroExpansionTest.kt
66 // * Port the test to rust and add it to this module
67 // * Make it pass :-)
68
69 #[test]
70 fn test_token_id_shift() {
71     let expansion = parse_macro(
72         r#"
73 macro_rules! foobar {
74     ($e:ident) => { foo bar $e }
75 }
76 "#,
77     )
78     .expand_tt("foobar!(baz);");
79
80     fn get_id(t: &tt::TokenTree) -> Option<u32> {
81         if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t {
82             return Some(ident.id.0);
83         }
84         None
85     }
86
87     assert_eq!(expansion.token_trees.len(), 3);
88     // {($e:ident) => { foo bar $e }}
89     // 012345      67 8 9   T   12
90     assert_eq!(get_id(&expansion.token_trees[0]), Some(9));
91     assert_eq!(get_id(&expansion.token_trees[1]), Some(10));
92
93     // The input args of macro call include parentheses:
94     // (baz)
95     // So baz should be 12+1+1
96     assert_eq!(get_id(&expansion.token_trees[2]), Some(14));
97 }
98
99 #[test]
100 fn test_token_map() {
101     let expanded = parse_macro(
102         r#"
103 macro_rules! foobar {
104     ($e:ident) => { fn $e() {} }
105 }
106 "#,
107     )
108     .expand_tt("foobar!(baz);");
109
110     let (node, token_map) = token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap();
111     let content = node.syntax_node().to_string();
112
113     let get_text = |id, kind| -> String {
114         content[token_map.range_by_token(id).unwrap().by_kind(kind).unwrap()].to_string()
115     };
116
117     assert_eq!(expanded.token_trees.len(), 4);
118     // {($e:ident) => { fn $e() {} }}
119     // 012345      67 8 9  T12  3
120
121     assert_eq!(get_text(tt::TokenId(9), IDENT), "fn");
122     assert_eq!(get_text(tt::TokenId(12), T!['(']), "(");
123     assert_eq!(get_text(tt::TokenId(13), T!['{']), "{");
124 }
125
126 #[test]
127 fn test_convert_tt() {
128     parse_macro(r#"
129 macro_rules! impl_froms {
130     ($e:ident: $($v:ident),*) => {
131         $(
132             impl From<$v> for $e {
133                 fn from(it: $v) -> $e {
134                     $e::$v(it)
135                 }
136             }
137         )*
138     }
139 }
140 "#)
141         .assert_expand_tt(
142             "impl_froms!(TokenTree: Leaf, Subtree);",
143             "impl From <Leaf > for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree ::Leaf (it)}} \
144              impl From <Subtree > for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree ::Subtree (it)}}"
145         );
146 }
147
148 #[test]
149 fn test_convert_tt2() {
150     parse_macro(
151         r#"
152 macro_rules! impl_froms {
153     ($e:ident: $($v:ident),*) => {
154         $(
155             impl From<$v> for $e {
156                 fn from(it: $v) -> $e {
157                     $e::$v(it)
158                 }
159             }
160         )*
161     }
162 }
163 "#,
164     )
165     .assert_expand(
166         "impl_froms!(TokenTree: Leaf, Subtree);",
167         r#"
168 SUBTREE $
169   IDENT   impl 20
170   IDENT   From 21
171   PUNCH   < [joint] 22
172   IDENT   Leaf 53
173   PUNCH   > [alone] 25
174   IDENT   for 26
175   IDENT   TokenTree 51
176   SUBTREE {} 29
177     IDENT   fn 30
178     IDENT   from 31
179     SUBTREE () 32
180       IDENT   it 33
181       PUNCH   : [alone] 34
182       IDENT   Leaf 53
183     PUNCH   - [joint] 37
184     PUNCH   > [alone] 38
185     IDENT   TokenTree 51
186     SUBTREE {} 41
187       IDENT   TokenTree 51
188       PUNCH   : [joint] 44
189       PUNCH   : [joint] 45
190       IDENT   Leaf 53
191       SUBTREE () 48
192         IDENT   it 49
193   IDENT   impl 20
194   IDENT   From 21
195   PUNCH   < [joint] 22
196   IDENT   Subtree 55
197   PUNCH   > [alone] 25
198   IDENT   for 26
199   IDENT   TokenTree 51
200   SUBTREE {} 29
201     IDENT   fn 30
202     IDENT   from 31
203     SUBTREE () 32
204       IDENT   it 33
205       PUNCH   : [alone] 34
206       IDENT   Subtree 55
207     PUNCH   - [joint] 37
208     PUNCH   > [alone] 38
209     IDENT   TokenTree 51
210     SUBTREE {} 41
211       IDENT   TokenTree 51
212       PUNCH   : [joint] 44
213       PUNCH   : [joint] 45
214       IDENT   Subtree 55
215       SUBTREE () 48
216         IDENT   it 49
217 "#,
218     );
219 }
220
221 #[test]
222 fn test_lifetime_split() {
223     parse_macro(
224         r#"
225 macro_rules! foo {
226     ($($t:tt)*) => { $($t)*}
227 }
228 "#,
229     )
230     .assert_expand(
231         r#"foo!(static bar: &'static str = "hello";);"#,
232         r#"
233 SUBTREE $
234   IDENT   static 17
235   IDENT   bar 18
236   PUNCH   : [alone] 19
237   PUNCH   & [alone] 20
238   PUNCH   ' [joint] 21
239   IDENT   static 22
240   IDENT   str 23
241   PUNCH   = [alone] 24
242   LITERAL "hello" 25
243   PUNCH   ; [joint] 26
244 "#,
245     );
246 }
247
248 #[test]
249 fn test_expr_order() {
250     let expanded = parse_macro(
251         r#"
252         macro_rules! foo {
253             ($ i:expr) => {
254                  fn bar() { $ i * 2; }
255             }
256         }
257 "#,
258     )
259     .expand_items("foo! { 1 + 1}");
260
261     let dump = format!("{:#?}", expanded);
262     assert_eq_text!(
263         r#"MACRO_ITEMS@0..15
264   FN@0..15
265     FN_KW@0..2 "fn"
266     NAME@2..5
267       IDENT@2..5 "bar"
268     PARAM_LIST@5..7
269       L_PAREN@5..6 "("
270       R_PAREN@6..7 ")"
271     BLOCK_EXPR@7..15
272       L_CURLY@7..8 "{"
273       EXPR_STMT@8..14
274         BIN_EXPR@8..13
275           BIN_EXPR@8..11
276             LITERAL@8..9
277               INT_NUMBER@8..9 "1"
278             PLUS@9..10 "+"
279             LITERAL@10..11
280               INT_NUMBER@10..11 "1"
281           STAR@11..12 "*"
282           LITERAL@12..13
283             INT_NUMBER@12..13 "2"
284         SEMICOLON@13..14 ";"
285       R_CURLY@14..15 "}""#,
286         dump.trim()
287     );
288 }
289
290 #[test]
291 fn test_fail_match_pattern_by_first_token() {
292     parse_macro(
293         r#"
294         macro_rules! foo {
295             ($ i:ident) => (
296                 mod $ i {}
297             );
298             (= $ i:ident) => (
299                 fn $ i() {}
300             );
301             (+ $ i:ident) => (
302                 struct $ i;
303             )
304         }
305 "#,
306     )
307     .assert_expand_items("foo! { foo }", "mod foo {}")
308     .assert_expand_items("foo! { = bar }", "fn bar () {}")
309     .assert_expand_items("foo! { + Baz }", "struct Baz ;");
310 }
311
312 #[test]
313 fn test_fail_match_pattern_by_last_token() {
314     parse_macro(
315         r#"
316         macro_rules! foo {
317             ($ i:ident) => (
318                 mod $ i {}
319             );
320             ($ i:ident =) => (
321                 fn $ i() {}
322             );
323             ($ i:ident +) => (
324                 struct $ i;
325             )
326         }
327 "#,
328     )
329     .assert_expand_items("foo! { foo }", "mod foo {}")
330     .assert_expand_items("foo! { bar = }", "fn bar () {}")
331     .assert_expand_items("foo! { Baz + }", "struct Baz ;");
332 }
333
334 #[test]
335 fn test_fail_match_pattern_by_word_token() {
336     parse_macro(
337         r#"
338         macro_rules! foo {
339             ($ i:ident) => (
340                 mod $ i {}
341             );
342             (spam $ i:ident) => (
343                 fn $ i() {}
344             );
345             (eggs $ i:ident) => (
346                 struct $ i;
347             )
348         }
349 "#,
350     )
351     .assert_expand_items("foo! { foo }", "mod foo {}")
352     .assert_expand_items("foo! { spam bar }", "fn bar () {}")
353     .assert_expand_items("foo! { eggs Baz }", "struct Baz ;");
354 }
355
356 #[test]
357 fn test_match_group_pattern_by_separator_token() {
358     parse_macro(
359         r#"
360         macro_rules! foo {
361             ($ ($ i:ident),*) => ($ (
362                 mod $ i {}
363             )*);
364             ($ ($ i:ident)#*) => ($ (
365                 fn $ i() {}
366             )*);
367             ($ i:ident ,# $ j:ident) => (
368                 struct $ i;
369                 struct $ j;
370             )
371         }
372 "#,
373     )
374     .assert_expand_items("foo! { foo, bar }", "mod foo {} mod bar {}")
375     .assert_expand_items("foo! { foo# bar }", "fn foo () {} fn bar () {}")
376     .assert_expand_items("foo! { Foo,# Bar }", "struct Foo ; struct Bar ;");
377 }
378
379 #[test]
380 fn test_match_group_pattern_with_multiple_defs() {
381     parse_macro(
382         r#"
383         macro_rules! foo {
384             ($ ($ i:ident),*) => ( struct Bar { $ (
385                 fn $ i {}
386             )*} );
387         }
388 "#,
389     )
390     .assert_expand_items("foo! { foo, bar }", "struct Bar {fn foo {} fn bar {}}");
391 }
392
393 #[test]
394 fn test_match_group_pattern_with_multiple_statement() {
395     parse_macro(
396         r#"
397         macro_rules! foo {
398             ($ ($ i:ident),*) => ( fn baz { $ (
399                 $ i ();
400             )*} );
401         }
402 "#,
403     )
404     .assert_expand_items("foo! { foo, bar }", "fn baz {foo () ; bar () ;}");
405 }
406
407 #[test]
408 fn test_match_group_pattern_with_multiple_statement_without_semi() {
409     parse_macro(
410         r#"
411         macro_rules! foo {
412             ($ ($ i:ident),*) => ( fn baz { $ (
413                 $i()
414             );*} );
415         }
416 "#,
417     )
418     .assert_expand_items("foo! { foo, bar }", "fn baz {foo () ;bar ()}");
419 }
420
421 #[test]
422 fn test_match_group_empty_fixed_token() {
423     parse_macro(
424         r#"
425         macro_rules! foo {
426             ($ ($ i:ident)* #abc) => ( fn baz { $ (
427                 $ i ();
428             )*} );
429         }
430 "#,
431     )
432     .assert_expand_items("foo! {#abc}", "fn baz {}");
433 }
434
435 #[test]
436 fn test_match_group_in_subtree() {
437     parse_macro(
438         r#"
439         macro_rules! foo {
440             (fn $name:ident {$($i:ident)*} ) => ( fn $name() { $ (
441                 $ i ();
442             )*} );
443         }"#,
444     )
445     .assert_expand_items("foo! {fn baz {a b} }", "fn baz () {a () ; b () ;}");
446 }
447
448 #[test]
449 fn test_match_group_with_multichar_sep() {
450     parse_macro(
451         r#"
452         macro_rules! foo {
453             (fn $name:ident {$($i:literal)*} ) => ( fn $name() -> bool { $($i)&&*} );
454         }"#,
455     )
456     .assert_expand_items("foo! (fn baz {true true} );", "fn baz () -> bool {true &&true}");
457 }
458
459 #[test]
460 fn test_match_group_zero_match() {
461     parse_macro(
462         r#"
463         macro_rules! foo {
464             ( $($i:ident)* ) => ();
465         }"#,
466     )
467     .assert_expand_items("foo! ();", "");
468 }
469
470 #[test]
471 fn test_match_group_in_group() {
472     parse_macro(
473         r#"
474         macro_rules! foo {
475             { $( ( $($i:ident)* ) )* } => ( $( ( $($i)* ) )* );
476         }"#,
477     )
478     .assert_expand_items("foo! ( (a b) );", "(a b)");
479 }
480
481 #[test]
482 fn test_expand_to_item_list() {
483     let tree = parse_macro(
484         "
485             macro_rules! structs {
486                 ($($i:ident),*) => {
487                     $(struct $i { field: u32 } )*
488                 }
489             }
490             ",
491     )
492     .expand_items("structs!(Foo, Bar);");
493     assert_eq!(
494         format!("{:#?}", tree).trim(),
495         r#"
496 MACRO_ITEMS@0..40
497   STRUCT@0..20
498     STRUCT_KW@0..6 "struct"
499     NAME@6..9
500       IDENT@6..9 "Foo"
501     RECORD_FIELD_LIST@9..20
502       L_CURLY@9..10 "{"
503       RECORD_FIELD@10..19
504         NAME@10..15
505           IDENT@10..15 "field"
506         COLON@15..16 ":"
507         PATH_TYPE@16..19
508           PATH@16..19
509             PATH_SEGMENT@16..19
510               NAME_REF@16..19
511                 IDENT@16..19 "u32"
512       R_CURLY@19..20 "}"
513   STRUCT@20..40
514     STRUCT_KW@20..26 "struct"
515     NAME@26..29
516       IDENT@26..29 "Bar"
517     RECORD_FIELD_LIST@29..40
518       L_CURLY@29..30 "{"
519       RECORD_FIELD@30..39
520         NAME@30..35
521           IDENT@30..35 "field"
522         COLON@35..36 ":"
523         PATH_TYPE@36..39
524           PATH@36..39
525             PATH_SEGMENT@36..39
526               NAME_REF@36..39
527                 IDENT@36..39 "u32"
528       R_CURLY@39..40 "}""#
529             .trim()
530     );
531 }
532
533 fn to_subtree(tt: &tt::TokenTree) -> &tt::Subtree {
534     if let tt::TokenTree::Subtree(subtree) = tt {
535         return &subtree;
536     }
537     unreachable!("It is not a subtree");
538 }
539 fn to_literal(tt: &tt::TokenTree) -> &tt::Literal {
540     if let tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) = tt {
541         return lit;
542     }
543     unreachable!("It is not a literal");
544 }
545
546 fn to_punct(tt: &tt::TokenTree) -> &tt::Punct {
547     if let tt::TokenTree::Leaf(tt::Leaf::Punct(lit)) = tt {
548         return lit;
549     }
550     unreachable!("It is not a Punct");
551 }
552
553 #[test]
554 fn test_expand_literals_to_token_tree() {
555     let expansion = parse_macro(
556         r#"
557             macro_rules! literals {
558                 ($i:ident) => {
559                     {
560                         let a = 'c';
561                         let c = 1000;
562                         let f = 12E+99_f64;
563                         let s = "rust1";
564                     }
565                 }
566             }
567             "#,
568     )
569     .expand_tt("literals!(foo);");
570     let stm_tokens = &to_subtree(&expansion.token_trees[0]).token_trees;
571
572     // [let] [a] [=] ['c'] [;]
573     assert_eq!(to_literal(&stm_tokens[3]).text, "'c'");
574     // [let] [c] [=] [1000] [;]
575     assert_eq!(to_literal(&stm_tokens[5 + 3]).text, "1000");
576     // [let] [f] [=] [12E+99_f64] [;]
577     assert_eq!(to_literal(&stm_tokens[10 + 3]).text, "12E+99_f64");
578     // [let] [s] [=] ["rust1"] [;]
579     assert_eq!(to_literal(&stm_tokens[15 + 3]).text, "\"rust1\"");
580 }
581
582 #[test]
583 fn test_attr_to_token_tree() {
584     let expansion = parse_to_token_tree_by_syntax(
585         r#"
586             #[derive(Copy)]
587             struct Foo;
588             "#,
589     );
590
591     assert_eq!(to_punct(&expansion.token_trees[0]).char, '#');
592     assert_eq!(
593         to_subtree(&expansion.token_trees[1]).delimiter_kind(),
594         Some(tt::DelimiterKind::Bracket)
595     );
596 }
597
598 #[test]
599 fn test_two_idents() {
600     parse_macro(
601         r#"
602         macro_rules! foo {
603             ($ i:ident, $ j:ident) => {
604                 fn foo() { let a = $ i; let b = $j; }
605             }
606         }
607 "#,
608     )
609     .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}");
610 }
611
612 #[test]
613 fn test_tt_to_stmts() {
614     let stmts = parse_macro(
615         r#"
616         macro_rules! foo {
617             () => {
618                  let a = 0;
619                  a = 10 + 1;
620                  a
621             }
622         }
623 "#,
624     )
625     .expand_statements("foo!{}");
626
627     assert_eq!(
628         format!("{:#?}", stmts).trim(),
629         r#"MACRO_STMTS@0..15
630   LET_STMT@0..7
631     LET_KW@0..3 "let"
632     IDENT_PAT@3..4
633       NAME@3..4
634         IDENT@3..4 "a"
635     EQ@4..5 "="
636     LITERAL@5..6
637       INT_NUMBER@5..6 "0"
638     SEMICOLON@6..7 ";"
639   EXPR_STMT@7..14
640     BIN_EXPR@7..13
641       PATH_EXPR@7..8
642         PATH@7..8
643           PATH_SEGMENT@7..8
644             NAME_REF@7..8
645               IDENT@7..8 "a"
646       EQ@8..9 "="
647       BIN_EXPR@9..13
648         LITERAL@9..11
649           INT_NUMBER@9..11 "10"
650         PLUS@11..12 "+"
651         LITERAL@12..13
652           INT_NUMBER@12..13 "1"
653     SEMICOLON@13..14 ";"
654   EXPR_STMT@14..15
655     PATH_EXPR@14..15
656       PATH@14..15
657         PATH_SEGMENT@14..15
658           NAME_REF@14..15
659             IDENT@14..15 "a""#,
660     );
661 }
662
663 #[test]
664 fn test_match_literal() {
665     parse_macro(
666         r#"
667     macro_rules! foo {
668         ('(') => {
669             fn foo() {}
670         }
671     }
672 "#,
673     )
674     .assert_expand_items("foo! ['('];", "fn foo () {}");
675 }
676
677 #[test]
678 fn test_parse_macro_def_simple() {
679     mark::check!(parse_macro_def_simple);
680
681     parse_macro2(
682         r#"
683 macro foo($id:ident) {
684     fn $id() {}
685 }
686 "#,
687     )
688     .assert_expand_items("foo!(bar);", "fn bar () {}");
689 }
690
691 #[test]
692 fn test_parse_macro_def_rules() {
693     mark::check!(parse_macro_def_rules);
694
695     parse_macro2(
696         r#"
697 macro foo {
698     ($id:ident) => {
699         fn $id() {}
700     }
701 }
702 "#,
703     )
704     .assert_expand_items("foo!(bar);", "fn bar () {}");
705 }
706
707 // The following tests are port from intellij-rust directly
708 // https://github.com/intellij-rust/intellij-rust/blob/c4e9feee4ad46e7953b1948c112533360b6087bb/src/test/kotlin/org/rust/lang/core/macros/RsMacroExpansionTest.kt
709
710 #[test]
711 fn test_path() {
712     parse_macro(
713         r#"
714         macro_rules! foo {
715             ($ i:path) => {
716                 fn foo() { let a = $ i; }
717             }
718         }
719 "#,
720     )
721     .assert_expand_items("foo! { foo }", "fn foo () {let a = foo ;}")
722     .assert_expand_items(
723         "foo! { bar::<u8>::baz::<u8> }",
724         "fn foo () {let a = bar ::< u8 >:: baz ::< u8 > ;}",
725     );
726 }
727
728 #[test]
729 fn test_two_paths() {
730     parse_macro(
731         r#"
732         macro_rules! foo {
733             ($ i:path, $ j:path) => {
734                 fn foo() { let a = $ i; let b = $j; }
735             }
736         }
737 "#,
738     )
739     .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}");
740 }
741
742 #[test]
743 fn test_path_with_path() {
744     parse_macro(
745         r#"
746         macro_rules! foo {
747             ($ i:path) => {
748                 fn foo() { let a = $ i :: bar; }
749             }
750         }
751 "#,
752     )
753     .assert_expand_items("foo! { foo }", "fn foo () {let a = foo :: bar ;}");
754 }
755
756 #[test]
757 fn test_expr() {
758     parse_macro(
759         r#"
760         macro_rules! foo {
761             ($ i:expr) => {
762                  fn bar() { $ i; }
763             }
764         }
765 "#,
766     )
767     .assert_expand_items(
768         "foo! { 2 + 2 * baz(3).quux() }",
769         "fn bar () {2 + 2 * baz (3) . quux () ;}",
770     );
771 }
772
773 #[test]
774 fn test_last_expr() {
775     parse_macro(
776         r#"
777         macro_rules! vec {
778             ($($item:expr),*) => {
779                 {
780                     let mut v = Vec::new();
781                     $(
782                         v.push($item);
783                     )*
784                     v
785                 }
786             };
787         }
788 "#,
789     )
790     .assert_expand_items(
791         "vec!(1,2,3);",
792         "{let mut v = Vec :: new () ; v . push (1) ; v . push (2) ; v . push (3) ; v}",
793     );
794 }
795
796 #[test]
797 fn test_expr_with_attr() {
798     parse_macro(
799         r#"
800 macro_rules! m {
801     ($a:expr) => {0}
802 }
803 "#,
804     )
805     .assert_expand_items("m!(#[allow(a)]())", "0");
806 }
807
808 #[test]
809 fn test_ty() {
810     parse_macro(
811         r#"
812         macro_rules! foo {
813             ($ i:ty) => (
814                 fn bar() -> $ i { unimplemented!() }
815             )
816         }
817 "#,
818     )
819     .assert_expand_items("foo! { Baz<u8> }", "fn bar () -> Baz < u8 > {unimplemented ! ()}");
820 }
821
822 #[test]
823 fn test_ty_with_complex_type() {
824     parse_macro(
825         r#"
826         macro_rules! foo {
827             ($ i:ty) => (
828                 fn bar() -> $ i { unimplemented!() }
829             )
830         }
831 "#,
832     )
833     // Reference lifetime struct with generic type
834     .assert_expand_items(
835         "foo! { &'a Baz<u8> }",
836         "fn bar () -> & 'a Baz < u8 > {unimplemented ! ()}",
837     )
838     // extern "Rust" func type
839     .assert_expand_items(
840         r#"foo! { extern "Rust" fn() -> Ret }"#,
841         r#"fn bar () -> extern "Rust" fn () -> Ret {unimplemented ! ()}"#,
842     );
843 }
844
845 #[test]
846 fn test_pat_() {
847     parse_macro(
848         r#"
849         macro_rules! foo {
850             ($ i:pat) => { fn foo() { let $ i; } }
851         }
852 "#,
853     )
854     .assert_expand_items("foo! { (a, b) }", "fn foo () {let (a , b) ;}");
855 }
856
857 #[test]
858 fn test_stmt() {
859     parse_macro(
860         r#"
861         macro_rules! foo {
862             ($ i:stmt) => (
863                 fn bar() { $ i; }
864             )
865         }
866 "#,
867     )
868     .assert_expand_items("foo! { 2 }", "fn bar () {2 ;}")
869     .assert_expand_items("foo! { let a = 0 }", "fn bar () {let a = 0 ;}");
870 }
871
872 #[test]
873 fn test_single_item() {
874     parse_macro(
875         r#"
876         macro_rules! foo {
877             ($ i:item) => (
878                 $ i
879             )
880         }
881 "#,
882     )
883     .assert_expand_items("foo! {mod c {}}", "mod c {}");
884 }
885
886 #[test]
887 fn test_all_items() {
888     parse_macro(
889         r#"
890         macro_rules! foo {
891             ($ ($ i:item)*) => ($ (
892                 $ i
893             )*)
894         }
895 "#,
896     ).
897     assert_expand_items(
898         r#"
899         foo! {
900             extern crate a;
901             mod b;
902             mod c {}
903             use d;
904             const E: i32 = 0;
905             static F: i32 = 0;
906             impl G {}
907             struct H;
908             enum I { Foo }
909             trait J {}
910             fn h() {}
911             extern {}
912             type T = u8;
913         }
914 "#,
915         r#"extern crate a ; mod b ; mod c {} use d ; const E : i32 = 0 ; static F : i32 = 0 ; impl G {} struct H ; enum I {Foo} trait J {} fn h () {} extern {} type T = u8 ;"#,
916     );
917 }
918
919 #[test]
920 fn test_block() {
921     parse_macro(
922         r#"
923         macro_rules! foo {
924             ($ i:block) => { fn foo() $ i }
925         }
926 "#,
927     )
928     .assert_expand_statements("foo! { { 1; } }", "fn foo () {1 ;}");
929 }
930
931 #[test]
932 fn test_meta() {
933     parse_macro(
934         r#"
935         macro_rules! foo {
936             ($ i:meta) => (
937                 #[$ i]
938                 fn bar() {}
939             )
940         }
941 "#,
942     )
943     .assert_expand_items(
944         r#"foo! { cfg(target_os = "windows") }"#,
945         r#"# [cfg (target_os = "windows")] fn bar () {}"#,
946     );
947 }
948
949 #[test]
950 fn test_meta_doc_comments() {
951     parse_macro(
952         r#"
953         macro_rules! foo {
954             ($(#[$ i:meta])+) => (
955                 $(#[$ i])+
956                 fn bar() {}
957             )
958         }
959 "#,
960     ).
961     assert_expand_items(
962         r#"foo! {
963             /// Single Line Doc 1
964             /**
965                 MultiLines Doc
966             */
967         }"#,
968         "# [doc = \" Single Line Doc 1\"] # [doc = \"\\\\n                MultiLines Doc\\\\n            \"] fn bar () {}",
969     );
970 }
971
972 #[test]
973 fn test_tt_block() {
974     parse_macro(
975         r#"
976             macro_rules! foo {
977                 ($ i:tt) => { fn foo() $ i }
978             }
979     "#,
980     )
981     .assert_expand_items(r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#);
982 }
983
984 #[test]
985 fn test_tt_group() {
986     parse_macro(
987         r#"
988             macro_rules! foo {
989                  ($($ i:tt)*) => { $($ i)* }
990             }
991     "#,
992     )
993     .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#);
994 }
995
996 #[test]
997 fn test_tt_composite() {
998     parse_macro(
999         r#"
1000             macro_rules! foo {
1001                  ($i:tt) => { 0 }
1002             }
1003     "#,
1004     )
1005     .assert_expand_items(r#"foo! { => }"#, r#"0"#);
1006 }
1007
1008 #[test]
1009 fn test_tt_composite2() {
1010     let node = parse_macro(
1011         r#"
1012             macro_rules! foo {
1013                 ($($tt:tt)*) => { abs!(=> $($tt)*) }
1014             }
1015     "#,
1016     )
1017     .expand_items(r#"foo!{#}"#);
1018
1019     let res = format!("{:#?}", &node);
1020     assert_eq_text!(
1021         r###"MACRO_ITEMS@0..10
1022   MACRO_CALL@0..10
1023     PATH@0..3
1024       PATH_SEGMENT@0..3
1025         NAME_REF@0..3
1026           IDENT@0..3 "abs"
1027     BANG@3..4 "!"
1028     TOKEN_TREE@4..10
1029       L_PAREN@4..5 "("
1030       EQ@5..6 "="
1031       R_ANGLE@6..7 ">"
1032       WHITESPACE@7..8 " "
1033       POUND@8..9 "#"
1034       R_PAREN@9..10 ")""###,
1035         res.trim()
1036     );
1037 }
1038
1039 #[test]
1040 fn test_tt_with_composite_without_space() {
1041     parse_macro(
1042         r#"
1043         macro_rules! foo {
1044             ($ op:tt, $j:path) => (
1045                 0
1046             )
1047         }
1048 "#,
1049     )
1050     // Test macro input without any spaces
1051     // See https://github.com/rust-analyzer/rust-analyzer/issues/6692
1052     .assert_expand_items("foo!(==,Foo::Bool)", "0");
1053 }
1054
1055 #[test]
1056 fn test_underscore() {
1057     parse_macro(
1058         r#"
1059             macro_rules! foo {
1060                  ($_:tt) => { 0 }
1061             }
1062     "#,
1063     )
1064     .assert_expand_items(r#"foo! { => }"#, r#"0"#);
1065 }
1066
1067 #[test]
1068 fn test_underscore_not_greedily() {
1069     parse_macro(
1070         r#"
1071 macro_rules! q {
1072     ($($a:ident)* _) => {0};
1073 }
1074 "#,
1075     )
1076     // `_` overlaps with `$a:ident` but rustc matches it under the `_` token
1077     .assert_expand_items(r#"q![a b c d _]"#, r#"0"#);
1078
1079     parse_macro(
1080         r#"
1081 macro_rules! q {
1082     ($($a:expr => $b:ident)* _ => $c:expr) => {0};
1083 }
1084 "#,
1085     )
1086     // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`
1087     .assert_expand_items(r#"q![a => b c => d _ => ou]"#, r#"0"#);
1088 }
1089
1090 #[test]
1091 fn test_underscore_as_type() {
1092     parse_macro(
1093         r#"
1094 macro_rules! q {
1095     ($a:ty) => {0};
1096 }
1097 "#,
1098     )
1099     // Underscore is a type
1100     .assert_expand_items(r#"q![_]"#, r#"0"#);
1101 }
1102
1103 #[test]
1104 fn test_vertical_bar_with_pat() {
1105     parse_macro(
1106         r#"
1107             macro_rules! foo {
1108                  (| $pat:pat | ) => { 0 }
1109             }
1110     "#,
1111     )
1112     .assert_expand_items(r#"foo! { | x | }"#, r#"0"#);
1113 }
1114
1115 #[test]
1116 fn test_dollar_crate_lhs_is_not_meta() {
1117     parse_macro(
1118         r#"
1119 macro_rules! foo {
1120     ($crate) => {};
1121     () => {0};
1122 }
1123     "#,
1124     )
1125     .assert_expand_items(r#"foo!{}"#, r#"0"#);
1126 }
1127
1128 #[test]
1129 fn test_lifetime() {
1130     parse_macro(
1131         r#"
1132         macro_rules! foo {
1133               ($ lt:lifetime) => { struct Ref<$ lt>{ s: &$ lt str } }
1134         }
1135 "#,
1136     )
1137     .assert_expand_items(r#"foo!{'a}"#, r#"struct Ref <'a > {s : &'a str}"#);
1138 }
1139
1140 #[test]
1141 fn test_literal() {
1142     parse_macro(
1143         r#"
1144         macro_rules! foo {
1145               ($ type:ty , $ lit:literal) => { const VALUE: $ type = $ lit;};
1146         }
1147 "#,
1148     )
1149     .assert_expand_items(r#"foo!(u8,0);"#, r#"const VALUE : u8 = 0 ;"#);
1150
1151     parse_macro(
1152         r#"
1153         macro_rules! foo {
1154               ($ type:ty , $ lit:literal) => { const VALUE: $ type = $ lit;};
1155         }
1156 "#,
1157     )
1158     .assert_expand_items(r#"foo!(i32,-1);"#, r#"const VALUE : i32 = - 1 ;"#);
1159 }
1160
1161 #[test]
1162 fn test_boolean_is_ident() {
1163     parse_macro(
1164         r#"
1165         macro_rules! foo {
1166               ($lit0:literal, $lit1:literal) => { const VALUE: (bool,bool) = ($lit0,$lit1); };
1167         }
1168 "#,
1169     )
1170     .assert_expand(
1171         r#"foo!(true,false);"#,
1172         r#"
1173 SUBTREE $
1174   IDENT   const 14
1175   IDENT   VALUE 15
1176   PUNCH   : [alone] 16
1177   SUBTREE () 17
1178     IDENT   bool 18
1179     PUNCH   , [alone] 19
1180     IDENT   bool 20
1181   PUNCH   = [alone] 21
1182   SUBTREE () 22
1183     IDENT   true 29
1184     PUNCH   , [joint] 25
1185     IDENT   false 31
1186   PUNCH   ; [alone] 28
1187 "#,
1188     );
1189 }
1190
1191 #[test]
1192 fn test_vis() {
1193     parse_macro(
1194         r#"
1195         macro_rules! foo {
1196               ($ vis:vis $ name:ident) => { $ vis fn $ name() {}};
1197         }
1198 "#,
1199     )
1200     .assert_expand_items(r#"foo!(pub foo);"#, r#"pub fn foo () {}"#)
1201     // test optional cases
1202     .assert_expand_items(r#"foo!(foo);"#, r#"fn foo () {}"#);
1203 }
1204
1205 #[test]
1206 fn test_inner_macro_rules() {
1207     parse_macro(
1208         r#"
1209 macro_rules! foo {
1210     ($a:ident, $b:ident, $c:tt) => {
1211
1212         macro_rules! bar {
1213             ($bi:ident) => {
1214                 fn $bi() -> u8 {$c}
1215             }
1216         }
1217
1218         bar!($a);
1219         fn $b() -> u8 {$c}
1220     }
1221 }
1222 "#,
1223     ).
1224     assert_expand_items(
1225         r#"foo!(x,y, 1);"#,
1226         r#"macro_rules ! bar {($ bi : ident) => {fn $ bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#,
1227     );
1228 }
1229
1230 #[test]
1231 fn test_expr_after_path_colons() {
1232     assert!(parse_macro(
1233         r#"
1234 macro_rules! m {
1235     ($k:expr) => {
1236             f(K::$k);
1237        }
1238 }
1239 "#,
1240     )
1241     .expand_statements(r#"m!(C("0"))"#)
1242     .descendants()
1243     .find(|token| token.kind() == ERROR)
1244     .is_some());
1245 }
1246
1247 // The following tests are based on real world situations
1248 #[test]
1249 fn test_vec() {
1250     let fixture = parse_macro(
1251         r#"
1252          macro_rules! vec {
1253             ($($item:expr),*) => {
1254                 {
1255                     let mut v = Vec::new();
1256                     $(
1257                         v.push($item);
1258                     )*
1259                     v
1260                 }
1261             };
1262 }
1263 "#,
1264     );
1265     fixture
1266         .assert_expand_items(r#"vec!();"#, r#"{let mut v = Vec :: new () ; v}"#)
1267         .assert_expand_items(
1268             r#"vec![1u32,2];"#,
1269             r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#,
1270         );
1271
1272     let tree = fixture.expand_expr(r#"vec![1u32,2];"#);
1273
1274     assert_eq!(
1275         format!("{:#?}", tree).trim(),
1276         r#"BLOCK_EXPR@0..45
1277   L_CURLY@0..1 "{"
1278   LET_STMT@1..20
1279     LET_KW@1..4 "let"
1280     IDENT_PAT@4..8
1281       MUT_KW@4..7 "mut"
1282       NAME@7..8
1283         IDENT@7..8 "v"
1284     EQ@8..9 "="
1285     CALL_EXPR@9..19
1286       PATH_EXPR@9..17
1287         PATH@9..17
1288           PATH@9..12
1289             PATH_SEGMENT@9..12
1290               NAME_REF@9..12
1291                 IDENT@9..12 "Vec"
1292           COLON2@12..14 "::"
1293           PATH_SEGMENT@14..17
1294             NAME_REF@14..17
1295               IDENT@14..17 "new"
1296       ARG_LIST@17..19
1297         L_PAREN@17..18 "("
1298         R_PAREN@18..19 ")"
1299     SEMICOLON@19..20 ";"
1300   EXPR_STMT@20..33
1301     METHOD_CALL_EXPR@20..32
1302       PATH_EXPR@20..21
1303         PATH@20..21
1304           PATH_SEGMENT@20..21
1305             NAME_REF@20..21
1306               IDENT@20..21 "v"
1307       DOT@21..22 "."
1308       NAME_REF@22..26
1309         IDENT@22..26 "push"
1310       ARG_LIST@26..32
1311         L_PAREN@26..27 "("
1312         LITERAL@27..31
1313           INT_NUMBER@27..31 "1u32"
1314         R_PAREN@31..32 ")"
1315     SEMICOLON@32..33 ";"
1316   EXPR_STMT@33..43
1317     METHOD_CALL_EXPR@33..42
1318       PATH_EXPR@33..34
1319         PATH@33..34
1320           PATH_SEGMENT@33..34
1321             NAME_REF@33..34
1322               IDENT@33..34 "v"
1323       DOT@34..35 "."
1324       NAME_REF@35..39
1325         IDENT@35..39 "push"
1326       ARG_LIST@39..42
1327         L_PAREN@39..40 "("
1328         LITERAL@40..41
1329           INT_NUMBER@40..41 "2"
1330         R_PAREN@41..42 ")"
1331     SEMICOLON@42..43 ";"
1332   PATH_EXPR@43..44
1333     PATH@43..44
1334       PATH_SEGMENT@43..44
1335         NAME_REF@43..44
1336           IDENT@43..44 "v"
1337   R_CURLY@44..45 "}""#
1338     );
1339 }
1340
1341 #[test]
1342 fn test_winapi_struct() {
1343     // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366
1344
1345     parse_macro(
1346         r#"
1347 macro_rules! STRUCT {
1348     ($(#[$attrs:meta])* struct $name:ident {
1349         $($field:ident: $ftype:ty,)+
1350     }) => (
1351         #[repr(C)] #[derive(Copy)] $(#[$attrs])*
1352         pub struct $name {
1353             $(pub $field: $ftype,)+
1354         }
1355         impl Clone for $name {
1356             #[inline]
1357             fn clone(&self) -> $name { *self }
1358         }
1359         #[cfg(feature = "impl-default")]
1360         impl Default for $name {
1361             #[inline]
1362             fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } }
1363         }
1364     );
1365 }
1366 "#,
1367     ).
1368     // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs
1369     assert_expand_items(r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#,
1370         "# [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 ()}}}"
1371     )
1372     .assert_expand_items(r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#,
1373         "# [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 ()}}}"
1374     );
1375 }
1376
1377 #[test]
1378 fn test_int_base() {
1379     parse_macro(
1380         r#"
1381 macro_rules! int_base {
1382     ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
1383         #[stable(feature = "rust1", since = "1.0.0")]
1384         impl fmt::$Trait for $T {
1385             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1386                 $Radix.fmt_int(*self as $U, f)
1387             }
1388         }
1389     }
1390 }
1391 "#,
1392     ).assert_expand_items(r#" int_base!{Binary for isize as usize -> Binary}"#,
1393         "# [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)}}"
1394     );
1395 }
1396
1397 #[test]
1398 fn test_generate_pattern_iterators() {
1399     // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs
1400     parse_macro(
1401         r#"
1402 macro_rules! generate_pattern_iterators {
1403         { double ended; with $(#[$common_stability_attribute:meta])*,
1404                            $forward_iterator:ident,
1405                            $reverse_iterator:ident, $iterty:ty
1406         } => {
1407             fn foo(){}
1408         }
1409 }
1410 "#,
1411     ).assert_expand_items(
1412         r#"generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str );"#,
1413         "fn foo () {}",
1414     );
1415 }
1416
1417 #[test]
1418 fn test_impl_fn_for_zst() {
1419     // from https://github.com/rust-lang/rust/blob/5d20ff4d2718c820632b38c1e49d4de648a9810b/src/libcore/internal_macros.rs
1420     parse_macro(
1421         r#"
1422 macro_rules! impl_fn_for_zst  {
1423         {  $( $( #[$attr: meta] )*
1424         struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
1425             |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
1426 $body: block; )+
1427         } => {
1428            $(
1429             $( #[$attr] )*
1430             struct $Name;
1431
1432             impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
1433                 #[inline]
1434                 extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
1435                     $body
1436                 }
1437             }
1438
1439             impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
1440                 #[inline]
1441                 extern "rust-call" fn call_mut(
1442                     &mut self,
1443                     ($( $arg, )*): ($( $ArgTy, )*)
1444                 ) -> $ReturnTy {
1445                     Fn::call(&*self, ($( $arg, )*))
1446                 }
1447             }
1448
1449             impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
1450                 type Output = $ReturnTy;
1451
1452                 #[inline]
1453                 extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
1454                     Fn::call(&self, ($( $arg, )*))
1455                 }
1456             }
1457         )+
1458 }
1459         }
1460 "#,
1461     ).assert_expand_items(r#"
1462 impl_fn_for_zst !   {
1463      # [ derive ( Clone ) ]
1464      struct   CharEscapeDebugContinue   impl   Fn   =   | c :   char |   ->   char :: EscapeDebug   {
1465          c . escape_debug_ext ( false )
1466      } ;
1467
1468      # [ derive ( Clone ) ]
1469      struct   CharEscapeUnicode   impl   Fn   =   | c :   char |   ->   char :: EscapeUnicode   {
1470          c . escape_unicode ( )
1471      } ;
1472      # [ derive ( Clone ) ]
1473      struct   CharEscapeDefault   impl   Fn   =   | c :   char |   ->   char :: EscapeDefault   {
1474          c . escape_default ( )
1475      } ;
1476  }
1477 "#,
1478         "# [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 ,))}}"
1479     );
1480 }
1481
1482 #[test]
1483 fn test_impl_nonzero_fmt() {
1484     // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12
1485     parse_macro(
1486         r#"
1487         macro_rules! impl_nonzero_fmt {
1488             ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
1489                 fn foo () {}
1490             }
1491         }
1492 "#,
1493     ).assert_expand_items(
1494         r#"impl_nonzero_fmt! { # [stable(feature= "nonzero",since="1.28.0")] (Debug,Display,Binary,Octal,LowerHex,UpperHex) for NonZeroU8}"#,
1495         "fn foo () {}",
1496     );
1497 }
1498
1499 #[test]
1500 fn test_cfg_if_items() {
1501     // from https://github.com/rust-lang/rust/blob/33fe1131cadba69d317156847be9a402b89f11bb/src/libstd/macros.rs#L986
1502     parse_macro(
1503         r#"
1504         macro_rules! __cfg_if_items {
1505             (($($not:meta,)*) ; ) => {};
1506             (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
1507                  __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
1508             }
1509         }
1510 "#,
1511     ).assert_expand_items(
1512         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 ; ) ) , }"#,
1513         "__cfg_if_items ! {(rustdoc ,) ;}",
1514     );
1515 }
1516
1517 #[test]
1518 fn test_cfg_if_main() {
1519     // from https://github.com/rust-lang/rust/blob/3d211248393686e0f73851fc7548f6605220fbe1/src/libpanic_unwind/macros.rs#L9
1520     parse_macro(
1521         r#"
1522         macro_rules! cfg_if {
1523             ($(
1524                 if #[cfg($($meta:meta),*)] { $($it:item)* }
1525             ) else * else {
1526                 $($it2:item)*
1527             }) => {
1528                 __cfg_if_items! {
1529                     () ;
1530                     $( ( ($($meta),*) ($($it)*) ), )*
1531                     ( () ($($it2)*) ),
1532                 }
1533             };
1534
1535             // Internal macro to Apply a cfg attribute to a list of items
1536             (@__apply $m:meta, $($it:item)*) => {
1537                 $(#[$m] $it)*
1538             };
1539         }
1540 "#,
1541     ).assert_expand_items(r#"
1542 cfg_if !   {
1543      if   # [ cfg ( target_env   =   "msvc" ) ]   {
1544          // no extra unwinder support needed
1545      }   else   if   # [ cfg ( all ( target_arch   =   "wasm32" ,   not ( target_os   =   "emscripten" ) ) ) ]   {
1546          // no unwinder on the system!
1547      }   else   {
1548          mod   libunwind ;
1549          pub   use   libunwind :: * ;
1550      }
1551  }
1552 "#,
1553         "__cfg_if_items ! {() ; ((target_env = \"msvc\") ()) , ((all (target_arch = \"wasm32\" , not (target_os = \"emscripten\"))) ()) , (() (mod libunwind ; pub use libunwind :: * ;)) ,}"
1554     ).assert_expand_items(
1555         r#"
1556 cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , target_os = "illumos" ) ) ) ) ) ) , }
1557 "#,
1558         "",
1559     );
1560 }
1561
1562 #[test]
1563 fn test_proptest_arbitrary() {
1564     // from https://github.com/AltSysrq/proptest/blob/d1c4b049337d2f75dd6f49a095115f7c532e5129/proptest/src/arbitrary/macros.rs#L16
1565     parse_macro(
1566         r#"
1567 macro_rules! arbitrary {
1568     ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty;
1569         $args: ident => $logic: expr) => {
1570         impl<$($bounds)*> $crate::arbitrary::Arbitrary for $typ {
1571             type Parameters = $params;
1572             type Strategy = $strat;
1573             fn arbitrary_with($args: Self::Parameters) -> Self::Strategy {
1574                 $logic
1575             }
1576         }
1577     };
1578
1579 }"#,
1580     ).assert_expand_items(r#"arbitrary !   ( [ A : Arbitrary ]
1581         Vec < A > ,
1582         VecStrategy < A :: Strategy > ,
1583         RangedParams1 < A :: Parameters > ;
1584         args =>   { let product_unpack !   [ range , a ] = args ; vec ( any_with :: < A >   ( a ) , range ) }
1585     ) ;"#,
1586     "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)}}}"
1587     );
1588 }
1589
1590 #[test]
1591 fn test_old_ridl() {
1592     // This is from winapi 2.8, which do not have a link from github
1593     //
1594     let expanded = parse_macro(
1595         r#"
1596 #[macro_export]
1597 macro_rules! RIDL {
1598     (interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident)
1599         {$(
1600             fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty
1601         ),+}
1602     ) => {
1603         impl $interface {
1604             $(pub unsafe fn $method(&mut self) -> $rtr {
1605                 ((*self.lpVtbl).$method)(self $(,$p)*)
1606             })+
1607         }
1608     };
1609 }"#,
1610     ).expand_tt(r#"
1611     RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) {
1612         fn GetDataSize(&mut self) -> UINT
1613     }}"#);
1614
1615     assert_eq!(expanded.to_string(), "impl ID3D11Asynchronous {pub unsafe fn GetDataSize (& mut self) -> UINT {((* self . lpVtbl) .GetDataSize) (self)}}");
1616 }
1617
1618 #[test]
1619 fn test_quick_error() {
1620     let expanded = parse_macro(
1621         r#"
1622 macro_rules! quick_error {
1623
1624  (SORT [enum $name:ident $( #[$meta:meta] )*]
1625         items [$($( #[$imeta:meta] )*
1626                   => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
1627                                 {$( $ifuncs:tt )*} )* ]
1628         buf [ ]
1629         queue [ ]
1630     ) => {
1631         quick_error!(ENUMINITION [enum $name $( #[$meta] )*]
1632             body []
1633             queue [$(
1634                 $( #[$imeta] )*
1635                 =>
1636                 $iitem: $imode [$( $ivar: $ityp ),*]
1637             )*]
1638         );
1639 };
1640
1641 }
1642 "#,
1643     )
1644     .expand_tt(
1645         r#"
1646 quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [
1647         => One : UNIT [] {}
1648         => Two : TUPLE [s :String] {display ("two: {}" , s) from ()}
1649     ] buf [] queue []) ;
1650 "#,
1651     );
1652
1653     assert_eq!(expanded.to_string(), "quick_error ! (ENUMINITION [enum Wrapped # [derive (Debug)]] body [] queue [=> One : UNIT [] => Two : TUPLE [s : String]]) ;");
1654 }
1655
1656 #[test]
1657 fn test_empty_repeat_vars_in_empty_repeat_vars() {
1658     parse_macro(
1659         r#"
1660 macro_rules! delegate_impl {
1661     ([$self_type:ident, $self_wrap:ty, $self_map:ident]
1662      pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* {
1663
1664         // "Escaped" associated types. Stripped before making the `trait`
1665         // itself, but forwarded when delegating impls.
1666         $(
1667         @escape [type $assoc_name_ext:ident]
1668         // Associated types. Forwarded.
1669         )*
1670         $(
1671         @section type
1672         $(
1673             $(#[$_assoc_attr:meta])*
1674             type $assoc_name:ident $(: $assoc_bound:ty)*;
1675         )+
1676         )*
1677         // Methods. Forwarded. Using $self_map!(self) around the self argument.
1678         // Methods must use receiver `self` or explicit type like `self: &Self`
1679         // &self and &mut self are _not_ supported.
1680         $(
1681         @section self
1682         $(
1683             $(#[$_method_attr:meta])*
1684             fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) -> $mret:ty;
1685         )+
1686         )*
1687         // Arbitrary tail that is ignored when forwarding.
1688         $(
1689         @section nodelegate
1690         $($tail:tt)*
1691         )*
1692     }) => {
1693         impl<> $name for $self_wrap where $self_type: $name {
1694             $(
1695             $(
1696                 fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) -> $mret {
1697                     $self_map!(self).$method_name($($marg),*)
1698                 }
1699             )*
1700             )*
1701         }
1702     }
1703 }
1704 "#,
1705     ).assert_expand_items(
1706         r#"delegate_impl ! {[G , & 'a mut G , deref] pub trait Data : GraphBase {@ section type type NodeWeight ;}}"#,
1707         "impl <> Data for & \'a mut G where G : Data {}",
1708     );
1709 }
1710
1711 #[test]
1712 fn expr_interpolation() {
1713     let expanded = parse_macro(
1714         r#"
1715         macro_rules! id {
1716             ($expr:expr) => {
1717                 map($expr)
1718             }
1719         }
1720         "#,
1721     )
1722     .expand_expr("id!(x + foo);");
1723
1724     assert_eq!(expanded.to_string(), "map(x+foo)");
1725 }
1726
1727 pub(crate) struct MacroFixture {
1728     rules: MacroRules,
1729 }
1730
1731 pub(crate) struct MacroFixture2 {
1732     rules: MacroDef,
1733 }
1734
1735 macro_rules! impl_fixture {
1736     ($name:ident) => {
1737         impl $name {
1738             pub(crate) fn expand_tt(&self, invocation: &str) -> tt::Subtree {
1739                 self.try_expand_tt(invocation).unwrap()
1740             }
1741
1742             fn try_expand_tt(&self, invocation: &str) -> Result<tt::Subtree, ExpandError> {
1743                 let source_file = ast::SourceFile::parse(invocation).tree();
1744                 let macro_invocation =
1745                     source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
1746
1747                 let (invocation_tt, _) = ast_to_token_tree(&macro_invocation.token_tree().unwrap())
1748                     .ok_or_else(|| ExpandError::ConversionError)?;
1749
1750                 self.rules.expand(&invocation_tt).result()
1751             }
1752
1753             #[allow(unused)]
1754             fn assert_expand_err(&self, invocation: &str, err: &ExpandError) {
1755                 assert_eq!(self.try_expand_tt(invocation).as_ref(), Err(err));
1756             }
1757
1758             #[allow(unused)]
1759             fn expand_items(&self, invocation: &str) -> SyntaxNode {
1760                 let expanded = self.expand_tt(invocation);
1761                 token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node()
1762             }
1763
1764             #[allow(unused)]
1765             fn expand_statements(&self, invocation: &str) -> SyntaxNode {
1766                 let expanded = self.expand_tt(invocation);
1767                 token_tree_to_syntax_node(&expanded, FragmentKind::Statements)
1768                     .unwrap()
1769                     .0
1770                     .syntax_node()
1771             }
1772
1773             #[allow(unused)]
1774             fn expand_expr(&self, invocation: &str) -> SyntaxNode {
1775                 let expanded = self.expand_tt(invocation);
1776                 token_tree_to_syntax_node(&expanded, FragmentKind::Expr).unwrap().0.syntax_node()
1777             }
1778
1779             #[allow(unused)]
1780             fn assert_expand_tt(&self, invocation: &str, expected: &str) {
1781                 let expansion = self.expand_tt(invocation);
1782                 assert_eq!(expansion.to_string(), expected);
1783             }
1784
1785             #[allow(unused)]
1786             fn assert_expand(&self, invocation: &str, expected: &str) {
1787                 let expansion = self.expand_tt(invocation);
1788                 let actual = format!("{:?}", expansion);
1789                 test_utils::assert_eq_text!(&expected.trim(), &actual.trim());
1790             }
1791
1792             fn assert_expand_items(&self, invocation: &str, expected: &str) -> &$name {
1793                 self.assert_expansion(FragmentKind::Items, invocation, expected);
1794                 self
1795             }
1796
1797             #[allow(unused)]
1798             fn assert_expand_statements(&self, invocation: &str, expected: &str) -> &$name {
1799                 self.assert_expansion(FragmentKind::Statements, invocation, expected);
1800                 self
1801             }
1802
1803             fn assert_expansion(&self, kind: FragmentKind, invocation: &str, expected: &str) {
1804                 let expanded = self.expand_tt(invocation);
1805                 assert_eq!(expanded.to_string(), expected);
1806
1807                 let expected = expected.replace("$crate", "C_C__C");
1808
1809                 // wrap the given text to a macro call
1810                 let expected = {
1811                     let wrapped = format!("wrap_macro!( {} )", expected);
1812                     let wrapped = ast::SourceFile::parse(&wrapped);
1813                     let wrapped = wrapped
1814                         .tree()
1815                         .syntax()
1816                         .descendants()
1817                         .find_map(ast::TokenTree::cast)
1818                         .unwrap();
1819                     let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0;
1820                     wrapped.delimiter = None;
1821                     wrapped
1822                 };
1823
1824                 let expanded_tree =
1825                     token_tree_to_syntax_node(&expanded, kind).unwrap().0.syntax_node();
1826                 let expanded_tree = debug_dump_ignore_spaces(&expanded_tree).trim().to_string();
1827
1828                 let expected_tree =
1829                     token_tree_to_syntax_node(&expected, kind).unwrap().0.syntax_node();
1830                 let expected_tree = debug_dump_ignore_spaces(&expected_tree).trim().to_string();
1831
1832                 let expected_tree = expected_tree.replace("C_C__C", "$crate");
1833                 assert_eq!(
1834                     expanded_tree, expected_tree,
1835                     "\nleft:\n{}\nright:\n{}",
1836                     expanded_tree, expected_tree,
1837                 );
1838             }
1839         }
1840     };
1841 }
1842
1843 impl_fixture!(MacroFixture);
1844 impl_fixture!(MacroFixture2);
1845
1846 fn parse_macro_rules_to_tt(ra_fixture: &str) -> tt::Subtree {
1847     let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap();
1848     let macro_definition =
1849         source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap();
1850
1851     let (definition_tt, _) = ast_to_token_tree(&macro_definition.token_tree().unwrap()).unwrap();
1852
1853     let parsed = parse_to_token_tree(
1854         &ra_fixture[macro_definition.token_tree().unwrap().syntax().text_range()],
1855     )
1856     .unwrap()
1857     .0;
1858     assert_eq!(definition_tt, parsed);
1859
1860     definition_tt
1861 }
1862
1863 fn parse_macro_def_to_tt(ra_fixture: &str) -> tt::Subtree {
1864     let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap();
1865     let macro_definition =
1866         source_file.syntax().descendants().find_map(ast::MacroDef::cast).unwrap();
1867
1868     let (definition_tt, _) = ast_to_token_tree(&macro_definition.body().unwrap()).unwrap();
1869
1870     let parsed =
1871         parse_to_token_tree(&ra_fixture[macro_definition.body().unwrap().syntax().text_range()])
1872             .unwrap()
1873             .0;
1874     assert_eq!(definition_tt, parsed);
1875
1876     definition_tt
1877 }
1878
1879 pub(crate) fn parse_macro(ra_fixture: &str) -> MacroFixture {
1880     let definition_tt = parse_macro_rules_to_tt(ra_fixture);
1881     let rules = MacroRules::parse(&definition_tt).unwrap();
1882     MacroFixture { rules }
1883 }
1884
1885 pub(crate) fn parse_macro2(ra_fixture: &str) -> MacroFixture2 {
1886     let definition_tt = parse_macro_def_to_tt(ra_fixture);
1887     let rules = MacroDef::parse(&definition_tt).unwrap();
1888     MacroFixture2 { rules }
1889 }
1890
1891 pub(crate) fn parse_macro_error(ra_fixture: &str) -> ParseError {
1892     let definition_tt = parse_macro_rules_to_tt(ra_fixture);
1893
1894     match MacroRules::parse(&definition_tt) {
1895         Ok(_) => panic!("Expect error"),
1896         Err(err) => err,
1897     }
1898 }
1899
1900 pub(crate) fn parse_to_token_tree_by_syntax(ra_fixture: &str) -> tt::Subtree {
1901     let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap();
1902     let tt = syntax_node_to_token_tree(source_file.syntax()).unwrap().0;
1903
1904     let parsed = parse_to_token_tree(ra_fixture).unwrap().0;
1905     assert_eq!(tt, parsed);
1906
1907     parsed
1908 }
1909
1910 fn debug_dump_ignore_spaces(node: &syntax::SyntaxNode) -> String {
1911     let mut level = 0;
1912     let mut buf = String::new();
1913     macro_rules! indent {
1914         () => {
1915             for _ in 0..level {
1916                 buf.push_str("  ");
1917             }
1918         };
1919     }
1920
1921     for event in node.preorder_with_tokens() {
1922         match event {
1923             WalkEvent::Enter(element) => {
1924                 match element {
1925                     NodeOrToken::Node(node) => {
1926                         indent!();
1927                         writeln!(buf, "{:?}", node.kind()).unwrap();
1928                     }
1929                     NodeOrToken::Token(token) => match token.kind() {
1930                         syntax::SyntaxKind::WHITESPACE => {}
1931                         _ => {
1932                             indent!();
1933                             writeln!(buf, "{:?}", token.kind()).unwrap();
1934                         }
1935                     },
1936                 }
1937                 level += 1;
1938             }
1939             WalkEvent::Leave(_) => level -= 1,
1940         }
1941     }
1942
1943     buf
1944 }
1945
1946 #[test]
1947 fn test_issue_2520() {
1948     let macro_fixture = parse_macro(
1949         r#"
1950         macro_rules! my_macro {
1951             {
1952                 ( $(
1953                     $( [] $sname:ident : $stype:ty  )?
1954                     $( [$expr:expr] $nname:ident : $ntype:ty  )?
1955                 ),* )
1956             } => {
1957                 Test {
1958                     $(
1959                         $( $sname, )?
1960                     )*
1961                 }
1962             };
1963         }
1964     "#,
1965     );
1966
1967     macro_fixture.assert_expand_items(
1968         r#"my_macro ! {
1969             ([] p1 : u32 , [|_| S0K0] s : S0K0 , [] k0 : i32)
1970         }"#,
1971         "Test {p1 , k0 ,}",
1972     );
1973 }
1974
1975 #[test]
1976 fn test_issue_3861() {
1977     let macro_fixture = parse_macro(
1978         r#"
1979         macro_rules! rgb_color {
1980             ($p:expr, $t: ty) => {
1981                 pub fn new() {
1982                     let _ = 0 as $t << $p;
1983                 }
1984             };
1985         }
1986     "#,
1987     );
1988
1989     macro_fixture.expand_items(r#"rgb_color!(8 + 8, u32);"#);
1990 }
1991
1992 #[test]
1993 fn test_repeat_bad_var() {
1994     // FIXME: the second rule of the macro should be removed and an error about
1995     // `$( $c )+` raised
1996     parse_macro(
1997         r#"
1998         macro_rules! foo {
1999             ($( $b:ident )+) => {
2000                 $( $c )+
2001             };
2002             ($( $b:ident )+) => {
2003                 $( $b )+
2004             }
2005         }
2006     "#,
2007     )
2008     .assert_expand_items("foo!(b0 b1);", "b0 b1");
2009 }
2010
2011 #[test]
2012 fn test_no_space_after_semi_colon() {
2013     let expanded = parse_macro(
2014         r#"
2015         macro_rules! with_std { ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) }
2016     "#,
2017     )
2018     .expand_items(r#"with_std! {mod m;mod f;}"#);
2019
2020     let dump = format!("{:#?}", expanded);
2021     assert_eq_text!(
2022         r###"MACRO_ITEMS@0..52
2023   MODULE@0..26
2024     ATTR@0..21
2025       POUND@0..1 "#"
2026       L_BRACK@1..2 "["
2027       PATH@2..5
2028         PATH_SEGMENT@2..5
2029           NAME_REF@2..5
2030             IDENT@2..5 "cfg"
2031       TOKEN_TREE@5..20
2032         L_PAREN@5..6 "("
2033         IDENT@6..13 "feature"
2034         EQ@13..14 "="
2035         STRING@14..19 "\"std\""
2036         R_PAREN@19..20 ")"
2037       R_BRACK@20..21 "]"
2038     MOD_KW@21..24 "mod"
2039     NAME@24..25
2040       IDENT@24..25 "m"
2041     SEMICOLON@25..26 ";"
2042   MODULE@26..52
2043     ATTR@26..47
2044       POUND@26..27 "#"
2045       L_BRACK@27..28 "["
2046       PATH@28..31
2047         PATH_SEGMENT@28..31
2048           NAME_REF@28..31
2049             IDENT@28..31 "cfg"
2050       TOKEN_TREE@31..46
2051         L_PAREN@31..32 "("
2052         IDENT@32..39 "feature"
2053         EQ@39..40 "="
2054         STRING@40..45 "\"std\""
2055         R_PAREN@45..46 ")"
2056       R_BRACK@46..47 "]"
2057     MOD_KW@47..50 "mod"
2058     NAME@50..51
2059       IDENT@50..51 "f"
2060     SEMICOLON@51..52 ";""###,
2061         dump.trim()
2062     );
2063 }
2064
2065 // https://github.com/rust-lang/rust/blob/master/src/test/ui/issues/issue-57597.rs
2066 #[test]
2067 fn test_rustc_issue_57597() {
2068     fn test_error(fixture: &str) {
2069         assert_eq!(parse_macro_error(fixture), ParseError::RepetitionEmptyTokenTree);
2070     }
2071
2072     test_error("macro_rules! foo { ($($($i:ident)?)+) => {}; }");
2073     test_error("macro_rules! foo { ($($($i:ident)?)*) => {}; }");
2074     test_error("macro_rules! foo { ($($($i:ident)?)?) => {}; }");
2075     test_error("macro_rules! foo { ($($($($i:ident)?)?)?) => {}; }");
2076     test_error("macro_rules! foo { ($($($($i:ident)*)?)?) => {}; }");
2077     test_error("macro_rules! foo { ($($($($i:ident)?)*)?) => {}; }");
2078     test_error("macro_rules! foo { ($($($($i:ident)?)?)*) => {}; }");
2079     test_error("macro_rules! foo { ($($($($i:ident)*)*)?) => {}; }");
2080     test_error("macro_rules! foo { ($($($($i:ident)?)*)*) => {}; }");
2081     test_error("macro_rules! foo { ($($($($i:ident)?)*)+) => {}; }");
2082     test_error("macro_rules! foo { ($($($($i:ident)+)?)*) => {}; }");
2083     test_error("macro_rules! foo { ($($($($i:ident)+)*)?) => {}; }");
2084 }
2085
2086 #[test]
2087 fn test_expand_bad_literal() {
2088     parse_macro(
2089         r#"
2090         macro_rules! foo { ($i:literal) => {}; }
2091     "#,
2092     )
2093     .assert_expand_err(r#"foo!(&k");"#, &ExpandError::BindingError("".into()));
2094 }
2095
2096 #[test]
2097 fn test_empty_comments() {
2098     parse_macro(
2099         r#"
2100         macro_rules! one_arg_macro { ($fmt:expr) => (); }
2101     "#,
2102     )
2103     .assert_expand_err(
2104         r#"one_arg_macro!(/**/)"#,
2105         &ExpandError::BindingError("expected Expr".into()),
2106     );
2107 }