Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir_def/src/macro_expansion_tests/mbe.rs20
-rw-r--r--crates/hir_def/src/macro_expansion_tests/mbe/tt_conversion.rs50
-rw-r--r--crates/mbe/src/syntax_bridge.rs1
-rw-r--r--crates/parser/src/tests.rs8
-rw-r--r--crates/parser/src/tests/top_entries.rs56
5 files changed, 113 insertions, 22 deletions
diff --git a/crates/hir_def/src/macro_expansion_tests/mbe.rs b/crates/hir_def/src/macro_expansion_tests/mbe.rs
index 466c85fc5b..2cd70a84c5 100644
--- a/crates/hir_def/src/macro_expansion_tests/mbe.rs
+++ b/crates/hir_def/src/macro_expansion_tests/mbe.rs
@@ -86,26 +86,6 @@ impl From<Subtree> for TokenTree {
}
#[test]
-fn expansion_does_not_parse_as_expression() {
- check(
- r#"
-macro_rules! stmts {
- () => { let _ = 0; }
-}
-
-fn f() { let _ = stmts!(); }
-"#,
- expect![[r#"
-macro_rules! stmts {
- () => { let _ = 0; }
-}
-
-fn f() { let _ = /* error: could not convert tokens */; }
-"#]],
- )
-}
-
-#[test]
fn wrong_nesting_level() {
check(
r#"
diff --git a/crates/hir_def/src/macro_expansion_tests/mbe/tt_conversion.rs b/crates/hir_def/src/macro_expansion_tests/mbe/tt_conversion.rs
index 291f99330f..97c27c453b 100644
--- a/crates/hir_def/src/macro_expansion_tests/mbe/tt_conversion.rs
+++ b/crates/hir_def/src/macro_expansion_tests/mbe/tt_conversion.rs
@@ -2,7 +2,9 @@
//! Rather, token trees are an explicit bridge between the parser and
//! (procedural or declarative) macros.
//!
-//! This module tests tt <-> syntax tree conversion specifically
+//! This module tests tt <-> syntax tree conversion specifically. In particular,
+//! it, among other things, check that we convert `tt` to the right kind of
+//! syntax node depending on the macro call-site.
use expect_test::expect;
use crate::macro_expansion_tests::check;
@@ -100,3 +102,49 @@ macro_rules! m2 { ($x:ident) => {} }
"#]],
)
}
+
+#[test]
+fn expansion_does_not_parse_as_expression() {
+ cov_mark::check!(expansion_does_not_parse_as_expression);
+ check(
+ r#"
+macro_rules! stmts {
+ () => { let _ = 0; }
+}
+
+fn f() { let _ = stmts!(); }
+"#,
+ expect![[r#"
+macro_rules! stmts {
+ () => { let _ = 0; }
+}
+
+fn f() { let _ = /* error: could not convert tokens */; }
+"#]],
+ )
+}
+
+#[test]
+fn broken_pat() {
+ check(
+ r#"
+macro_rules! m1 { () => (Some(x) left overs) }
+macro_rules! m2 { () => ($) }
+
+fn main() {
+ let m1!() = ();
+ let m2!/*+errors*/() = ();
+}
+"#,
+ expect![[r#"
+macro_rules! m1 { () => (Some(x) left overs) }
+macro_rules! m2 { () => ($) }
+
+fn main() {
+ let Some(x) = ();
+ let /* parse error: expected pattern */
+$ = ();
+}
+"#]],
+ )
+}
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 8021e63f7f..1141365e82 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -67,6 +67,7 @@ pub fn token_tree_to_syntax_node(
}
}
if tree_sink.roots.len() != 1 {
+ cov_mark::hit!(expansion_does_not_parse_as_expression);
return Err(ExpandError::ConversionError);
}
//FIXME: would be cool to report errors
diff --git a/crates/parser/src/tests.rs b/crates/parser/src/tests.rs
index 52388dacc6..c0437bc3b8 100644
--- a/crates/parser/src/tests.rs
+++ b/crates/parser/src/tests.rs
@@ -114,7 +114,13 @@ fn parse(entry: TopEntryPoint, text: &str) -> (String, bool) {
errors.push(format!("error {}: {}\n", pos, msg))
}
});
- assert_eq!(len, text.len());
+ assert_eq!(
+ len,
+ text.len(),
+ "didn't parse all text.\nParsed:\n{}\n\nAll:\n{}\n",
+ &text[..len],
+ text
+ );
for (token, msg) in lexed.errors() {
let pos = lexed.text_start(token);
diff --git a/crates/parser/src/tests/top_entries.rs b/crates/parser/src/tests/top_entries.rs
index 0b77c0a5b9..fa25ffd0a2 100644
--- a/crates/parser/src/tests/top_entries.rs
+++ b/crates/parser/src/tests/top_entries.rs
@@ -92,6 +92,62 @@ fn macro_stmt() {
);
}
+#[test]
+fn macro_items() {
+ check(
+ TopEntryPoint::MacroItems,
+ "#!/usr/bin/rust",
+ expect![[r##"
+ MACRO_ITEMS
+ ERROR
+ SHEBANG "#!/usr/bin/rust"
+ error 0: expected an item
+ "##]],
+ );
+ check(
+ TopEntryPoint::MacroItems,
+ "struct S; foo!{}",
+ expect![[r#"
+ MACRO_ITEMS
+ STRUCT
+ STRUCT_KW "struct"
+ WHITESPACE " "
+ NAME
+ IDENT "S"
+ SEMICOLON ";"
+ WHITESPACE " "
+ MACRO_CALL
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "foo"
+ BANG "!"
+ TOKEN_TREE
+ L_CURLY "{"
+ R_CURLY "}"
+ "#]],
+ );
+}
+
+#[test]
+fn macro_pattern() {
+ check(
+ TopEntryPoint::Pattern,
+ "Some(_)",
+ expect![[r#"
+ TUPLE_STRUCT_PAT
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Some"
+ L_PAREN "("
+ WILDCARD_PAT
+ UNDERSCORE "_"
+ R_PAREN ")"
+ "#]],
+ );
+}
+
#[track_caller]
fn check(entry: TopEntryPoint, input: &str, expect: expect_test::Expect) {
let (parsed, _errors) = super::parse(entry, input);