rust/crates/ra_hir/src/nameres/tests.rs

406 lines
8.6 KiB
Rust
Raw Normal View History

2018-12-09 03:48:55 -06:00
use std::sync::Arc;
use salsa::Database;
use ra_db::{FilesDatabase, CrateGraph, SourceRootId};
2018-12-19 03:40:41 -06:00
use relative_path::RelativePath;
2018-12-27 12:02:08 -06:00
use test_utils::assert_eq_text;
2018-12-09 03:48:55 -06:00
use crate::{
2019-01-08 06:57:45 -06:00
ItemMap, Resolution,
2018-12-09 03:48:55 -06:00
db::HirDatabase,
mock::MockDatabase,
2019-01-08 06:57:45 -06:00
module_tree::ModuleId,
2018-12-09 03:48:55 -06:00
};
2019-01-08 06:57:45 -06:00
fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
2018-12-09 03:48:55 -06:00
let (db, pos) = MockDatabase::with_position(fixture);
let source_root = db.file_source_root(pos.file_id);
2019-01-08 06:57:45 -06:00
let module = crate::source_binder::module_from_position(&db, pos)
2018-12-09 03:48:55 -06:00
.unwrap()
.unwrap();
2019-01-06 08:38:20 -06:00
let module_id = module.def_id.loc(&db).module_id;
2018-12-09 03:48:55 -06:00
(db.item_map(source_root).unwrap(), module_id)
}
2019-01-08 06:57:45 -06:00
fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) {
2018-12-27 12:02:08 -06:00
let mut lines = map.per_module[&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);
2018-12-27 12:02:08 -06:00
2019-01-08 06:57:45 -06:00
fn dump_resolution(resolution: &Resolution) -> &'static str {
2018-12-27 12:02:08 -06:00
match (
resolution.def_id.types.is_some(),
resolution.def_id.values.is_some(),
) {
(true, true) => "t v",
(true, false) => "t",
(false, true) => "v",
(false, false) => "_",
}
}
}
2018-12-09 03:48:55 -06:00
#[test]
2018-12-09 04:49:54 -06:00
fn item_map_smoke_test() {
2018-12-09 03:48:55 -06:00
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;
",
);
2018-12-27 12:02:08 -06:00
check_module_item_map(
&item_map,
module_id,
"
Baz: t v
foo: t
",
);
2018-12-09 03:48:55 -06:00
}
2019-01-08 07:39:55 -06:00
#[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
",
);
}
2019-01-01 13:12:05 -06:00
#[test]
fn item_map_contains_items_from_expansions() {
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
salsa::query_group! {
trait Baz {}
}
",
);
check_module_item_map(
&item_map,
module_id,
"
Baz: t
foo: t
",
);
}
2018-12-21 16:29:59 -06:00
#[test]
2018-12-27 12:02:08 -06:00
fn item_map_using_self() {
2018-12-21 16:29:59 -06:00
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;
",
);
2018-12-27 12:02:08 -06:00
check_module_item_map(
&item_map,
module_id,
"
Baz: t v
foo: t
",
);
2018-12-21 16:29:59 -06:00
}
2018-12-09 04:49:54 -06:00
#[test]
fn item_map_across_crates() {
2018-12-19 03:40:41 -06:00
let (mut db, sr) = MockDatabase::with_files(
2018-12-09 04:49:54 -06:00
"
//- /main.rs
use test_crate::Baz;
//- /lib.rs
pub struct Baz;
",
);
let main_id = sr.files[RelativePath::new("/main.rs")];
let lib_id = sr.files[RelativePath::new("/lib.rs")];
let mut crate_graph = CrateGraph::default();
let main_crate = crate_graph.add_crate_root(main_id);
let lib_crate = crate_graph.add_crate_root(lib_id);
crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate);
db.set_crate_graph(crate_graph);
let source_root = db.file_source_root(main_id);
let module = crate::source_binder::module_from_file_id(&db, main_id)
.unwrap()
.unwrap();
let module_id = module.def_id.loc(&db).module_id;
let item_map = db.item_map(source_root).unwrap();
check_module_item_map(
&item_map,
module_id,
"
Baz: t v
test_crate: t
",
);
}
#[test]
fn import_across_source_roots() {
let (mut db, sr) = MockDatabase::with_files(
"
//- /lib.rs
pub mod a {
pub mod b {
pub struct C;
}
}
",
);
let lib_id = sr.files[RelativePath::new("/lib.rs")];
let source_root = SourceRootId(1);
let (sr2, pos) = db.add_fixture(
source_root,
"
//- /main.rs
use test_crate::a::b::C;
",
);
assert!(pos.is_none());
let main_id = sr2.files[RelativePath::new("/main.rs")];
eprintln!("lib = {:?}, main = {:?}", lib_id, main_id);
let mut crate_graph = CrateGraph::default();
let main_crate = crate_graph.add_crate_root(main_id);
let lib_crate = crate_graph.add_crate_root(lib_id);
crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate);
db.set_crate_graph(crate_graph);
let module = crate::source_binder::module_from_file_id(&db, main_id)
.unwrap()
.unwrap();
let module_id = module.def_id.loc(&db).module_id;
let item_map = db.item_map(source_root).unwrap();
check_module_item_map(
&item_map,
module_id,
"
C: t v
test_crate: t
",
);
}
#[test]
fn reexport_across_crates() {
let (mut db, sr) = MockDatabase::with_files(
"
//- /main.rs
use test_crate::Baz;
//- /lib.rs
pub use foo::Baz;
mod foo;
//- /foo.rs
2018-12-09 04:49:54 -06:00
pub struct Baz;
",
);
2018-12-19 03:40:41 -06:00
let main_id = sr.files[RelativePath::new("/main.rs")];
let lib_id = sr.files[RelativePath::new("/lib.rs")];
2018-12-09 04:49:54 -06:00
let mut crate_graph = CrateGraph::default();
let main_crate = crate_graph.add_crate_root(main_id);
let lib_crate = crate_graph.add_crate_root(lib_id);
crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate);
db.set_crate_graph(crate_graph);
let source_root = db.file_source_root(main_id);
2019-01-08 06:57:45 -06:00
let module = crate::source_binder::module_from_file_id(&db, main_id)
2018-12-09 04:49:54 -06:00
.unwrap()
.unwrap();
2019-01-06 08:38:20 -06:00
let module_id = module.def_id.loc(&db).module_id;
2018-12-09 04:49:54 -06:00
let item_map = db.item_map(source_root).unwrap();
2018-12-27 12:02:08 -06:00
check_module_item_map(
&item_map,
module_id,
"
Baz: t v
test_crate: t
",
);
2018-12-09 04:49:54 -06:00
}
2019-01-08 15:48:54 -06:00
fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
let (mut db, pos) = MockDatabase::with_position(initial);
let source_root = db.file_source_root(pos.file_id);
{
let events = db.log_executed(|| {
db.item_map(source_root).unwrap();
});
assert!(format!("{:?}", events).contains("item_map"))
}
db.query_mut(ra_db::FileTextQuery)
.set(pos.file_id, Arc::new(file_change.to_string()));
{
let events = db.log_executed(|| {
db.item_map(source_root).unwrap();
});
assert!(
!format!("{:?}", events).contains("item_map"),
"{:#?}",
events
)
}
}
2018-12-09 03:48:55 -06:00
#[test]
fn typing_inside_a_function_should_not_invalidate_item_map() {
2019-01-08 15:48:54 -06:00
check_item_map_is_not_recomputed(
2019-01-01 13:12:05 -06:00
"
//- /lib.rs
2019-01-08 15:49:21 -06:00
mod foo;<|>
2019-01-01 13:12:05 -06:00
use crate::foo::bar::Baz;
2019-01-08 15:49:21 -06:00
fn foo() -> i32 {
1 + 1
}
2019-01-01 13:12:05 -06:00
//- /foo/mod.rs
pub mod bar;
//- /foo/bar.rs
2019-01-08 15:49:21 -06:00
pub struct Baz;
2019-01-01 13:12:05 -06:00
",
2019-01-08 15:48:54 -06:00
"
2019-01-08 15:49:21 -06:00
mod foo;
use crate::foo::bar::Baz;
fn foo() -> i32 { 92 }
2019-01-08 15:48:54 -06:00
",
);
2019-01-01 13:12:05 -06:00
}
#[test]
fn typing_inside_a_function_inside_a_macro_should_not_invalidate_item_map() {
2019-01-08 15:48:54 -06:00
check_item_map_is_not_recomputed(
2018-12-09 03:48:55 -06:00
"
//- /lib.rs
2019-01-08 15:49:21 -06:00
mod foo;
2018-12-09 03:48:55 -06:00
use crate::foo::bar::Baz;
//- /foo/mod.rs
pub mod bar;
//- /foo/bar.rs
2019-01-08 15:49:21 -06:00
<|>
salsa::query_group! {
trait Baz {
fn foo() -> i32 { 1 + 1 }
}
}
2019-01-08 15:48:54 -06:00
",
"
2019-01-08 15:49:21 -06:00
salsa::query_group! {
trait Baz {
fn foo() -> i32 { 92 }
}
}
2019-01-08 15:48:54 -06:00
",
);
2018-12-09 03:48:55 -06:00
}