aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/mock.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/mock.rs')
-rw-r--r--crates/ra_hir/src/mock.rs262
1 files changed, 0 insertions, 262 deletions
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
deleted file mode 100644
index ab97a09b9..000000000
--- a/crates/ra_hir/src/mock.rs
+++ /dev/null
@@ -1,262 +0,0 @@
1//! FIXME: write short doc here
2
3use std::{panic, sync::Arc};
4
5use hir_expand::diagnostics::DiagnosticSink;
6use parking_lot::Mutex;
7use ra_cfg::CfgOptions;
8use ra_db::{
9 salsa, CrateGraph, CrateId, Edition, FileId, FileLoader, FileLoaderDelegate, FilePosition,
10 RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId,
11};
12use rustc_hash::FxHashMap;
13use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
14
15use crate::{db, debug::HirDebugHelper};
16
17pub const WORKSPACE: SourceRootId = SourceRootId(0);
18
19#[salsa::database(
20 ra_db::SourceDatabaseExtStorage,
21 ra_db::SourceDatabaseStorage,
22 db::InternDatabaseStorage,
23 db::AstDatabaseStorage,
24 db::DefDatabaseStorage,
25 db::DefDatabase2Storage,
26 db::HirDatabaseStorage
27)]
28#[derive(Debug)]
29pub struct MockDatabase {
30 events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>,
31 runtime: salsa::Runtime<MockDatabase>,
32 files: FxHashMap<String, FileId>,
33 crate_names: Arc<FxHashMap<CrateId, String>>,
34 file_paths: Arc<FxHashMap<FileId, String>>,
35}
36
37impl panic::RefUnwindSafe for MockDatabase {}
38
39impl FileLoader for MockDatabase {
40 fn file_text(&self, file_id: FileId) -> Arc<String> {
41 FileLoaderDelegate(self).file_text(file_id)
42 }
43 fn resolve_relative_path(
44 &self,
45 anchor: FileId,
46 relative_path: &RelativePath,
47 ) -> Option<FileId> {
48 FileLoaderDelegate(self).resolve_relative_path(anchor, relative_path)
49 }
50 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
51 FileLoaderDelegate(self).relevant_crates(file_id)
52 }
53}
54
55impl HirDebugHelper for MockDatabase {
56 fn crate_name(&self, krate: CrateId) -> Option<String> {
57 self.crate_names.get(&krate).cloned()
58 }
59
60 fn file_path(&self, file_id: FileId) -> Option<String> {
61 self.file_paths.get(&file_id).cloned()
62 }
63}
64
65impl MockDatabase {
66 pub fn with_files(fixture: &str) -> MockDatabase {
67 let (db, position) = MockDatabase::from_fixture(fixture);
68 assert!(position.is_none());
69 db
70 }
71
72 pub fn with_single_file(text: &str) -> (MockDatabase, SourceRoot, FileId) {
73 let mut db = MockDatabase::default();
74 let mut source_root = SourceRoot::default();
75 let file_id = db.add_file(WORKSPACE, "/", &mut source_root, "/main.rs", text);
76 db.set_source_root(WORKSPACE, Arc::new(source_root.clone()));
77 (db, source_root, file_id)
78 }
79
80 pub fn file_id_of(&self, path: &str) -> FileId {
81 match self.files.get(path) {
82 Some(it) => *it,
83 None => panic!("unknown file: {:?}\nexisting files:\n{:#?}", path, self.files),
84 }
85 }
86
87 pub fn diagnostics(&self) -> String {
88 let mut buf = String::new();
89 let mut files: Vec<FileId> = self.files.values().copied().collect();
90 files.sort();
91 for file in files {
92 let src = crate::Source {
93 file_id: file.into(),
94 ast: crate::ModuleSource::new(self, Some(file), None),
95 };
96 let module = crate::Module::from_definition(self, src).unwrap();
97 module.diagnostics(
98 self,
99 &mut DiagnosticSink::new(|d| {
100 buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message());
101 }),
102 )
103 }
104 buf
105 }
106
107 fn from_fixture(fixture: &str) -> (MockDatabase, Option<FilePosition>) {
108 let mut db = MockDatabase::default();
109
110 let pos = db.add_fixture(fixture);
111
112 (db, pos)
113 }
114
115 fn add_fixture(&mut self, fixture: &str) -> Option<FilePosition> {
116 let mut position = None;
117 let mut source_root = SourceRoot::default();
118 let mut source_root_id = WORKSPACE;
119 let mut source_root_prefix = "/".to_string();
120 for entry in parse_fixture(fixture) {
121 if entry.meta.starts_with("root") {
122 self.set_source_root(source_root_id, Arc::new(source_root));
123 source_root = SourceRoot::default();
124
125 source_root_id = SourceRootId(source_root_id.0 + 1);
126 source_root_prefix = entry.meta["root".len()..].trim().to_string();
127 continue;
128 }
129 if entry.text.contains(CURSOR_MARKER) {
130 assert!(position.is_none(), "only one marker (<|>) per fixture is allowed");
131 position = Some(self.add_file_with_position(
132 source_root_id,
133 &source_root_prefix,
134 &mut source_root,
135 &entry.meta,
136 &entry.text,
137 ));
138 } else {
139 self.add_file(
140 source_root_id,
141 &source_root_prefix,
142 &mut source_root,
143 &entry.meta,
144 &entry.text,
145 );
146 }
147 }
148 self.set_source_root(source_root_id, Arc::new(source_root));
149 position
150 }
151
152 fn add_file(
153 &mut self,
154 source_root_id: SourceRootId,
155 source_root_prefix: &str,
156 source_root: &mut SourceRoot,
157 path: &str,
158 text: &str,
159 ) -> FileId {
160 assert!(source_root_prefix.starts_with('/'));
161 assert!(source_root_prefix.ends_with('/'));
162 assert!(path.starts_with(source_root_prefix));
163 let rel_path = RelativePathBuf::from_path(&path[source_root_prefix.len()..]).unwrap();
164
165 let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs";
166
167 let file_id = FileId(self.files.len() as u32);
168
169 let prev = self.files.insert(path.to_string(), file_id);
170 assert!(prev.is_none(), "duplicate files in the text fixture");
171 Arc::make_mut(&mut self.file_paths).insert(file_id, path.to_string());
172
173 let text = Arc::new(text.to_string());
174 self.set_file_text(file_id, text);
175 self.set_file_relative_path(file_id, rel_path.clone());
176 self.set_file_source_root(file_id, source_root_id);
177 source_root.insert_file(rel_path, file_id);
178
179 if is_crate_root {
180 let mut crate_graph = CrateGraph::default();
181 crate_graph.add_crate_root(file_id, Edition::Edition2018, CfgOptions::default());
182 self.set_crate_graph(Arc::new(crate_graph));
183 }
184 file_id
185 }
186
187 fn add_file_with_position(
188 &mut self,
189 source_root_id: SourceRootId,
190 source_root_prefix: &str,
191 source_root: &mut SourceRoot,
192 path: &str,
193 text: &str,
194 ) -> FilePosition {
195 let (offset, text) = extract_offset(text);
196 let file_id = self.add_file(source_root_id, source_root_prefix, source_root, path, &text);
197 FilePosition { file_id, offset }
198 }
199}
200
201impl salsa::Database for MockDatabase {
202 fn salsa_runtime(&self) -> &salsa::Runtime<MockDatabase> {
203 &self.runtime
204 }
205
206 fn salsa_event(&self, event: impl Fn() -> salsa::Event<MockDatabase>) {
207 let mut events = self.events.lock();
208 if let Some(events) = &mut *events {
209 events.push(event());
210 }
211 }
212}
213
214impl Default for MockDatabase {
215 fn default() -> MockDatabase {
216 let mut db = MockDatabase {
217 events: Default::default(),
218 runtime: salsa::Runtime::default(),
219 files: FxHashMap::default(),
220 crate_names: Default::default(),
221 file_paths: Default::default(),
222 };
223 db.set_crate_graph(Default::default());
224 db
225 }
226}
227
228impl salsa::ParallelDatabase for MockDatabase {
229 fn snapshot(&self) -> salsa::Snapshot<MockDatabase> {
230 salsa::Snapshot::new(MockDatabase {
231 events: Default::default(),
232 runtime: self.runtime.snapshot(self),
233 // only the root database can be used to get file_id by path.
234 files: FxHashMap::default(),
235 file_paths: Arc::clone(&self.file_paths),
236 crate_names: Arc::clone(&self.crate_names),
237 })
238 }
239}
240
241impl MockDatabase {
242 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> {
243 *self.events.lock() = Some(Vec::new());
244 f();
245 self.events.lock().take().unwrap()
246 }
247
248 pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
249 let events = self.log(f);
250 events
251 .into_iter()
252 .filter_map(|e| match e.kind {
253 // This pretty horrible, but `Debug` is the only way to inspect
254 // QueryDescriptor at the moment.
255 salsa::EventKind::WillExecute { database_key } => {
256 Some(format!("{:?}", database_key))
257 }
258 _ => None,
259 })
260 .collect()
261 }
262}