aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/test_db.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/test_db.rs')
-rw-r--r--crates/hir_ty/src/test_db.rs136
1 files changed, 136 insertions, 0 deletions
diff --git a/crates/hir_ty/src/test_db.rs b/crates/hir_ty/src/test_db.rs
new file mode 100644
index 000000000..15b8435e9
--- /dev/null
+++ b/crates/hir_ty/src/test_db.rs
@@ -0,0 +1,136 @@
1//! Database used for testing `hir`.
2
3use std::{
4 fmt, panic,
5 sync::{Arc, Mutex},
6};
7
8use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast};
9use hir_def::{db::DefDatabase, ModuleId};
10use hir_expand::db::AstDatabase;
11use rustc_hash::{FxHashMap, FxHashSet};
12use syntax::TextRange;
13use test_utils::extract_annotations;
14
15#[salsa::database(
16 base_db::SourceDatabaseExtStorage,
17 base_db::SourceDatabaseStorage,
18 hir_expand::db::AstDatabaseStorage,
19 hir_def::db::InternDatabaseStorage,
20 hir_def::db::DefDatabaseStorage,
21 crate::db::HirDatabaseStorage
22)]
23#[derive(Default)]
24pub struct TestDB {
25 storage: salsa::Storage<TestDB>,
26 events: Mutex<Option<Vec<salsa::Event>>>,
27}
28impl fmt::Debug for TestDB {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.debug_struct("TestDB").finish()
31 }
32}
33
34impl Upcast<dyn AstDatabase> for TestDB {
35 fn upcast(&self) -> &(dyn AstDatabase + 'static) {
36 &*self
37 }
38}
39
40impl Upcast<dyn DefDatabase> for TestDB {
41 fn upcast(&self) -> &(dyn DefDatabase + 'static) {
42 &*self
43 }
44}
45
46impl salsa::Database for TestDB {
47 fn salsa_event(&self, event: salsa::Event) {
48 let mut events = self.events.lock().unwrap();
49 if let Some(events) = &mut *events {
50 events.push(event);
51 }
52 }
53}
54
55impl salsa::ParallelDatabase for TestDB {
56 fn snapshot(&self) -> salsa::Snapshot<TestDB> {
57 salsa::Snapshot::new(TestDB {
58 storage: self.storage.snapshot(),
59 events: Default::default(),
60 })
61 }
62}
63
64impl panic::RefUnwindSafe for TestDB {}
65
66impl FileLoader for TestDB {
67 fn file_text(&self, file_id: FileId) -> Arc<String> {
68 FileLoaderDelegate(self).file_text(file_id)
69 }
70 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> {
71 FileLoaderDelegate(self).resolve_path(anchor, path)
72 }
73 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
74 FileLoaderDelegate(self).relevant_crates(file_id)
75 }
76}
77
78impl TestDB {
79 pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId {
80 for &krate in self.relevant_crates(file_id).iter() {
81 let crate_def_map = self.crate_def_map(krate);
82 for (local_id, data) in crate_def_map.modules.iter() {
83 if data.origin.file_id() == Some(file_id) {
84 return ModuleId { krate, local_id };
85 }
86 }
87 }
88 panic!("Can't find module for file")
89 }
90
91 pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> {
92 let mut files = Vec::new();
93 let crate_graph = self.crate_graph();
94 for krate in crate_graph.iter() {
95 let crate_def_map = self.crate_def_map(krate);
96 for (module_id, _) in crate_def_map.modules.iter() {
97 let file_id = crate_def_map[module_id].origin.file_id();
98 files.extend(file_id)
99 }
100 }
101 files
102 .into_iter()
103 .filter_map(|file_id| {
104 let text = self.file_text(file_id);
105 let annotations = extract_annotations(&text);
106 if annotations.is_empty() {
107 return None;
108 }
109 Some((file_id, annotations))
110 })
111 .collect()
112 }
113}
114
115impl TestDB {
116 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> {
117 *self.events.lock().unwrap() = Some(Vec::new());
118 f();
119 self.events.lock().unwrap().take().unwrap()
120 }
121
122 pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
123 let events = self.log(f);
124 events
125 .into_iter()
126 .filter_map(|e| match e.kind {
127 // This pretty horrible, but `Debug` is the only way to inspect
128 // QueryDescriptor at the moment.
129 salsa::EventKind::WillExecute { database_key } => {
130 Some(format!("{:?}", database_key.debug(self)))
131 }
132 _ => None,
133 })
134 .collect()
135 }
136}