Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/tests.rs')
-rw-r--r--crates/mbe/src/tests.rs179
1 files changed, 179 insertions, 0 deletions
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
new file mode 100644
index 0000000000..5422c9ae64
--- /dev/null
+++ b/crates/mbe/src/tests.rs
@@ -0,0 +1,179 @@
+//! Tests specific to declarative macros, aka macros by example. This covers
+//! both stable `macro_rules!` macros as well as unstable `macro` macros.
+// FIXME: Move more of the nameres independent tests from
+// crates\hir-def\src\macro_expansion_tests\mod.rs to this
+use expect_test::expect;
+use span::{Edition, EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId};
+use stdx::format_to;
+use syntax_bridge::insert_whitespace_into_node::insert_ws_into;
+use tt::{TextRange, TextSize};
+
+use crate::DeclarativeMacro;
+
+fn check_(
+ def_edition: Edition,
+ call_edition: Edition,
+ macro2: bool,
+ decl: &str,
+ arg: &str,
+ render_debug: bool,
+ expect: expect_test::Expect,
+ parse: parser::TopEntryPoint,
+) {
+ let decl_tt = &syntax_bridge::parse_to_token_tree(
+ def_edition,
+ SpanAnchor {
+ file_id: EditionedFileId::new(FileId::from_raw(0), def_edition),
+ ast_id: ErasedFileAstId::from_raw(0),
+ },
+ SyntaxContextId::ROOT,
+ decl,
+ )
+ .unwrap();
+ let mac = if macro2 {
+ DeclarativeMacro::parse_macro2(None, decl_tt, |_| def_edition)
+ } else {
+ DeclarativeMacro::parse_macro_rules(decl_tt, |_| def_edition)
+ };
+ let call_anchor = SpanAnchor {
+ file_id: EditionedFileId::new(FileId::from_raw(1), call_edition),
+ ast_id: ErasedFileAstId::from_raw(0),
+ };
+ let arg_tt =
+ syntax_bridge::parse_to_token_tree(call_edition, call_anchor, SyntaxContextId::ROOT, arg)
+ .unwrap();
+ let res = mac.expand(
+ &arg_tt,
+ |_| (),
+ Span {
+ range: TextRange::up_to(TextSize::of(arg)),
+ anchor: call_anchor,
+ ctx: SyntaxContextId::ROOT,
+ },
+ def_edition,
+ );
+ let mut expect_res = String::new();
+ if let Some(err) = res.err {
+ format_to!(expect_res, "{err:#?}\n\n",);
+ }
+ if render_debug {
+ format_to!(expect_res, "{:#?}\n\n", res.value.0);
+ }
+ let (node, _) = syntax_bridge::token_tree_to_syntax_node(&res.value.0, parse, def_edition);
+ format_to!(expect_res, "{}", insert_ws_into(node.syntax_node()));
+ expect.assert_eq(&expect_res);
+}
+
+fn check(
+ def_edition: Edition,
+ call_edition: Edition,
+ decl: &str,
+ arg: &str,
+ expect: expect_test::Expect,
+) {
+ check_(
+ def_edition,
+ call_edition,
+ false,
+ decl,
+ arg,
+ true,
+ expect,
+ parser::TopEntryPoint::SourceFile,
+ );
+}
+
+#[test]
+fn token_mapping_smoke_test() {
+ check(
+ Edition::CURRENT,
+ Edition::CURRENT,
+ r#"
+( struct $ident:ident ) => {
+ struct $ident {
+ map: ::std::collections::HashSet<()>,
+ }
+};
+"#,
+ r#"
+struct MyTraitMap2
+"#,
+ expect![[r#"
+ IDENT struct 0:[email protected]#0
+ IDENT MyTraitMap2 1:[email protected]#0
+ IDENT map 0:[email protected]#0
+ PUNCH : [alone] 0:[email protected]#0
+ PUNCH : [joint] 0:[email protected]#0
+ PUNCH : [alone] 0:[email protected]#0
+ IDENT std 0:[email protected]#0
+ PUNCH : [joint] 0:[email protected]#0
+ PUNCH : [alone] 0:[email protected]#0
+ IDENT collections 0:[email protected]#0
+ PUNCH : [joint] 0:[email protected]#0
+ PUNCH : [alone] 0:[email protected]#0
+ IDENT HashSet 0:[email protected]#0
+ PUNCH < [alone] 0:[email protected]#0
+ PUNCH > [joint] 0:[email protected]#0
+ PUNCH , [alone] 0:[email protected]#0
+
+ struct MyTraitMap2 {
+ map: ::std::collections::HashSet<()>,
+ }"#]],
+ );
+}
+
+#[test]
+fn token_mapping_floats() {
+ // Regression test for https://github.com/rust-lang/rust-analyzer/issues/12216
+ // (and related issues)
+ check(
+ Edition::CURRENT,
+ Edition::CURRENT,
+ r#"
+($($tt:tt)*) => {
+ $($tt)*
+};
+"#,
+ r#"
+fn main() {
+ 1;
+ 1.0;
+ ((1,),).0.0;
+ let x = 1;
+}
+"#,
+ expect![[r#"
+ IDENT fn 1:[email protected]#0
+ IDENT main 1:[email protected]#0
+ LITERAL Integer 1 1:[email protected]#0
+ PUNCH ; [alone] 1:[email protected]#0
+ LITERAL Float 1.0 1:[email protected]#0
+ PUNCH ; [alone] 1:[email protected]#0
+ LITERAL Integer 1 1:[email protected]#0
+ PUNCH , [alone] 1:[email protected]#0
+ PUNCH , [alone] 1:[email protected]#0
+ PUNCH . [alone] 1:[email protected]#0
+ LITERAL Float 0.0 1:[email protected]#0
+ PUNCH ; [alone] 1:[email protected]#0
+ IDENT let 1:[email protected]#0
+ IDENT x 1:[email protected]#0
+ PUNCH = [alone] 1:[email protected]#0
+ LITERAL Integer 1 1:[email protected]#0
+ PUNCH ; [alone] 1:[email protected]#0
+
+ fn main(){
+ 1;
+ 1.0;
+ ((1,),).0.0;
+ let x = 1;
+ }"#]],
+ );
+}