aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/test_db.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/test_db.rs')
-rw-r--r--crates/ra_hir_ty/src/test_db.rs144
1 files changed, 144 insertions, 0 deletions
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
new file mode 100644
index 000000000..0e51f4130
--- /dev/null
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -0,0 +1,144 @@
1//! Database used for testing `hir`.
2
3use std::{panic, sync::Arc};
4
5use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId, ModuleId};
6use hir_expand::diagnostics::DiagnosticSink;
7use parking_lot::Mutex;
8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase};
9
10use crate::{db::HirDatabase, expr::ExprValidator};
11
12#[salsa::database(
13 ra_db::SourceDatabaseExtStorage,
14 ra_db::SourceDatabaseStorage,
15 hir_expand::db::AstDatabaseStorage,
16 hir_def::db::InternDatabaseStorage,
17 hir_def::db::DefDatabaseStorage,
18 crate::db::HirDatabaseStorage
19)]
20#[derive(Debug, Default)]
21pub struct TestDB {
22 events: Mutex<Option<Vec<salsa::Event<TestDB>>>>,
23 runtime: salsa::Runtime<TestDB>,
24}
25
26impl salsa::Database for TestDB {
27 fn salsa_runtime(&self) -> &salsa::Runtime<TestDB> {
28 &self.runtime
29 }
30
31 fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
32 &mut self.runtime
33 }
34
35 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) {
36 let mut events = self.events.lock();
37 if let Some(events) = &mut *events {
38 events.push(event());
39 }
40 }
41}
42
43impl salsa::ParallelDatabase for TestDB {
44 fn snapshot(&self) -> salsa::Snapshot<TestDB> {
45 salsa::Snapshot::new(TestDB {
46 events: Default::default(),
47 runtime: self.runtime.snapshot(self),
48 })
49 }
50}
51
52impl panic::RefUnwindSafe for TestDB {}
53
54impl FileLoader for TestDB {
55 fn file_text(&self, file_id: FileId) -> Arc<String> {
56 FileLoaderDelegate(self).file_text(file_id)
57 }
58 fn resolve_relative_path(
59 &self,
60 anchor: FileId,
61 relative_path: &RelativePath,
62 ) -> Option<FileId> {
63 FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path)
64 }
65 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
66 FileLoaderDelegate(self).relevant_crates(file_id)
67 }
68}
69
70impl TestDB {
71 pub fn module_for_file(&self, file_id: FileId) -> ModuleId {
72 for &krate in self.relevant_crates(file_id).iter() {
73 let crate_def_map = self.crate_def_map(krate);
74 for (module_id, data) in crate_def_map.modules.iter() {
75 if data.definition == Some(file_id) {
76 return ModuleId { krate, module_id };
77 }
78 }
79 }
80 panic!("Can't find module for file")
81 }
82
83 // FIXME: don't duplicate this
84 pub fn diagnostics(&self) -> String {
85 let mut buf = String::new();
86 let crate_graph = self.crate_graph();
87 for krate in crate_graph.iter().next() {
88 let crate_def_map = self.crate_def_map(krate);
89
90 let mut fns = Vec::new();
91 for (module_id, _) in crate_def_map.modules.iter() {
92 for decl in crate_def_map[module_id].scope.declarations() {
93 match decl {
94 ModuleDefId::FunctionId(f) => fns.push(f),
95 _ => (),
96 }
97 }
98
99 for &impl_id in crate_def_map[module_id].impls.iter() {
100 let impl_data = self.impl_data(impl_id);
101 for item in impl_data.items.iter() {
102 if let AssocItemId::FunctionId(f) = item {
103 fns.push(*f)
104 }
105 }
106 }
107 }
108
109 for f in fns {
110 let infer = self.infer(f.into());
111 let mut sink = DiagnosticSink::new(|d| {
112 buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message());
113 });
114 infer.add_diagnostics(self, f, &mut sink);
115 let mut validator = ExprValidator::new(f, infer, &mut sink);
116 validator.validate_body(self);
117 }
118 }
119 buf
120 }
121}
122
123impl TestDB {
124 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<TestDB>> {
125 *self.events.lock() = Some(Vec::new());
126 f();
127 self.events.lock().take().unwrap()
128 }
129
130 pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
131 let events = self.log(f);
132 events
133 .into_iter()
134 .filter_map(|e| match e.kind {
135 // This pretty horrible, but `Debug` is the only way to inspect
136 // QueryDescriptor at the moment.
137 salsa::EventKind::WillExecute { database_key } => {
138 Some(format!("{:?}", database_key))
139 }
140 _ => None,
141 })
142 .collect()
143 }
144}