From 71e5adf694a4b253bc5bb48be96bb6ba08002d8c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Mar 2019 11:53:40 +0300 Subject: move tests over to crate-def-map --- crates/ra_hir/src/marks.rs | 2 +- crates/ra_hir/src/nameres.rs | 5 +- crates/ra_hir/src/nameres/crate_def_map.rs | 2 +- .../ra_hir/src/nameres/crate_def_map/collector.rs | 15 +- crates/ra_hir/src/nameres/crate_def_map/tests.rs | 411 +++++++++-- .../src/nameres/crate_def_map/tests/globs.rs | 118 ++++ .../src/nameres/crate_def_map/tests/incremental.rs | 123 ++++ .../src/nameres/crate_def_map/tests/macros.rs | 94 +++ crates/ra_hir/src/nameres/tests.rs | 769 --------------------- 9 files changed, 689 insertions(+), 850 deletions(-) create mode 100644 crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs create mode 100644 crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs create mode 100644 crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs delete mode 100644 crates/ra_hir/src/nameres/tests.rs diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs index 16852a6a1..e8f3005f1 100644 --- a/crates/ra_hir/src/marks.rs +++ b/crates/ra_hir/src/marks.rs @@ -1,6 +1,6 @@ test_utils::marks!( name_res_works_for_broken_modules - item_map_enum_importing + can_import_enum_variant type_var_cycles_resolve_completely type_var_cycles_resolve_as_possible type_var_resolves_to_int_var diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index baffbce6f..59297425e 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -661,7 +661,7 @@ impl ItemMap { } ModuleDef::Enum(e) => { // enum variant - tested_by!(item_map_enum_importing); + tested_by!(can_import_enum_variant); match e.variant(db, &segment.name) { Some(variant) => PerNs::both(variant.into(), variant.into()), None => { @@ -693,6 +693,3 @@ impl ItemMap { ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) } } - -#[cfg(test)] -mod tests; diff --git a/crates/ra_hir/src/nameres/crate_def_map.rs b/crates/ra_hir/src/nameres/crate_def_map.rs index d7ccb6584..37b36719f 100644 --- a/crates/ra_hir/src/nameres/crate_def_map.rs +++ b/crates/ra_hir/src/nameres/crate_def_map.rs @@ -273,7 +273,7 @@ impl CrateDefMap { } ModuleDef::Enum(e) => { // enum variant - tested_by!(item_map_enum_importing); + tested_by!(can_import_enum_variant); match e.variant(db, &segment.name) { Some(variant) => PerNs::both(variant.into(), variant.into()), None => { diff --git a/crates/ra_hir/src/nameres/crate_def_map/collector.rs b/crates/ra_hir/src/nameres/crate_def_map/collector.rs index 2fbfa9e34..68f74b866 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/collector.rs +++ b/crates/ra_hir/src/nameres/crate_def_map/collector.rs @@ -85,6 +85,12 @@ where break; } } + + let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); + // show unresolved imports in completion, etc + for (module_id, import, import_data) in unresolved_imports { + self.record_resolved_import(module_id, PerNs::none(), import, &import_data) + } } fn define_macro(&mut self, name: Name, tt: &tt::Subtree, export: bool) { @@ -415,7 +421,14 @@ where modules[res].parent = Some(self.module_id); modules[res].declaration = Some(declaration); modules[res].definition = definition; - modules[self.module_id].children.insert(name, res); + modules[self.module_id].children.insert(name.clone(), res); + let resolution = Resolution { + def: PerNs::types( + Module { krate: self.def_collector.def_map.krate, module_id: res }.into(), + ), + import: None, + }; + self.def_collector.update(self.module_id, None, &[(name, resolution)]); res } diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests.rs b/crates/ra_hir/src/nameres/crate_def_map/tests.rs index 742a19e5c..36c1d74ce 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/tests.rs +++ b/crates/ra_hir/src/nameres/crate_def_map/tests.rs @@ -1,3 +1,7 @@ +mod macros; +mod globs; +mod incremental; + use std::sync::Arc; use ra_db::SourceDatabase; @@ -62,6 +66,8 @@ fn crate_def_map_smoke_test() { //- /lib.rs mod foo; struct S; + use crate::foo::bar::E; + use self::E::V; //- /foo/mod.rs pub mod bar; @@ -74,9 +80,13 @@ fn crate_def_map_smoke_test() { ); assert_snapshot_matches!(map, @r###" crate +V: t v +E: t +foo: t S: t v crate::foo +bar: t f: v crate::foo::bar @@ -87,91 +97,96 @@ E: t } #[test] -fn macro_rules_are_globally_visible() { +fn use_as() { let map = def_map( " //- /lib.rs - macro_rules! structs { - ($($i:ident),*) => { - $(struct $i { field: u32 } )* - } - } - structs!(Foo); - mod nested; + mod foo; + + use crate::foo::Baz as Foo; - //- /nested.rs - structs!(Bar, Baz); + //- /foo/mod.rs + pub struct Baz; ", ); - assert_snapshot_matches!(map, @r###" + assert_snapshot_matches!(map, + @r###" crate Foo: t v +foo: t -crate::nested -Bar: t v +crate::foo Baz: t v -"###); +"### + ); } #[test] -fn macro_rules_can_define_modules() { +fn use_trees() { let map = def_map( " //- /lib.rs - macro_rules! m { - ($name:ident) => { mod $name; } - } - m!(n1); + mod foo; + + use crate::foo::bar::{Baz, Quux}; + + //- /foo/mod.rs + pub mod bar; - //- /n1.rs - m!(n2) - //- /n1/n2.rs - struct X; + //- /foo/bar.rs + pub struct Baz; + pub enum Quux {}; ", ); - assert_snapshot_matches!(map, @r###" + assert_snapshot_matches!(map, + @r###" crate +Quux: t +Baz: t v +foo: t -crate::n1 +crate::foo +bar: t -crate::n1::n2 -X: t v -"###); +crate::foo::bar +Quux: t +Baz: t v +"### + ); } #[test] -fn macro_rules_from_other_crates_are_visible() { - let map = def_map_with_crate_graph( +fn re_exports() { + let map = def_map( " - //- /main.rs - foo::structs!(Foo, Bar) - mod bar; + //- /lib.rs + mod foo; - //- /bar.rs - use crate::*; + use self::foo::Baz; - //- /lib.rs - #[macro_export] - macro_rules! structs { - ($($i:ident),*) => { - $(struct $i { field: u32 } )* - } - } + //- /foo/mod.rs + pub mod bar; + + pub use self::bar::Baz; + + //- /foo/bar.rs + pub struct Baz; ", - crate_graph! { - "main": ("/main.rs", ["foo"]), - "foo": ("/lib.rs", []), - }, ); - assert_snapshot_matches!(map, @r###" + assert_snapshot_matches!(map, + @r###" crate -Foo: t v -Bar: t v +Baz: t v +foo: t -crate::bar -Foo: t v -Bar: t v -"###); +crate::foo +bar: t +Baz: t v + +crate::foo::bar +Baz: t v +"### + ); } #[test] @@ -203,12 +218,152 @@ Baz: t v } #[test] -fn glob_across_crates() { - covers!(glob_across_crates); +fn can_import_enum_variant() { + covers!(can_import_enum_variant); + let map = def_map( + " + //- /lib.rs + enum E { V } + use self::E::V; + ", + ); + assert_snapshot_matches!(map, @r###" +crate +V: t v +E: t +"### + ); +} + +#[test] +fn edition_2015_imports() { + let map = def_map_with_crate_graph( + " + //- /main.rs + mod foo; + mod bar; + + //- /bar.rs + struct Bar; + + //- /foo.rs + use bar::Bar; + use other_crate::FromLib; + + //- /lib.rs + struct FromLib; + ", + crate_graph! { + "main": ("/main.rs", "2015", ["other_crate"]), + "other_crate": ("/lib.rs", "2018", []), + }, + ); + + assert_snapshot_matches!(map, + @r###" +crate +bar: t +foo: t + +crate::bar +Bar: t v + +crate::foo +FromLib: t v +Bar: t v +"### + ); +} + +#[test] +fn module_resolution_works_for_non_standard_filenames() { + let map = def_map_with_crate_graph( + " + //- /my_library.rs + mod foo; + use self::foo::Bar; + + //- /foo/mod.rs + pub struct Bar; + ", + crate_graph! { + "my_library": ("/my_library.rs", []), + }, + ); + + assert_snapshot_matches!(map, + @r###" +crate +Bar: t v +foo: t + +crate::foo +Bar: t v +"### + ); +} + +#[test] +fn name_res_works_for_broken_modules() { + covers!(name_res_works_for_broken_modules); + let map = def_map( + " + //- /lib.rs + mod foo // no `;`, no body + + use self::foo::Baz; + + //- /foo/mod.rs + pub mod bar; + + pub use self::bar::Baz; + + //- /foo/bar.rs + pub struct Baz; + ", + ); + assert_snapshot_matches!(map, + @r###" +crate +Baz: _ +"### + ); +} + +#[test] +fn item_map_using_self() { + let map = def_map( + " + //- /lib.rs + mod foo; + use crate::foo::bar::Baz::{self}; + //- /foo/mod.rs + pub mod bar; + //- /foo/bar.rs + pub struct Baz; + ", + ); + assert_snapshot_matches!(map, + @r###" +crate +Baz: t v +foo: t + +crate::foo +bar: t + +crate::foo::bar +Baz: t v +"### + ); +} + +#[test] +fn item_map_across_crates() { let map = def_map_with_crate_graph( " //- /main.rs - use test_crate::*; + use test_crate::Baz; //- /lib.rs pub struct Baz; @@ -218,7 +373,9 @@ fn glob_across_crates() { "test_crate": ("/lib.rs", []), }, ); - assert_snapshot_matches!(map, @r###" + + assert_snapshot_matches!(map, + @r###" crate Baz: t v "### @@ -226,40 +383,146 @@ Baz: t v } #[test] -fn item_map_enum_importing() { - covers!(item_map_enum_importing); - let map = def_map( +fn extern_crate_rename() { + let map = def_map_with_crate_graph( " + //- /main.rs + extern crate alloc as alloc_crate; + + mod alloc; + mod sync; + + //- /sync.rs + use alloc_crate::Arc; + //- /lib.rs - enum E { V } - use self::E::V; + struct Arc; ", + crate_graph! { + "main": ("/main.rs", ["alloc"]), + "alloc": ("/lib.rs", []), + }, ); - assert_snapshot_matches!(map, @r###" + + assert_snapshot_matches!(map, + @r###" crate -V: t v -E: t +Arc: t v "### ); } #[test] -fn glob_enum() { - covers!(glob_enum); - let map = def_map( +fn extern_crate_rename_2015_edition() { + let map = def_map_with_crate_graph( + " + //- /main.rs + extern crate alloc as alloc_crate; + + mod alloc; + mod sync; + + //- /sync.rs + use alloc_crate::Arc; + + //- /lib.rs + struct Arc; + ", + crate_graph! { + "main": ("/main.rs", "2015", ["alloc"]), + "alloc": ("/lib.rs", []), + }, + ); + + assert_snapshot_matches!(map, + @r###" +crate +Arc: t v +"### + ); +} + +#[test] +fn import_across_source_roots() { + let map = def_map_with_crate_graph( " //- /lib.rs - enum Foo { - Bar, Baz + pub mod a { + pub mod b { + pub struct C; + } } - use self::Foo::*; + + //- root /main/ + + //- /main/main.rs + use test_crate::a::b::C; ", + crate_graph! { + "main": ("/main/main.rs", ["test_crate"]), + "test_crate": ("/lib.rs", []), + }, ); - assert_snapshot_matches!(map, @r###" + + assert_snapshot_matches!(map, + @r###" +crate +C: t v +"### + ); +} + +#[test] +fn reexport_across_crates() { + let map = def_map_with_crate_graph( + " + //- /main.rs + use test_crate::Baz; + + //- /lib.rs + pub use foo::Baz; + + mod foo; + + //- /foo.rs + pub struct Baz; + ", + crate_graph! { + "main": ("/main.rs", ["test_crate"]), + "test_crate": ("/lib.rs", []), + }, + ); + + assert_snapshot_matches!(map, + @r###" crate -Foo: t -Bar: t v Baz: t v "### ); } + +#[test] +fn values_dont_shadow_extern_crates() { + let map = def_map_with_crate_graph( + " + //- /main.rs + fn foo() {} + use foo::Bar; + + //- /foo/lib.rs + pub struct Bar; + ", + crate_graph! { + "main": ("/main.rs", ["foo"]), + "foo": ("/foo/lib.rs", []), + }, + ); + + assert_snapshot_matches!(map, + @r###" +crate +Bar: t v +foo: v +"### + ); +} diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs b/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs new file mode 100644 index 000000000..6e50c7ff6 --- /dev/null +++ b/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs @@ -0,0 +1,118 @@ +use super::*; + +#[test] +fn glob_1() { + let map = def_map( + " + //- /lib.rs + mod foo; + use foo::*; + + //- /foo/mod.rs + pub mod bar; + pub use self::bar::Baz; + pub struct Foo; + + //- /foo/bar.rs + pub struct Baz; + ", + ); + assert_snapshot_matches!(map, @r###" +crate +bar: t +Foo: t v +Baz: t v +foo: t + +crate::foo +bar: t +Foo: t v +Baz: t v + +crate::foo::bar +Baz: t v +"### + ); +} + +#[test] +fn glob_2() { + let map = def_map( + " + //- /lib.rs + mod foo; + use foo::*; + + //- /foo/mod.rs + pub mod bar; + pub use self::bar::*; + pub struct Foo; + + //- /foo/bar.rs + pub struct Baz; + pub use super::*; + ", + ); + assert_snapshot_matches!(map, @r###" +crate +bar: t +Foo: t v +Baz: t v +foo: t + +crate::foo +bar: t +Foo: t v +Baz: t v + +crate::foo::bar +bar: t +Foo: t v +Baz: t v +"### + ); +} + +#[test] +fn glob_across_crates() { + covers!(glob_across_crates); + let map = def_map_with_crate_graph( + " + //- /main.rs + use test_crate::*; + + //- /lib.rs + pub struct Baz; + ", + crate_graph! { + "main": ("/main.rs", ["test_crate"]), + "test_crate": ("/lib.rs", []), + }, + ); + assert_snapshot_matches!(map, @r###" +crate +Baz: t v +"### + ); +} + +#[test] +fn glob_enum() { + covers!(glob_enum); + let map = def_map( + " + //- /lib.rs + enum Foo { + Bar, Baz + } + use self::Foo::*; + ", + ); + assert_snapshot_matches!(map, @r###" +crate +Foo: t +Bar: t v +Baz: t v +"### + ); +} diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs b/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs new file mode 100644 index 000000000..698781923 --- /dev/null +++ b/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs @@ -0,0 +1,123 @@ +use super::*; + +use std::sync::Arc; + +use ra_db::SourceDatabase; + +fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) { + let (mut db, pos) = MockDatabase::with_position(initial); + let crate_id = db.crate_graph().iter().next().unwrap(); + let krate = Crate { crate_id }; + { + let events = db.log_executed(|| { + db.crate_def_map(krate); + }); + assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) + } + db.set_file_text(pos.file_id, Arc::new(file_change.to_string())); + + { + let events = db.log_executed(|| { + db.crate_def_map(krate); + }); + assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) + } +} + +#[test] +fn typing_inside_a_function_should_not_invalidate_def_map() { + check_def_map_is_not_recomputed( + " + //- /lib.rs + mod foo;<|> + + use crate::foo::bar::Baz; + + fn foo() -> i32 { + 1 + 1 + } + //- /foo/mod.rs + pub mod bar; + + //- /foo/bar.rs + pub struct Baz; + ", + " + mod foo; + + use crate::foo::bar::Baz; + + fn foo() -> i32 { 92 } + ", + ); +} + +#[test] +fn adding_inner_items_should_not_invalidate_def_map() { + check_def_map_is_not_recomputed( + " + //- /lib.rs + struct S { a: i32} + enum E { A } + trait T { + fn a() {} + } + mod foo;<|> + impl S { + fn a() {} + } + use crate::foo::bar::Baz; + //- /foo/mod.rs + pub mod bar; + + //- /foo/bar.rs + pub struct Baz; + ", + " + struct S { a: i32, b: () } + enum E { A, B } + trait T { + fn a() {} + fn b() {} + } + mod foo;<|> + impl S { + fn a() {} + fn b() {} + } + use crate::foo::bar::Baz; + ", + ); +} + +// It would be awesome to make this work, but it's unclear how +#[test] +#[ignore] +fn typing_inside_a_function_inside_a_macro_should_not_invalidate_def_map() { + check_def_map_is_not_recomputed( + " + //- /lib.rs + mod foo; + + use crate::foo::bar::Baz; + + //- /foo/mod.rs + pub mod bar; + + //- /foo/bar.rs + <|> + salsa::query_group! { + trait Baz { + fn foo() -> i32 { 1 + 1 } + } + } + ", + " + salsa::query_group! { + trait Baz { + fn foo() -> i32 { 92 } + } + } + ", + ); +} diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs b/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs new file mode 100644 index 000000000..8781b026b --- /dev/null +++ b/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs @@ -0,0 +1,94 @@ +use super::*; + +#[test] +fn macro_rules_are_globally_visible() { + let map = def_map( + " + //- /lib.rs + macro_rules! structs { + ($($i:ident),*) => { + $(struct $i { field: u32 } )* + } + } + structs!(Foo); + mod nested; + + //- /nested.rs + structs!(Bar, Baz); + ", + ); + assert_snapshot_matches!(map, @r###" +crate +nested: t +Foo: t v + +crate::nested +Bar: t v +Baz: t v +"###); +} + +#[test] +fn macro_rules_can_define_modules() { + let map = def_map( + " + //- /lib.rs + macro_rules! m { + ($name:ident) => { mod $name; } + } + m!(n1); + + //- /n1.rs + m!(n2) + //- /n1/n2.rs + struct X; + ", + ); + assert_snapshot_matches!(map, @r###" +crate +n1: t + +crate::n1 +n2: t + +crate::n1::n2 +X: t v +"###); +} + +#[test] +fn macro_rules_from_other_crates_are_visible() { + let map = def_map_with_crate_graph( + " + //- /main.rs + foo::structs!(Foo, Bar) + mod bar; + + //- /bar.rs + use crate::*; + + //- /lib.rs + #[macro_export] + macro_rules! structs { + ($($i:ident),*) => { + $(struct $i { field: u32 } )* + } + } + ", + crate_graph! { + "main": ("/main.rs", ["foo"]), + "foo": ("/lib.rs", []), + }, + ); + assert_snapshot_matches!(map, @r###" +crate +bar: t +Foo: t v +Bar: t v + +crate::bar +bar: t +Foo: t v +Bar: t v +"###); +} diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs deleted file mode 100644 index 961e442a9..000000000 --- a/crates/ra_hir/src/nameres/tests.rs +++ /dev/null @@ -1,769 +0,0 @@ -use std::sync::Arc; - -use ra_db::SourceDatabase; -use test_utils::{assert_eq_text, covers}; - -use crate::{ - ItemMap, - PersistentHirDatabase, - mock::MockDatabase, - nameres::crate_def_map::ModuleId, -}; -use super::Resolution; - -fn item_map(fixture: &str) -> (Arc, ModuleId) { - let (db, pos) = MockDatabase::with_position(fixture); - let module = crate::source_binder::module_from_position(&db, pos).unwrap(); - let krate = module.krate(&db).unwrap(); - let module_id = module.module_id; - (db.item_map(krate), module_id) -} - -fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { - let mut lines = map[module_id] - .items - .iter() - .map(|(name, res)| format!("{}: {}", name, dump_resolution(res))) - .collect::>(); - lines.sort(); - let actual = lines.join("\n"); - let expected = expected.trim().lines().map(|it| it.trim()).collect::>().join("\n"); - assert_eq_text!(&expected, &actual); - - fn dump_resolution(resolution: &Resolution) -> &'static str { - match (resolution.def.types.is_some(), resolution.def.values.is_some()) { - (true, true) => "t v", - (true, false) => "t", - (false, true) => "v", - (false, false) => "_", - } - } -} - -#[test] -fn item_map_smoke_test() { - let (item_map, module_id) = item_map( - " - //- /lib.rs - mod foo; - - use crate::foo::bar::Baz; - <|> - - //- /foo/mod.rs - pub mod bar; - - //- /foo/bar.rs - pub struct Baz; - ", - ); - check_module_item_map( - &item_map, - module_id, - " - Baz: t v - foo: t - ", - ); -} - -#[test] -fn use_as() { - let (item_map, module_id) = item_map( - " - //- /lib.rs - mod foo; - - use crate::foo::Baz as Foo; - <|> - - //- /foo/mod.rs - pub struct Baz; - ", - ); - check_module_item_map( - &item_map, - module_id, - " - Foo: t v - foo: t - ", - ); -} - -#[test] -fn use_trees() { - let (item_map, module_id) = item_map( - " - //- /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 {}; - ", - ); - check_module_item_map( - &item_map, - module_id, - " - Baz: t v - Quux: t - foo: t - ", - ); -} - -#[test] -fn re_exports() { - let (item_map, module_id) = item_map( - " - //- /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; - ", - ); - check_module_item_map( - &item_map, - module_id, - " - Baz: t v - foo: t - ", - ); -} - -#[test] -fn glob_1() { - let (item_map, module_id) = item_map( - " - //- /lib.rs - mod foo; - use foo::*; - <|> - - //- /foo/mod.rs - pub mod bar; - pub use self::bar::Baz; - pub struct Foo; - - //- /foo/bar.rs - pub struct Baz; - ", - ); - check_module_item_map( - &item_map, - module_id, - " - Baz: t v - Foo: t v - bar: t - foo: t - ", - ); -} - -#[test] -fn glob_2() { - let (item_map, module_id) = item_map( - " - //- /lib.rs - mod foo; - use foo::*; - <|> - - //- /foo/mod.rs - pub mod bar; - pub use self::bar::*; - pub struct Foo; - - //- /foo/bar.rs - pub struct Baz; - pub use super::*; - ", - ); - check_module_item_map( - &item_map, - module_id, - " - Baz: t v - Foo: t v - bar: t - foo: t - ", - ); -} - -#[test] -fn glob_enum() { - covers!(glob_enum); - let (item_map, module_id) = item_map( - " - //- /lib.rs - enum Foo { - Bar, Baz - } - use self::Foo::*; - <|> - ", - ); - check_module_item_map( - &item_map, - module_id, - " - Bar: t v - Baz: t v - Foo: t - ", - ); -} - -#[test] -fn glob_across_crates() { - covers!(glob_across_crates); - let mut db = MockDatabase::with_files( - " - //- /main.rs - use test_crate::*; - - //- /lib.rs - pub struct Baz; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "main": ("/main.rs", ["test_crate"]), - "test_crate": ("/lib.rs", []), - }); - let main_id = db.file_id_of("/main.rs"); - - let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let krate = module.krate(&db).unwrap(); - let item_map = db.item_map(krate); - - check_module_item_map( - &item_map, - module.module_id, - " - Baz: t v - ", - ); -} - -#[test] -fn edition_2015_imports() { - let mut db = MockDatabase::with_files( - " - //- /main.rs - mod foo; - mod bar; - - //- /bar.rs - struct Bar; - - //- /foo.rs - use bar::Bar; - use other_crate::FromLib; - - //- /lib.rs - struct FromLib; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "main": ("/main.rs", "2015", ["other_crate"]), - "other_crate": ("/lib.rs", "2018", []), - }); - let foo_id = db.file_id_of("/foo.rs"); - - let module = crate::source_binder::module_from_file_id(&db, foo_id).unwrap(); - let krate = module.krate(&db).unwrap(); - let item_map = db.item_map(krate); - - check_module_item_map( - &item_map, - module.module_id, - " - Bar: t v - FromLib: t v - ", - ); -} - -#[test] -fn module_resolution_works_for_non_standard_filenames() { - let mut db = MockDatabase::with_files( - " - //- /my_library.rs - mod foo; - use self::foo::Bar; - - //- /foo/mod.rs - pub struct Bar; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "my_library": ("/my_library.rs", []), - }); - let file_id = db.file_id_of("/my_library.rs"); - - let module = crate::source_binder::module_from_file_id(&db, file_id).unwrap(); - let krate = module.krate(&db).unwrap(); - let module_id = module.module_id; - let item_map = db.item_map(krate); - check_module_item_map( - &item_map, - module_id, - " - Bar: t v - foo: t - ", - ); -} - -#[test] -fn std_prelude() { - covers!(std_prelude); - let mut db = MockDatabase::with_files( - " - //- /main.rs - use Foo::*; - - //- /lib.rs - mod prelude; - #[prelude_import] - use prelude::*; - - //- /prelude.rs - pub enum Foo { Bar, Baz }; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "main": ("/main.rs", ["test_crate"]), - "test_crate": ("/lib.rs", []), - }); - let main_id = db.file_id_of("/main.rs"); - - let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - eprintln!("module = {:?}", module); - let krate = module.krate(&db).unwrap(); - let item_map = db.item_map(krate); - - check_module_item_map( - &item_map, - module.module_id, - " - Bar: t v - Baz: t v - ", - ); -} - -#[test] -fn name_res_works_for_broken_modules() { - covers!(name_res_works_for_broken_modules); - let (item_map, module_id) = item_map( - " - //- /lib.rs - mod foo // no `;`, no body - - use self::foo::Baz; - <|> - - //- /foo/mod.rs - pub mod bar; - - pub use self::bar::Baz; - - //- /foo/bar.rs - pub struct Baz; - ", - ); - check_module_item_map( - &item_map, - module_id, - " - Baz: _ - ", - ); -} - -#[test] -fn item_map_using_self() { - let (item_map, module_id) = item_map( - " - //- /lib.rs - mod foo; - use crate::foo::bar::Baz::{self}; - <|> - //- /foo/mod.rs - pub mod bar; - //- /foo/bar.rs - pub struct Baz; - ", - ); - check_module_item_map( - &item_map, - module_id, - " - Baz: t v - foo: t - ", - ); -} - -#[test] -fn item_map_enum_importing() { - covers!(item_map_enum_importing); - let (item_map, module_id) = item_map( - " - //- /lib.rs - enum E { V } - use self::E::V; - <|> - ", - ); - check_module_item_map( - &item_map, - module_id, - " - E: t - V: t v - ", - ); -} - -#[test] -fn item_map_across_crates() { - let mut db = MockDatabase::with_files( - " - //- /main.rs - use test_crate::Baz; - - //- /lib.rs - pub struct Baz; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "main": ("/main.rs", ["test_crate"]), - "test_crate": ("/lib.rs", []), - }); - let main_id = db.file_id_of("/main.rs"); - - let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let krate = module.krate(&db).unwrap(); - let item_map = db.item_map(krate); - - check_module_item_map( - &item_map, - module.module_id, - " - Baz: t v - ", - ); -} - -#[test] -fn extern_crate_rename() { - let mut db = MockDatabase::with_files( - " - //- /main.rs - extern crate alloc as alloc_crate; - - mod alloc; - mod sync; - - //- /sync.rs - use alloc_crate::Arc; - - //- /lib.rs - struct Arc; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "main": ("/main.rs", ["alloc"]), - "alloc": ("/lib.rs", []), - }); - let sync_id = db.file_id_of("/sync.rs"); - - let module = crate::source_binder::module_from_file_id(&db, sync_id).unwrap(); - let krate = module.krate(&db).unwrap(); - let item_map = db.item_map(krate); - - check_module_item_map( - &item_map, - module.module_id, - " - Arc: t v - ", - ); -} - -#[test] -fn extern_crate_rename_2015_edition() { - let mut db = MockDatabase::with_files( - " - //- /main.rs - extern crate alloc as alloc_crate; - - mod alloc; - mod sync; - - //- /sync.rs - use alloc_crate::Arc; - - //- /lib.rs - struct Arc; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "main": ("/main.rs", "2015", ["alloc"]), - "alloc": ("/lib.rs", []), - }); - let sync_id = db.file_id_of("/sync.rs"); - - let module = crate::source_binder::module_from_file_id(&db, sync_id).unwrap(); - let krate = module.krate(&db).unwrap(); - let item_map = db.item_map(krate); - - check_module_item_map( - &item_map, - module.module_id, - " - Arc: t v - ", - ); -} - -#[test] -fn import_across_source_roots() { - let mut db = MockDatabase::with_files( - " - //- /lib.rs - pub mod a { - pub mod b { - pub struct C; - } - } - - //- root /main/ - - //- /main/main.rs - use test_crate::a::b::C; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "main": ("/main/main.rs", ["test_crate"]), - "test_crate": ("/lib.rs", []), - }); - let main_id = db.file_id_of("/main/main.rs"); - - let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let krate = module.krate(&db).unwrap(); - let item_map = db.item_map(krate); - - check_module_item_map( - &item_map, - module.module_id, - " - C: t v - ", - ); -} - -#[test] -fn reexport_across_crates() { - let mut db = MockDatabase::with_files( - " - //- /main.rs - use test_crate::Baz; - - //- /lib.rs - pub use foo::Baz; - - mod foo; - - //- /foo.rs - pub struct Baz; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "main": ("/main.rs", ["test_crate"]), - "test_crate": ("/lib.rs", []), - }); - let main_id = db.file_id_of("/main.rs"); - - let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let krate = module.krate(&db).unwrap(); - let item_map = db.item_map(krate); - - check_module_item_map( - &item_map, - module.module_id, - " - Baz: t v - ", - ); -} - -#[test] -fn values_dont_shadow_extern_crates() { - let mut db = MockDatabase::with_files( - " - //- /main.rs - fn foo() {} - use foo::Bar; - - //- /foo/lib.rs - pub struct Bar; - ", - ); - db.set_crate_graph_from_fixture(crate_graph! { - "main": ("/main.rs", ["foo"]), - "foo": ("/foo/lib.rs", []), - }); - let main_id = db.file_id_of("/main.rs"); - - let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); - let krate = module.krate(&db).unwrap(); - let item_map = db.item_map(krate); - - check_module_item_map( - &item_map, - module.module_id, - " - Bar: t v - foo: v - ", - ); -} - -fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { - let (mut db, pos) = MockDatabase::with_position(initial); - let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); - let krate = module.krate(&db).unwrap(); - { - let events = db.log_executed(|| { - db.item_map(krate); - }); - assert!(format!("{:?}", events).contains("item_map")) - } - db.set_file_text(pos.file_id, Arc::new(file_change.to_string())); - - { - let events = db.log_executed(|| { - db.item_map(krate); - }); - assert!(!format!("{:?}", events).contains("item_map"), "{:#?}", events) - } -} - -#[test] -fn typing_inside_a_function_should_not_invalidate_item_map() { - check_item_map_is_not_recomputed( - " - //- /lib.rs - mod foo;<|> - - use crate::foo::bar::Baz; - - fn foo() -> i32 { - 1 + 1 - } - //- /foo/mod.rs - pub mod bar; - - //- /foo/bar.rs - pub struct Baz; - ", - " - mod foo; - - use crate::foo::bar::Baz; - - fn foo() -> i32 { 92 } - ", - ); -} - -#[test] -fn adding_inner_items_should_not_invalidate_item_map() { - check_item_map_is_not_recomputed( - " - //- /lib.rs - struct S { a: i32} - enum E { A } - trait T { - fn a() {} - } - mod foo;<|> - impl S { - fn a() {} - } - use crate::foo::bar::Baz; - //- /foo/mod.rs - pub mod bar; - - //- /foo/bar.rs - pub struct Baz; - ", - " - struct S { a: i32, b: () } - enum E { A, B } - trait T { - fn a() {} - fn b() {} - } - mod foo;<|> - impl S { - fn a() {} - fn b() {} - } - use crate::foo::bar::Baz; - ", - ); -} - -#[test] -fn typing_inside_a_function_inside_a_macro_should_not_invalidate_item_map() { - check_item_map_is_not_recomputed( - " - //- /lib.rs - mod foo; - - use crate::foo::bar::Baz; - - //- /foo/mod.rs - pub mod bar; - - //- /foo/bar.rs - <|> - salsa::query_group! { - trait Baz { - fn foo() -> i32 { 1 + 1 } - } - } - ", - " - salsa::query_group! { - trait Baz { - fn foo() -> i32 { 92 } - } - } - ", - ); -} -- cgit v1.2.3