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