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.rs82
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};
7use relative_path::RelativePathBuf; 7use relative_path::RelativePathBuf;
8use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; 8use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
9use rustc_hash::FxHashMap;
9 10
10use crate::{db, HirInterner}; 11use 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
27impl panic::RefUnwindSafe for MockDatabase {} 28impl panic::RefUnwindSafe for MockDatabase {}
28 29
29impl MockDatabase { 30impl 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}