diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs')
-rw-r--r-- | src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs | 933 |
1 files changed, 933 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs new file mode 100644 index 000000000..70dd2eb3a --- /dev/null +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs @@ -0,0 +1,933 @@ +mod globs; +mod incremental; +mod macros; +mod mod_resolution; +mod primitives; + +use std::sync::Arc; + +use base_db::{fixture::WithFixture, SourceDatabase}; +use expect_test::{expect, Expect}; + +use crate::{db::DefDatabase, test_db::TestDB}; + +use super::DefMap; + +fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { + let db = TestDB::with_files(ra_fixture); + let krate = db.crate_graph().iter().next().unwrap(); + db.crate_def_map(krate) +} + +fn render_crate_def_map(ra_fixture: &str) -> String { + let db = TestDB::with_files(ra_fixture); + let krate = db.crate_graph().iter().next().unwrap(); + db.crate_def_map(krate).dump(&db) +} + +fn check(ra_fixture: &str, expect: Expect) { + let actual = render_crate_def_map(ra_fixture); + expect.assert_eq(&actual); +} + +#[test] +fn crate_def_map_smoke_test() { + check( + r#" +//- /lib.rs +mod foo; +struct S; +use crate::foo::bar::E; +use self::E::V; + +//- /foo/mod.rs +pub mod bar; +fn f() {} + +//- /foo/bar.rs +pub struct Baz; + +union U { to_be: bool, not_to_be: u8 } +enum E { V } + +extern { + type Ext; + static EXT: u8; + fn ext(); +} +"#, + expect![[r#" + crate + E: t + S: t v + V: t v + foo: t + + crate::foo + bar: t + f: v + + crate::foo::bar + Baz: t v + E: t + EXT: v + Ext: t + U: t + ext: v + "#]], + ); +} + +#[test] +fn crate_def_map_super_super() { + check( + r#" +mod a { + const A: usize = 0; + mod b { + const B: usize = 0; + mod c { + use super::super::*; + } + } +} +"#, + expect![[r#" + crate + a: t + + crate::a + A: v + b: t + + crate::a::b + B: v + c: t + + crate::a::b::c + A: v + b: t + "#]], + ); +} + +#[test] +fn crate_def_map_fn_mod_same_name() { + check( + r#" +mod m { + pub mod z {} + pub fn z() {} +} +"#, + expect![[r#" + crate + m: t + + crate::m + z: t v + + crate::m::z + "#]], + ); +} + +#[test] +fn bogus_paths() { + cov_mark::check!(bogus_paths); + check( + r#" +//- /lib.rs +mod foo; +struct S; +use self; + +//- /foo/mod.rs +use super; +use crate; +"#, + expect![[r#" + crate + S: t v + foo: t + + crate::foo + "#]], + ); +} + +#[test] +fn use_as() { + check( + r#" +//- /lib.rs +mod foo; +use crate::foo::Baz as Foo; + +//- /foo/mod.rs +pub struct Baz; +"#, + expect![[r#" + crate + Foo: t v + foo: t + + crate::foo + Baz: t v + "#]], + ); +} + +#[test] +fn use_trees() { + check( + r#" +//- /lib.rs +mod foo; +use crate::foo::bar::{Baz, Quux}; + +//- /foo/mod.rs +pub mod bar; + +//- /foo/bar.rs +pub struct Baz; +pub enum Quux {}; +"#, + expect![[r#" + crate + Baz: t v + Quux: t + foo: t + + crate::foo + bar: t + + crate::foo::bar + Baz: t v + Quux: t + "#]], + ); +} + +#[test] +fn re_exports() { + check( + r#" +//- /lib.rs +mod foo; +use self::foo::Baz; + +//- /foo/mod.rs +pub mod bar; +pub use self::bar::Baz; + +//- /foo/bar.rs +pub struct Baz; +"#, + expect![[r#" + crate + Baz: t v + foo: t + + crate::foo + Baz: t v + bar: t + + crate::foo::bar + Baz: t v + "#]], + ); +} + +#[test] +fn std_prelude() { + cov_mark::check!(std_prelude); + check( + r#" +//- /main.rs crate:main deps:test_crate +#[prelude_import] +use ::test_crate::prelude::*; + +use Foo::*; + +//- /lib.rs crate:test_crate +pub mod prelude; + +//- /prelude.rs +pub enum Foo { Bar, Baz } +"#, + expect![[r#" + crate + Bar: t v + Baz: t v + "#]], + ); +} + +#[test] +fn can_import_enum_variant() { + cov_mark::check!(can_import_enum_variant); + check( + r#" +enum E { V } +use self::E::V; +"#, + expect![[r#" + crate + E: t + V: t v + "#]], + ); +} + +#[test] +fn edition_2015_imports() { + check( + r#" +//- /main.rs crate:main deps:other_crate edition:2015 +mod foo; +mod bar; + +//- /bar.rs +struct Bar; + +//- /foo.rs +use bar::Bar; +use other_crate::FromLib; + +//- /lib.rs crate:other_crate edition:2018 +pub struct FromLib; +"#, + expect![[r#" + crate + bar: t + foo: t + + crate::bar + Bar: t v + + crate::foo + Bar: t v + FromLib: t v + "#]], + ); +} + +#[test] +fn item_map_using_self() { + check( + r#" +//- /lib.rs +mod foo; +use crate::foo::bar::Baz::{self}; + +//- /foo/mod.rs +pub mod bar; + +//- /foo/bar.rs +pub struct Baz; +"#, + expect![[r#" + crate + Baz: t + foo: t + + crate::foo + bar: t + + crate::foo::bar + Baz: t v + "#]], + ); +} + +#[test] +fn item_map_across_crates() { + check( + r#" +//- /main.rs crate:main deps:test_crate +use test_crate::Baz; + +//- /lib.rs crate:test_crate +pub struct Baz; +"#, + expect![[r#" + crate + Baz: t v + "#]], + ); +} + +#[test] +fn extern_crate_rename() { + check( + r#" +//- /main.rs crate:main deps:alloc +extern crate alloc as alloc_crate; +mod alloc; +mod sync; + +//- /sync.rs +use alloc_crate::Arc; + +//- /lib.rs crate:alloc +pub struct Arc; +"#, + expect![[r#" + crate + alloc: t + alloc_crate: t + sync: t + + crate::alloc + + crate::sync + Arc: t v + "#]], + ); +} + +#[test] +fn extern_crate_rename_2015_edition() { + check( + r#" +//- /main.rs crate:main deps:alloc edition:2015 +extern crate alloc as alloc_crate; +mod alloc; +mod sync; + +//- /sync.rs +use alloc_crate::Arc; + +//- /lib.rs crate:alloc +pub struct Arc; +"#, + expect![[r#" + crate + alloc: t + alloc_crate: t + sync: t + + crate::alloc + + crate::sync + Arc: t v + "#]], + ); +} + +#[test] +fn macro_use_extern_crate_self() { + cov_mark::check!(ignore_macro_use_extern_crate_self); + check( + r#" +//- /main.rs crate:main +#[macro_use] +extern crate self as bla; +"#, + expect![[r#" + crate + bla: t + "#]], + ); +} + +#[test] +fn reexport_across_crates() { + check( + r#" +//- /main.rs crate:main deps:test_crate +use test_crate::Baz; + +//- /lib.rs crate:test_crate +pub use foo::Baz; +mod foo; + +//- /foo.rs +pub struct Baz; +"#, + expect![[r#" + crate + Baz: t v + "#]], + ); +} + +#[test] +fn values_dont_shadow_extern_crates() { + check( + r#" +//- /main.rs crate:main deps:foo +fn foo() {} +use foo::Bar; + +//- /foo/lib.rs crate:foo +pub struct Bar; +"#, + expect![[r#" + crate + Bar: t v + foo: v + "#]], + ); +} + +#[test] +fn no_std_prelude() { + check( + r#" + //- /main.rs crate:main deps:core,std + #![cfg_attr(not(never), no_std)] + use Rust; + + //- /core.rs crate:core + pub mod prelude { + pub mod rust_2018 { + pub struct Rust; + } + } + //- /std.rs crate:std deps:core + pub mod prelude { + pub mod rust_2018 { + } + } + "#, + expect![[r#" + crate + Rust: t v + "#]], + ); +} + +#[test] +fn edition_specific_preludes() { + // We can't test the 2015 prelude here since you can't reexport its contents with 2015's + // absolute paths. + + check( + r#" + //- /main.rs edition:2018 crate:main deps:std + use Rust2018; + + //- /std.rs crate:std + pub mod prelude { + pub mod rust_2018 { + pub struct Rust2018; + } + } + "#, + expect![[r#" + crate + Rust2018: t v + "#]], + ); + check( + r#" + //- /main.rs edition:2021 crate:main deps:std + use Rust2021; + + //- /std.rs crate:std + pub mod prelude { + pub mod rust_2021 { + pub struct Rust2021; + } + } + "#, + expect![[r#" + crate + Rust2021: t v + "#]], + ); +} + +#[test] +fn std_prelude_takes_precedence_above_core_prelude() { + check( + r#" +//- /main.rs crate:main deps:core,std +use {Foo, Bar}; + +//- /std.rs crate:std deps:core +pub mod prelude { + pub mod rust_2018 { + pub struct Foo; + pub use core::prelude::rust_2018::Bar; + } +} + +//- /core.rs crate:core +pub mod prelude { + pub mod rust_2018 { + pub struct Bar; + } +} +"#, + expect![[r#" + crate + Bar: t v + Foo: t v + "#]], + ); +} + +#[test] +fn cfg_not_test() { + check( + r#" +//- /main.rs crate:main deps:std +use {Foo, Bar, Baz}; + +//- /lib.rs crate:std +pub mod prelude { + pub mod rust_2018 { + #[cfg(test)] + pub struct Foo; + #[cfg(not(test))] + pub struct Bar; + #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] + pub struct Baz; + } +} +"#, + expect![[r#" + crate + Bar: t v + Baz: _ + Foo: _ + "#]], + ); +} + +#[test] +fn cfg_test() { + check( + r#" +//- /main.rs crate:main deps:std +use {Foo, Bar, Baz}; + +//- /lib.rs crate:std cfg:test,feature=foo,feature=bar,opt=42 +pub mod prelude { + pub mod rust_2018 { + #[cfg(test)] + pub struct Foo; + #[cfg(not(test))] + pub struct Bar; + #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))] + pub struct Baz; + } +} +"#, + expect![[r#" + crate + Bar: _ + Baz: t v + Foo: t v + "#]], + ); +} + +#[test] +fn infer_multiple_namespace() { + check( + r#" +//- /main.rs +mod a { + pub type T = (); + pub use crate::b::*; +} + +use crate::a::T; + +mod b { + pub const T: () = (); +} +"#, + expect![[r#" + crate + T: t v + a: t + b: t + + crate::a + T: t v + + crate::b + T: v + "#]], + ); +} + +#[test] +fn underscore_import() { + check( + r#" +//- /main.rs +use tr::Tr as _; +use tr::Tr2 as _; + +mod tr { + pub trait Tr {} + pub trait Tr2 {} +} + "#, + expect![[r#" + crate + _: t + _: t + tr: t + + crate::tr + Tr: t + Tr2: t + "#]], + ); +} + +#[test] +fn underscore_reexport() { + check( + r#" +//- /main.rs +mod tr { + pub trait PubTr {} + pub trait PrivTr {} +} +mod reex { + use crate::tr::PrivTr as _; + pub use crate::tr::PubTr as _; +} +use crate::reex::*; + "#, + expect![[r#" + crate + _: t + reex: t + tr: t + + crate::reex + _: t + _: t + + crate::tr + PrivTr: t + PubTr: t + "#]], + ); +} + +#[test] +fn underscore_pub_crate_reexport() { + cov_mark::check!(upgrade_underscore_visibility); + check( + r#" +//- /main.rs crate:main deps:lib +use lib::*; + +//- /lib.rs crate:lib +use tr::Tr as _; +pub use tr::Tr as _; + +mod tr { + pub trait Tr {} +} + "#, + expect![[r#" + crate + _: t + "#]], + ); +} + +#[test] +fn underscore_nontrait() { + check( + r#" +//- /main.rs +mod m { + pub struct Struct; + pub enum Enum {} + pub const CONST: () = (); +} +use crate::m::{Struct as _, Enum as _, CONST as _}; + "#, + expect![[r#" + crate + m: t + + crate::m + CONST: v + Enum: t + Struct: t v + "#]], + ); +} + +#[test] +fn underscore_name_conflict() { + check( + r#" +//- /main.rs +struct Tr; + +use tr::Tr as _; + +mod tr { + pub trait Tr {} +} + "#, + expect![[r#" + crate + _: t + Tr: t v + tr: t + + crate::tr + Tr: t + "#]], + ); +} + +#[test] +fn cfg_the_entire_crate() { + check( + r#" +//- /main.rs +#![cfg(never)] + +pub struct S; +pub enum E {} +pub fn f() {} + "#, + expect![[r#" + crate + "#]], + ); +} + +#[test] +fn use_crate_as() { + check( + r#" +use crate as foo; + +use foo::bar as baz; + +fn bar() {} + "#, + expect![[r#" + crate + bar: v + baz: v + foo: t + "#]], + ); +} + +#[test] +fn self_imports_only_types() { + check( + r#" +//- /main.rs +mod m { + pub macro S() {} + pub struct S; +} + +use self::m::S::{self}; + "#, + expect![[r#" + crate + S: t + m: t + + crate::m + S: t v m + "#]], + ); +} + +#[test] +fn import_from_extern_crate_only_imports_public_items() { + check( + r#" +//- /lib.rs crate:lib deps:settings,macros +use macros::settings; +use settings::Settings; +//- /settings.rs crate:settings +pub struct Settings; +//- /macros.rs crate:macros +mod settings {} +pub const settings: () = (); + "#, + expect![[r#" + crate + Settings: t v + settings: v + "#]], + ) +} + +#[test] +fn non_prelude_deps() { + check( + r#" +//- /lib.rs crate:lib deps:dep extern-prelude: +use dep::Struct; +//- /dep.rs crate:dep +pub struct Struct; + "#, + expect![[r#" + crate + Struct: _ + "#]], + ); + check( + r#" +//- /lib.rs crate:lib deps:dep extern-prelude: +extern crate dep; +use dep::Struct; +//- /dep.rs crate:dep +pub struct Struct; + "#, + expect![[r#" + crate + Struct: t v + dep: t + "#]], + ); +} + +#[test] +fn braced_supers_in_use_tree() { + cov_mark::check!(concat_super_mod_paths); + check( + r#" +mod some_module { + pub fn unknown_func() {} +} + +mod other_module { + mod some_submodule { + use { super::{ super::unknown_func, }, }; + } +} + +use some_module::unknown_func; + "#, + expect![[r#" + crate + other_module: t + some_module: t + unknown_func: v + + crate::other_module + some_submodule: t + + crate::other_module::some_submodule + unknown_func: v + + crate::some_module + unknown_func: v + "#]], + ) +} |