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 --- .../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 +++++ 5 files changed, 686 insertions(+), 75 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 (limited to 'crates/ra_hir/src/nameres/crate_def_map') 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 +"###); +} -- cgit v1.2.3