diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-11-28 13:28:44 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-11-28 13:28:44 +0000 |
commit | 0cda188621b792265c957bdf4ac54af31cbc9947 (patch) | |
tree | 6f93cb6c8d04e2eb44154464b7e74ef549573a6f /crates/ra_hir/src/mock.rs | |
parent | 95c0c8f3986c8b3bcf0052d34d3ace09ebb9fa1b (diff) | |
parent | 555483d397db530d1d102d7828c7847a948baf6b (diff) |
Merge #248
248: Hir tests r=matklad a=matklad
bors r+
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/mock.rs')
-rw-r--r-- | crates/ra_hir/src/mock.rs | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs new file mode 100644 index 000000000..8e256b89f --- /dev/null +++ b/crates/ra_hir/src/mock.rs | |||
@@ -0,0 +1,172 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use parking_lot::Mutex; | ||
4 | use salsa::{self, Database}; | ||
5 | use ra_db::{LocationIntener, BaseDatabase, FilePosition, mock::FileMap, FileId, WORKSPACE}; | ||
6 | use relative_path::RelativePathBuf; | ||
7 | use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; | ||
8 | |||
9 | use crate::{db, DefId, DefLoc, FnId, SourceItemId}; | ||
10 | |||
11 | #[derive(Debug)] | ||
12 | pub(crate) struct MockDatabase { | ||
13 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, | ||
14 | runtime: salsa::Runtime<MockDatabase>, | ||
15 | id_maps: Arc<IdMaps>, | ||
16 | } | ||
17 | |||
18 | impl MockDatabase { | ||
19 | pub(crate) fn with_position(fixture: &str) -> (MockDatabase, FilePosition) { | ||
20 | let mut db = MockDatabase::default(); | ||
21 | |||
22 | let mut position = None; | ||
23 | let mut file_map = FileMap::default(); | ||
24 | for entry in parse_fixture(fixture) { | ||
25 | if entry.text.contains(CURSOR_MARKER) { | ||
26 | assert!( | ||
27 | position.is_none(), | ||
28 | "only one marker (<|>) per fixture is allowed" | ||
29 | ); | ||
30 | position = Some(db.add_file_with_position(&mut file_map, &entry.meta, &entry.text)); | ||
31 | } else { | ||
32 | db.add_file(&mut file_map, &entry.meta, &entry.text); | ||
33 | } | ||
34 | } | ||
35 | let position = position.expect("expected a marker (<|>)"); | ||
36 | let source_root = file_map.into_source_root(); | ||
37 | db.query_mut(ra_db::SourceRootQuery) | ||
38 | .set(WORKSPACE, Arc::new(source_root)); | ||
39 | (db, position) | ||
40 | } | ||
41 | |||
42 | fn add_file(&mut self, file_map: &mut FileMap, path: &str, text: &str) -> FileId { | ||
43 | assert!(path.starts_with('/')); | ||
44 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); | ||
45 | |||
46 | let file_id = file_map.add(path); | ||
47 | let text = Arc::new(text.to_string()); | ||
48 | self.query_mut(ra_db::FileTextQuery).set(file_id, text); | ||
49 | self.query_mut(ra_db::FileSourceRootQuery) | ||
50 | .set(file_id, WORKSPACE); | ||
51 | file_id | ||
52 | } | ||
53 | |||
54 | fn add_file_with_position( | ||
55 | &mut self, | ||
56 | file_map: &mut FileMap, | ||
57 | path: &str, | ||
58 | text: &str, | ||
59 | ) -> FilePosition { | ||
60 | let (offset, text) = extract_offset(text); | ||
61 | let file_id = self.add_file(file_map, path, &text); | ||
62 | FilePosition { file_id, offset } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | #[derive(Debug, Default)] | ||
67 | struct IdMaps { | ||
68 | fns: LocationIntener<SourceItemId, FnId>, | ||
69 | defs: LocationIntener<DefLoc, DefId>, | ||
70 | } | ||
71 | |||
72 | impl salsa::Database for MockDatabase { | ||
73 | fn salsa_runtime(&self) -> &salsa::Runtime<MockDatabase> { | ||
74 | &self.runtime | ||
75 | } | ||
76 | |||
77 | fn salsa_event(&self, event: impl Fn() -> salsa::Event<MockDatabase>) { | ||
78 | let mut events = self.events.lock(); | ||
79 | if let Some(events) = &mut *events { | ||
80 | events.push(event()); | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | |||
85 | impl Default for MockDatabase { | ||
86 | fn default() -> MockDatabase { | ||
87 | let mut db = MockDatabase { | ||
88 | events: Default::default(), | ||
89 | runtime: salsa::Runtime::default(), | ||
90 | id_maps: Default::default(), | ||
91 | }; | ||
92 | db.query_mut(ra_db::SourceRootQuery) | ||
93 | .set(ra_db::WORKSPACE, Default::default()); | ||
94 | db.query_mut(ra_db::CrateGraphQuery) | ||
95 | .set((), Default::default()); | ||
96 | db.query_mut(ra_db::LibrariesQuery) | ||
97 | .set((), Default::default()); | ||
98 | db | ||
99 | } | ||
100 | } | ||
101 | |||
102 | impl salsa::ParallelDatabase for MockDatabase { | ||
103 | fn snapshot(&self) -> salsa::Snapshot<MockDatabase> { | ||
104 | salsa::Snapshot::new(MockDatabase { | ||
105 | events: Default::default(), | ||
106 | runtime: self.runtime.snapshot(self), | ||
107 | id_maps: self.id_maps.clone(), | ||
108 | }) | ||
109 | } | ||
110 | } | ||
111 | |||
112 | impl BaseDatabase for MockDatabase {} | ||
113 | |||
114 | impl AsRef<LocationIntener<DefLoc, DefId>> for MockDatabase { | ||
115 | fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> { | ||
116 | &self.id_maps.defs | ||
117 | } | ||
118 | } | ||
119 | |||
120 | impl AsRef<LocationIntener<SourceItemId, FnId>> for MockDatabase { | ||
121 | fn as_ref(&self) -> &LocationIntener<SourceItemId, FnId> { | ||
122 | &self.id_maps.fns | ||
123 | } | ||
124 | } | ||
125 | |||
126 | impl MockDatabase { | ||
127 | pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<MockDatabase>> { | ||
128 | *self.events.lock() = Some(Vec::new()); | ||
129 | f(); | ||
130 | let events = self.events.lock().take().unwrap(); | ||
131 | events | ||
132 | } | ||
133 | |||
134 | pub(crate) fn log_executed(&self, f: impl FnOnce()) -> Vec<String> { | ||
135 | let events = self.log(f); | ||
136 | events | ||
137 | .into_iter() | ||
138 | .filter_map(|e| match e.kind { | ||
139 | // This pretty horrible, but `Debug` is the only way to inspect | ||
140 | // QueryDescriptor at the moment. | ||
141 | salsa::EventKind::WillExecute { descriptor } => Some(format!("{:?}", descriptor)), | ||
142 | _ => None, | ||
143 | }) | ||
144 | .collect() | ||
145 | } | ||
146 | } | ||
147 | |||
148 | salsa::database_storage! { | ||
149 | pub(crate) struct MockDatabaseStorage for MockDatabase { | ||
150 | impl ra_db::FilesDatabase { | ||
151 | fn file_text() for ra_db::FileTextQuery; | ||
152 | fn file_source_root() for ra_db::FileSourceRootQuery; | ||
153 | fn source_root() for ra_db::SourceRootQuery; | ||
154 | fn libraries() for ra_db::LibrariesQuery; | ||
155 | fn crate_graph() for ra_db::CrateGraphQuery; | ||
156 | } | ||
157 | impl ra_db::SyntaxDatabase { | ||
158 | fn source_file() for ra_db::SourceFileQuery; | ||
159 | fn file_lines() for ra_db::FileLinesQuery; | ||
160 | } | ||
161 | impl db::HirDatabase { | ||
162 | fn module_tree() for db::ModuleTreeQuery; | ||
163 | fn fn_scopes() for db::FnScopesQuery; | ||
164 | fn file_items() for db::SourceFileItemsQuery; | ||
165 | fn file_item() for db::FileItemQuery; | ||
166 | fn input_module_items() for db::InputModuleItemsQuery; | ||
167 | fn item_map() for db::ItemMapQuery; | ||
168 | fn fn_syntax() for db::FnSyntaxQuery; | ||
169 | fn submodules() for db::SubmodulesQuery; | ||
170 | } | ||
171 | } | ||
172 | } | ||