diff options
Diffstat (limited to 'crates/ra_hir/src/mock.rs')
-rw-r--r-- | crates/ra_hir/src/mock.rs | 82 |
1 files changed, 55 insertions, 27 deletions
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 950f89948..29b696afa 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -6,6 +6,7 @@ use ra_db::{ | |||
6 | }; | 6 | }; |
7 | use relative_path::RelativePathBuf; | 7 | use relative_path::RelativePathBuf; |
8 | use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; | 8 | use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; |
9 | use rustc_hash::FxHashMap; | ||
9 | 10 | ||
10 | use crate::{db, HirInterner}; | 11 | use crate::{db, HirInterner}; |
11 | 12 | ||
@@ -21,82 +22,107 @@ pub struct MockDatabase { | |||
21 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, | 22 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, |
22 | runtime: salsa::Runtime<MockDatabase>, | 23 | runtime: salsa::Runtime<MockDatabase>, |
23 | interner: Arc<HirInterner>, | 24 | interner: Arc<HirInterner>, |
24 | file_counter: u32, | 25 | files: FxHashMap<String, FileId>, |
25 | } | 26 | } |
26 | 27 | ||
27 | impl panic::RefUnwindSafe for MockDatabase {} | 28 | impl panic::RefUnwindSafe for MockDatabase {} |
28 | 29 | ||
29 | impl MockDatabase { | 30 | impl MockDatabase { |
30 | pub fn with_files(fixture: &str) -> (MockDatabase, SourceRoot) { | 31 | pub fn with_files(fixture: &str) -> MockDatabase { |
31 | let (db, source_root, position) = MockDatabase::from_fixture(fixture); | 32 | let (db, position) = MockDatabase::from_fixture(fixture); |
32 | assert!(position.is_none()); | 33 | assert!(position.is_none()); |
33 | (db, source_root) | 34 | db |
34 | } | 35 | } |
35 | 36 | ||
36 | pub fn with_single_file(text: &str) -> (MockDatabase, SourceRoot, FileId) { | 37 | pub fn with_single_file(text: &str) -> (MockDatabase, SourceRoot, FileId) { |
37 | let mut db = MockDatabase::default(); | 38 | let mut db = MockDatabase::default(); |
38 | let mut source_root = SourceRoot::default(); | 39 | let mut source_root = SourceRoot::default(); |
39 | let file_id = db.add_file(WORKSPACE, &mut source_root, "/main.rs", text); | 40 | let file_id = db.add_file(WORKSPACE, "/", &mut source_root, "/main.rs", text); |
40 | db.set_source_root(WORKSPACE, Arc::new(source_root.clone())); | 41 | db.set_source_root(WORKSPACE, Arc::new(source_root.clone())); |
41 | (db, source_root, file_id) | 42 | (db, source_root, file_id) |
42 | } | 43 | } |
43 | 44 | ||
44 | pub fn with_position(fixture: &str) -> (MockDatabase, FilePosition) { | 45 | pub fn with_position(fixture: &str) -> (MockDatabase, FilePosition) { |
45 | let (db, _, position) = MockDatabase::from_fixture(fixture); | 46 | let (db, position) = MockDatabase::from_fixture(fixture); |
46 | let position = position.expect("expected a marker ( <|> )"); | 47 | let position = position.expect("expected a marker ( <|> )"); |
47 | (db, position) | 48 | (db, position) |
48 | } | 49 | } |
49 | 50 | ||
50 | fn from_fixture(fixture: &str) -> (MockDatabase, SourceRoot, Option<FilePosition>) { | 51 | pub fn file_id_of(&self, path: &str) -> FileId { |
52 | match self.files.get(path) { | ||
53 | Some(it) => *it, | ||
54 | None => panic!("unknown file: {:?}\nexisting files:\n{:#?}", path, self.files), | ||
55 | } | ||
56 | } | ||
57 | |||
58 | fn from_fixture(fixture: &str) -> (MockDatabase, Option<FilePosition>) { | ||
51 | let mut db = MockDatabase::default(); | 59 | let mut db = MockDatabase::default(); |
52 | 60 | ||
53 | let (source_root, pos) = db.add_fixture(WORKSPACE, fixture); | 61 | let pos = db.add_fixture(fixture); |
54 | 62 | ||
55 | (db, source_root, pos) | 63 | (db, pos) |
56 | } | 64 | } |
57 | 65 | ||
58 | pub fn add_fixture( | 66 | fn add_fixture(&mut self, fixture: &str) -> Option<FilePosition> { |
59 | &mut self, | ||
60 | source_root_id: SourceRootId, | ||
61 | fixture: &str, | ||
62 | ) -> (SourceRoot, Option<FilePosition>) { | ||
63 | let mut position = None; | 67 | let mut position = None; |
64 | let mut source_root = SourceRoot::default(); | 68 | let mut source_root = SourceRoot::default(); |
69 | let mut source_root_id = WORKSPACE; | ||
70 | let mut source_root_prefix = "/".to_string(); | ||
65 | for entry in parse_fixture(fixture) { | 71 | for entry in parse_fixture(fixture) { |
72 | if entry.meta.starts_with("root") { | ||
73 | self.set_source_root(source_root_id, Arc::new(source_root)); | ||
74 | source_root = SourceRoot::default(); | ||
75 | |||
76 | source_root_id = SourceRootId(source_root_id.0 + 1); | ||
77 | source_root_prefix = entry.meta["root".len()..].trim().to_string(); | ||
78 | continue; | ||
79 | } | ||
66 | if entry.text.contains(CURSOR_MARKER) { | 80 | if entry.text.contains(CURSOR_MARKER) { |
67 | assert!(position.is_none(), "only one marker (<|>) per fixture is allowed"); | 81 | assert!(position.is_none(), "only one marker (<|>) per fixture is allowed"); |
68 | position = Some(self.add_file_with_position( | 82 | position = Some(self.add_file_with_position( |
69 | source_root_id, | 83 | source_root_id, |
84 | &source_root_prefix, | ||
70 | &mut source_root, | 85 | &mut source_root, |
71 | &entry.meta, | 86 | &entry.meta, |
72 | &entry.text, | 87 | &entry.text, |
73 | )); | 88 | )); |
74 | } else { | 89 | } else { |
75 | self.add_file(source_root_id, &mut source_root, &entry.meta, &entry.text); | 90 | self.add_file( |
91 | source_root_id, | ||
92 | &source_root_prefix, | ||
93 | &mut source_root, | ||
94 | &entry.meta, | ||
95 | &entry.text, | ||
96 | ); | ||
76 | } | 97 | } |
77 | } | 98 | } |
78 | self.set_source_root(source_root_id, Arc::new(source_root.clone())); | 99 | self.set_source_root(source_root_id, Arc::new(source_root)); |
79 | (source_root, position) | 100 | position |
80 | } | 101 | } |
81 | 102 | ||
82 | fn add_file( | 103 | fn add_file( |
83 | &mut self, | 104 | &mut self, |
84 | source_root_id: SourceRootId, | 105 | source_root_id: SourceRootId, |
106 | source_root_prefix: &str, | ||
85 | source_root: &mut SourceRoot, | 107 | source_root: &mut SourceRoot, |
86 | path: &str, | 108 | path: &str, |
87 | text: &str, | 109 | text: &str, |
88 | ) -> FileId { | 110 | ) -> FileId { |
89 | assert!(path.starts_with('/')); | 111 | assert!(source_root_prefix.starts_with('/')); |
90 | let is_crate_root = path == "/lib.rs" || path == "/main.rs"; | 112 | assert!(source_root_prefix.ends_with('/')); |
113 | assert!(path.starts_with(source_root_prefix)); | ||
114 | let rel_path = RelativePathBuf::from_path(&path[source_root_prefix.len()..]).unwrap(); | ||
115 | |||
116 | let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs"; | ||
91 | 117 | ||
92 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); | 118 | let file_id = FileId(self.files.len() as u32); |
93 | let file_id = FileId(self.file_counter); | 119 | let prev = self.files.insert(path.to_string(), file_id); |
94 | self.file_counter += 1; | 120 | assert!(prev.is_none(), "duplicate files in the text fixture"); |
95 | let text = Arc::new(text.to_string()); | 121 | let text = Arc::new(text.to_string()); |
96 | self.set_file_text(file_id, text); | 122 | self.set_file_text(file_id, text); |
97 | self.set_file_relative_path(file_id, path.clone()); | 123 | self.set_file_relative_path(file_id, rel_path.clone()); |
98 | self.set_file_source_root(file_id, source_root_id); | 124 | self.set_file_source_root(file_id, source_root_id); |
99 | source_root.files.insert(path, file_id); | 125 | source_root.files.insert(rel_path, file_id); |
100 | 126 | ||
101 | if is_crate_root { | 127 | if is_crate_root { |
102 | let mut crate_graph = CrateGraph::default(); | 128 | let mut crate_graph = CrateGraph::default(); |
@@ -109,12 +135,13 @@ impl MockDatabase { | |||
109 | fn add_file_with_position( | 135 | fn add_file_with_position( |
110 | &mut self, | 136 | &mut self, |
111 | source_root_id: SourceRootId, | 137 | source_root_id: SourceRootId, |
138 | source_root_prefix: &str, | ||
112 | source_root: &mut SourceRoot, | 139 | source_root: &mut SourceRoot, |
113 | path: &str, | 140 | path: &str, |
114 | text: &str, | 141 | text: &str, |
115 | ) -> FilePosition { | 142 | ) -> FilePosition { |
116 | let (offset, text) = extract_offset(text); | 143 | let (offset, text) = extract_offset(text); |
117 | let file_id = self.add_file(source_root_id, source_root, path, &text); | 144 | let file_id = self.add_file(source_root_id, source_root_prefix, source_root, path, &text); |
118 | FilePosition { file_id, offset } | 145 | FilePosition { file_id, offset } |
119 | } | 146 | } |
120 | } | 147 | } |
@@ -138,7 +165,7 @@ impl Default for MockDatabase { | |||
138 | events: Default::default(), | 165 | events: Default::default(), |
139 | runtime: salsa::Runtime::default(), | 166 | runtime: salsa::Runtime::default(), |
140 | interner: Default::default(), | 167 | interner: Default::default(), |
141 | file_counter: 0, | 168 | files: FxHashMap::default(), |
142 | }; | 169 | }; |
143 | db.set_crate_graph(Default::default()); | 170 | db.set_crate_graph(Default::default()); |
144 | db | 171 | db |
@@ -151,7 +178,8 @@ impl salsa::ParallelDatabase for MockDatabase { | |||
151 | events: Default::default(), | 178 | events: Default::default(), |
152 | runtime: self.runtime.snapshot(self), | 179 | runtime: self.runtime.snapshot(self), |
153 | interner: Arc::clone(&self.interner), | 180 | interner: Arc::clone(&self.interner), |
154 | file_counter: self.file_counter, | 181 | // only the root database can be used to get file_id by path. |
182 | files: FxHashMap::default(), | ||
155 | }) | 183 | }) |
156 | } | 184 | } |
157 | } | 185 | } |