Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/nameres/tests/macros.rs')
-rw-r--r--crates/hir-def/src/nameres/tests/macros.rs256
1 files changed, 241 insertions, 15 deletions
diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs
index a4ccd14cbb..f4cca8d68d 100644
--- a/crates/hir-def/src/nameres/tests/macros.rs
+++ b/crates/hir-def/src/nameres/tests/macros.rs
@@ -260,6 +260,72 @@ mod priv_mod {
}
#[test]
+fn macro_use_filter() {
+ check(
+ r#"
+//- /main.rs crate:main deps:empty,multiple,all
+#[macro_use()]
+extern crate empty;
+
+foo_not_imported!();
+
+#[macro_use(bar1)]
+#[macro_use()]
+#[macro_use(bar2, bar3)]
+extern crate multiple;
+
+bar1!();
+bar2!();
+bar3!();
+bar_not_imported!();
+
+#[macro_use(baz1)]
+#[macro_use]
+#[macro_use(baz2)]
+extern crate all;
+
+baz1!();
+baz2!();
+baz3!();
+
+//- /empty.rs crate:empty
+#[macro_export]
+macro_rules! foo_not_imported { () => { struct NotOkFoo; } }
+
+//- /multiple.rs crate:multiple
+#[macro_export]
+macro_rules! bar1 { () => { struct OkBar1; } }
+#[macro_export]
+macro_rules! bar2 { () => { struct OkBar2; } }
+#[macro_export]
+macro_rules! bar3 { () => { struct OkBar3; } }
+#[macro_export]
+macro_rules! bar_not_imported { () => { struct NotOkBar; } }
+
+//- /all.rs crate:all
+#[macro_export]
+macro_rules! baz1 { () => { struct OkBaz1; } }
+#[macro_export]
+macro_rules! baz2 { () => { struct OkBaz2; } }
+#[macro_export]
+macro_rules! baz3 { () => { struct OkBaz3; } }
+"#,
+ expect![[r#"
+ crate
+ OkBar1: t v
+ OkBar2: t v
+ OkBar3: t v
+ OkBaz1: t v
+ OkBaz2: t v
+ OkBaz3: t v
+ all: t
+ empty: t
+ multiple: t
+ "#]],
+ );
+}
+
+#[test]
fn prelude_is_macro_use() {
cov_mark::check!(prelude_is_macro_use);
check(
@@ -665,6 +731,29 @@ pub struct bar;
}
#[test]
+fn macro_dollar_crate_is_correct_in_derive_meta() {
+ let map = compute_crate_def_map(
+ r#"
+//- minicore: derive, clone
+//- /main.rs crate:main deps:lib
+lib::foo!();
+
+//- /lib.rs crate:lib
+#[macro_export]
+macro_rules! foo {
+ () => {
+ #[derive($crate::Clone)]
+ struct S;
+ }
+}
+
+pub use core::clone::Clone;
+"#,
+ );
+ assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1);
+}
+
+#[test]
fn expand_derive() {
let map = compute_crate_def_map(
r#"
@@ -683,7 +772,7 @@ pub macro Copy {}
pub macro Clone {}
"#,
);
- assert_eq!(map.modules[map.root].scope.impls().len(), 2);
+ assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 2);
}
#[test]
@@ -726,7 +815,7 @@ pub macro derive($item:item) {}
pub macro Clone {}
"#,
);
- assert_eq!(map.modules[map.root].scope.impls().len(), 1);
+ assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1);
}
#[test]
@@ -991,7 +1080,7 @@ macro_rules! mbe {
#[test]
fn collects_derive_helpers() {
- let def_map = compute_crate_def_map(
+ let db = TestDB::with_files(
r#"
#![crate_type="proc-macro"]
struct TokenStream;
@@ -1002,11 +1091,13 @@ pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
}
"#,
);
+ let krate = db.crate_graph().iter().next().unwrap();
+ let def_map = db.crate_def_map(krate);
- assert_eq!(def_map.exported_derives.len(), 1);
- match def_map.exported_derives.values().next() {
+ assert_eq!(def_map.data.exported_derives.len(), 1);
+ match def_map.data.exported_derives.values().next() {
Some(helpers) => match &**helpers {
- [attr] => assert_eq!(attr.to_string(), "helper_attr"),
+ [attr] => assert_eq!(attr.display(&db).to_string(), "helper_attr"),
_ => unreachable!(),
},
_ => unreachable!(),
@@ -1169,7 +1260,7 @@ struct A;
#[test]
fn macro_use_imports_all_macro_types() {
- let def_map = compute_crate_def_map(
+ let db = TestDB::with_files(
r#"
//- /main.rs crate:main deps:lib
#[macro_use]
@@ -1192,18 +1283,153 @@ struct TokenStream;
fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
"#,
);
+ let krate = db.crate_graph().iter().next().unwrap();
+ let def_map = db.crate_def_map(krate);
+
+ let root_module = &def_map[DefMap::ROOT].scope;
+ assert!(
+ root_module.legacy_macros().count() == 0,
+ "`#[macro_use]` shouldn't bring macros into textual macro scope",
+ );
- let root = &def_map[def_map.root()].scope;
- let actual = root
- .legacy_macros()
- .sorted_by(|a, b| std::cmp::Ord::cmp(&a.0, &b.0))
- .map(|(name, _)| format!("{name}\n"))
- .collect::<String>();
+ let actual = def_map
+ .macro_use_prelude
+ .iter()
+ .map(|(name, _)| name.display(&db).to_string())
+ .sorted()
+ .join("\n");
expect![[r#"
legacy
macro20
- proc_attr
- "#]]
+ proc_attr"#]]
.assert_eq(&actual);
}
+
+#[test]
+fn non_prelude_macros_take_precedence_over_macro_use_prelude() {
+ check(
+ r#"
+//- /lib.rs edition:2021 crate:lib deps:dep,core
+#[macro_use]
+extern crate dep;
+
+macro foo() { struct Ok; }
+macro bar() { fn ok() {} }
+
+foo!();
+bar!();
+
+//- /dep.rs crate:dep
+#[macro_export]
+macro_rules! foo {
+ () => { struct NotOk; }
+}
+
+//- /core.rs crate:core
+pub mod prelude {
+ pub mod rust_2021 {
+ #[macro_export]
+ macro_rules! bar {
+ () => { fn not_ok() {} }
+ }
+ }
+}
+ "#,
+ expect![[r#"
+ crate
+ Ok: t v
+ bar: m
+ dep: t
+ foo: m
+ ok: v
+ "#]],
+ );
+}
+
+#[test]
+fn macro_use_prelude_is_eagerly_expanded() {
+ // See FIXME in `ModCollector::collect_macro_call()`.
+ check(
+ r#"
+//- /main.rs crate:main deps:lib
+#[macro_use]
+extern crate lib;
+mk_foo!();
+mod a {
+ foo!();
+}
+//- /lib.rs crate:lib
+#[macro_export]
+macro_rules! mk_foo {
+ () => {
+ macro_rules! foo {
+ () => { struct Ok; }
+ }
+ }
+}
+ "#,
+ expect![[r#"
+ crate
+ a: t
+ lib: t
+
+ crate::a
+ Ok: t v
+ "#]],
+ );
+}
+
+#[test]
+fn macro_sub_namespace() {
+ let map = compute_crate_def_map(
+ r#"
+//- minicore: derive, clone
+macro_rules! Clone { () => {} }
+macro_rules! derive { () => {} }
+
+#[derive(Clone)]
+struct S;
+ "#,
+ );
+ assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1);
+}
+
+#[test]
+fn macro_sub_namespace2() {
+ check(
+ r#"
+//- /main.rs edition:2021 crate:main deps:proc,core
+use proc::{foo, bar};
+
+foo!();
+bar!();
+
+//- /proc.rs crate:proc
+#![crate_type="proc-macro"]
+#[proc_macro_derive(foo)]
+pub fn foo() {}
+#[proc_macro_attribute]
+pub fn bar() {}
+
+//- /core.rs crate:core
+pub mod prelude {
+ pub mod rust_2021 {
+ pub macro foo() {
+ struct Ok;
+ }
+ pub macro bar() {
+ fn ok() {}
+ }
+ }
+}
+ "#,
+ expect![[r#"
+ crate
+ Ok: t v
+ bar: m
+ foo: m
+ ok: v
+ "#]],
+ );
+}