move tests over to crate-def-map

This commit is contained in:
Aleksey Kladov 2019-03-14 11:53:40 +03:00
parent 2195d1db6d
commit 71e5adf694
9 changed files with 706 additions and 867 deletions

View File

@ -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

View File

@ -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;

View File

@ -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 => {

View File

@ -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
}

View File

@ -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;
//- /nested.rs
structs!(Bar, Baz);
use crate::foo::Baz as Foo;
//- /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;
//- /n1.rs
m!(n2)
//- /n1/n2.rs
struct X;
use crate::foo::bar::{Baz, Quux};
//- /foo/mod.rs
pub mod bar;
//- /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;
//- /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
Foo: t v
Bar: t v
mod foo;
crate::bar
Foo: t v
Bar: t v
"###);
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: t v
foo: t
crate::foo
bar: t
Baz: t v
crate::foo::bar
Baz: t v
"###
);
}
#[test]
@ -203,31 +218,8 @@ 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 item_map_enum_importing() {
covers!(item_map_enum_importing);
fn can_import_enum_variant() {
covers!(can_import_enum_variant);
let map = def_map(
"
//- /lib.rs
@ -244,22 +236,293 @@ E: t
}
#[test]
fn glob_enum() {
covers!(glob_enum);
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
enum Foo {
Bar, Baz
}
use self::Foo::*;
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###"
assert_snapshot_matches!(map,
@r###"
crate
Foo: t
Bar: t v
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::Baz;
//- /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 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
struct Arc;
",
crate_graph! {
"main": ("/main.rs", ["alloc"]),
"alloc": ("/lib.rs", []),
},
);
assert_snapshot_matches!(map,
@r###"
crate
Arc: t v
"###
);
}
#[test]
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
pub mod a {
pub mod b {
pub struct C;
}
}
//- 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###"
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
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
"###
);
}

View File

@ -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
"###
);
}

View File

@ -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 }
}
}
",
);
}

View File

@ -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
"###);
}

View File

@ -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<ItemMap>, 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::<Vec<_>>();
lines.sort();
let actual = lines.join("\n");
let expected = expected.trim().lines().map(|it| it.trim()).collect::<Vec<_>>().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 }
}
}
",
);
}