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