Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_def/src/macro_expansion_tests/mbe.rs')
| -rw-r--r-- | crates/hir_def/src/macro_expansion_tests/mbe.rs | 272 |
1 files changed, 248 insertions, 24 deletions
diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs index c57e9cd838..384c70028d 100644 --- a/crates/hir_def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs @@ -10,6 +10,45 @@ use expect_test::expect; use crate::macro_expansion_tests::check; #[test] +fn mbe_smoke_test() { + check( + r#" +macro_rules! impl_froms { + ($e:ident: $($v:ident),*) => { + $( + impl From<$v> for $e { + fn from(it: $v) -> $e { $e::$v(it) } + } + )* + } +} +impl_froms!(TokenTree: Leaf, Subtree); +"#, + expect![[r#" +macro_rules! impl_froms { + ($e:ident: $($v:ident),*) => { + $( + impl From<$v> for $e { + fn from(it: $v) -> $e { $e::$v(it) } + } + )* + } +} +impl From<Leaf> for TokenTree { + fn from(it:Leaf) -> TokenTree { + TokenTree::Leaf(it) + } +} +impl From<Subtree> for TokenTree { + fn from(it:Subtree) -> TokenTree { + TokenTree::Subtree(it) + } +} +"#]], + ); +} + +#[test] fn expansion_does_not_parse_as_expression() { check( r#" @@ -52,9 +91,9 @@ fn match_by_first_token_literally() { check( r#" macro_rules! m { - ($ i:ident) => ( mod $ i {} ); - (= $ i:ident) => ( fn $ i() {} ); - (+ $ i:ident) => ( struct $ i; ) + ($i:ident) => ( mod $i {} ); + (= $i:ident) => ( fn $i() {} ); + (+ $i:ident) => ( struct $i; ) } m! { foo } m! { = bar } @@ -62,9 +101,9 @@ m! { + Baz } "#, expect![[r#" macro_rules! m { - ($ i:ident) => ( mod $ i {} ); - (= $ i:ident) => ( fn $ i() {} ); - (+ $ i:ident) => ( struct $ i; ) + ($i:ident) => ( mod $i {} ); + (= $i:ident) => ( fn $i() {} ); + (+ $i:ident) => ( struct $i; ) } mod foo {} fn bar() {} @@ -78,9 +117,9 @@ fn match_by_last_token_literally() { check( r#" macro_rules! m { - ($ i:ident) => ( mod $ i {} ); - ($ i:ident =) => ( fn $ i() {} ); - ($ i:ident +) => ( struct $ i; ) + ($i:ident) => ( mod $i {} ); + ($i:ident =) => ( fn $i() {} ); + ($i:ident +) => ( struct $i; ) } m! { foo } m! { bar = } @@ -88,9 +127,9 @@ m! { Baz + } "#, expect![[r#" macro_rules! m { - ($ i:ident) => ( mod $ i {} ); - ($ i:ident =) => ( fn $ i() {} ); - ($ i:ident +) => ( struct $ i; ) + ($i:ident) => ( mod $i {} ); + ($i:ident =) => ( fn $i() {} ); + ($i:ident +) => ( struct $i; ) } mod foo {} fn bar() {} @@ -104,9 +143,9 @@ fn match_by_ident() { check( r#" macro_rules! m { - ($ i:ident) => ( mod $ i {} ); - (spam $ i:ident) => ( fn $ i() {} ); - (eggs $ i:ident) => ( struct $ i; ) + ($i:ident) => ( mod $i {} ); + (spam $i:ident) => ( fn $i() {} ); + (eggs $i:ident) => ( struct $i; ) } m! { foo } m! { spam bar } @@ -114,9 +153,9 @@ m! { eggs Baz } "#, expect![[r#" macro_rules! m { - ($ i:ident) => ( mod $ i {} ); - (spam $ i:ident) => ( fn $ i() {} ); - (eggs $ i:ident) => ( struct $ i; ) + ($i:ident) => ( mod $i {} ); + (spam $i:ident) => ( fn $i() {} ); + (eggs $i:ident) => ( struct $i; ) } mod foo {} fn bar() {} @@ -130,9 +169,9 @@ fn match_by_separator_token() { check( r#" macro_rules! m { - ($ ($ i:ident),*) => ($ ( mod $ i {} )*); - ($ ($ i:ident)#*) => ($ ( fn $ i() {} )*); - ($ i:ident ,# $ j:ident) => ( struct $ i; struct $ j; ) + ($($i:ident),*) => ($(mod $i {} )*); + ($($i:ident)#*) => ($(fn $i() {} )*); + ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; ) } m! { foo, bar } @@ -143,9 +182,9 @@ m! { Foo,# Bar } "#, expect![[r##" macro_rules! m { - ($ ($ i:ident),*) => ($ ( mod $ i {} )*); - ($ ($ i:ident)#*) => ($ ( fn $ i() {} )*); - ($ i:ident ,# $ j:ident) => ( struct $ i; struct $ j; ) + ($($i:ident),*) => ($(mod $i {} )*); + ($($i:ident)#*) => ($(fn $i() {} )*); + ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; ) } mod foo {} @@ -159,3 +198,188 @@ struct Bar; "##]], ); } + +#[test] +fn test_match_group_pattern_with_multiple_defs() { + check( + r#" +macro_rules! m { + ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); +} +m! { foo, bar } +"#, + expect![[r#" +macro_rules! m { + ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); +} +impl Bar { + fn foo() {} + fn bar() {} +} +"#]], + ); +} + +#[test] +fn test_match_group_pattern_with_multiple_statement() { + check( + r#" +macro_rules! m { + ($($i:ident),*) => ( fn baz() { $($i ();)* } ); +} +m! { foo, bar } +"#, + expect![[r#" +macro_rules! m { + ($($i:ident),*) => ( fn baz() { $($i ();)* } ); +} +fn baz() { + foo(); + bar(); +} +"#]], + ) +} + +#[test] +fn test_match_group_pattern_with_multiple_statement_without_semi() { + check( + r#" +macro_rules! m { + ($($i:ident),*) => ( fn baz() { $($i() );* } ); +} +m! { foo, bar } +"#, + expect![[r#" +macro_rules! m { + ($($i:ident),*) => ( fn baz() { $($i() );* } ); +} +fn baz() { + foo(); + bar() +} +"#]], + ) +} + +#[test] +fn test_match_group_empty_fixed_token() { + check( + r#" +macro_rules! m { + ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } ); +} +m!{#abc} +"#, + expect![[r##" +macro_rules! m { + ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } ); +} +fn baz() {} +"##]], + ) +} + +#[test] +fn test_match_group_in_subtree() { + check( + r#" +macro_rules! m { + (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } ); +} +m! { fn baz { a b } } +"#, + expect![[r#" +macro_rules! m { + (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } ); +} +fn baz() { + a(); + b(); +} +"#]], + ) +} + +#[test] +fn test_expr_order() { + check( + r#" +macro_rules! m { + ($ i:expr) => { fn bar() { $ i * 3; } } +} +// +tree +m! { 1 + 2 } +"#, + expect![[r#" +macro_rules! m { + ($ i:expr) => { fn bar() { $ i * 3; } } +} +fn bar() { + 1+2*3; +} +// [email protected] "fn" +// [email protected] "bar" +// [email protected] "(" +// [email protected] ")" +// [email protected] "{" +// [email protected] "1" +// [email protected] "+" +// [email protected] "2" +// [email protected] "*" +// [email protected] "3" +// [email protected] ";" +// [email protected] "}" + +"#]], + ) +} + +#[test] +fn test_match_group_with_multichar_sep() { + check( + r#" +macro_rules! m { + (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } ); +} +m! (fn baz { true false } ); +"#, + expect![[r#" +macro_rules! m { + (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } ); +} +fn baz() -> bool { + true && false +} +"#]], + ); + + check( + r#" +macro_rules! m { + (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } ); +} +m! (fn baz { true && false } ); +"#, + expect![[r#" +macro_rules! m { + (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } ); +} +fn baz() -> bool { + true && false +} +"#]], + ); +} |