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.rs272
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;
+}
+
+"#]],
+ )
+}
+
+#[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
+}
+"#]],
+ );
+}