diff options
Diffstat (limited to 'crates/base_db')
-rw-r--r-- | crates/base_db/src/fixture.rs | 173 |
1 files changed, 90 insertions, 83 deletions
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs index 5ff8ead0e..48fa73bf0 100644 --- a/crates/base_db/src/fixture.rs +++ b/crates/base_db/src/fixture.rs | |||
@@ -65,24 +65,26 @@ use test_utils::{extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER} | |||
65 | use vfs::{file_set::FileSet, VfsPath}; | 65 | use vfs::{file_set::FileSet, VfsPath}; |
66 | 66 | ||
67 | use crate::{ | 67 | use crate::{ |
68 | input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, SourceDatabaseExt, | 68 | input::CrateName, Change, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, |
69 | SourceRoot, SourceRootId, | 69 | SourceDatabaseExt, SourceRoot, SourceRootId, |
70 | }; | 70 | }; |
71 | 71 | ||
72 | pub const WORKSPACE: SourceRootId = SourceRootId(0); | 72 | pub const WORKSPACE: SourceRootId = SourceRootId(0); |
73 | 73 | ||
74 | pub trait WithFixture: Default + SourceDatabaseExt + 'static { | 74 | pub trait WithFixture: Default + SourceDatabaseExt + 'static { |
75 | fn with_single_file(text: &str) -> (Self, FileId) { | 75 | fn with_single_file(text: &str) -> (Self, FileId) { |
76 | let fixture = ChangeFixture::parse(text); | ||
76 | let mut db = Self::default(); | 77 | let mut db = Self::default(); |
77 | let (_, files) = with_files(&mut db, text); | 78 | fixture.change.apply(&mut db); |
78 | assert_eq!(files.len(), 1); | 79 | assert_eq!(fixture.files.len(), 1); |
79 | (db, files[0]) | 80 | (db, fixture.files[0]) |
80 | } | 81 | } |
81 | 82 | ||
82 | fn with_files(ra_fixture: &str) -> Self { | 83 | fn with_files(ra_fixture: &str) -> Self { |
84 | let fixture = ChangeFixture::parse(ra_fixture); | ||
83 | let mut db = Self::default(); | 85 | let mut db = Self::default(); |
84 | let (pos, _) = with_files(&mut db, ra_fixture); | 86 | fixture.change.apply(&mut db); |
85 | assert!(pos.is_none()); | 87 | assert!(fixture.file_position.is_none()); |
86 | db | 88 | db |
87 | } | 89 | } |
88 | 90 | ||
@@ -96,9 +98,10 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { | |||
96 | } | 98 | } |
97 | 99 | ||
98 | fn with_range_or_offset(ra_fixture: &str) -> (Self, FileId, RangeOrOffset) { | 100 | fn with_range_or_offset(ra_fixture: &str) -> (Self, FileId, RangeOrOffset) { |
101 | let fixture = ChangeFixture::parse(ra_fixture); | ||
99 | let mut db = Self::default(); | 102 | let mut db = Self::default(); |
100 | let (pos, _) = with_files(&mut db, ra_fixture); | 103 | fixture.change.apply(&mut db); |
101 | let (file_id, range_or_offset) = pos.unwrap(); | 104 | let (file_id, range_or_offset) = fixture.file_position.unwrap(); |
102 | (db, file_id, range_or_offset) | 105 | (db, file_id, range_or_offset) |
103 | } | 106 | } |
104 | 107 | ||
@@ -113,89 +116,93 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { | |||
113 | 116 | ||
114 | impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {} | 117 | impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {} |
115 | 118 | ||
116 | fn with_files( | 119 | pub struct ChangeFixture { |
117 | db: &mut dyn SourceDatabaseExt, | 120 | file_position: Option<(FileId, RangeOrOffset)>, |
118 | fixture: &str, | 121 | files: Vec<FileId>, |
119 | ) -> (Option<(FileId, RangeOrOffset)>, Vec<FileId>) { | 122 | change: Change, |
120 | let fixture = Fixture::parse(fixture); | 123 | } |
121 | |||
122 | let mut files = Vec::new(); | ||
123 | let mut crate_graph = CrateGraph::default(); | ||
124 | let mut crates = FxHashMap::default(); | ||
125 | let mut crate_deps = Vec::new(); | ||
126 | let mut default_crate_root: Option<FileId> = None; | ||
127 | |||
128 | let mut file_set = FileSet::default(); | ||
129 | let source_root_id = WORKSPACE; | ||
130 | let source_root_prefix = "/".to_string(); | ||
131 | let mut file_id = FileId(0); | ||
132 | |||
133 | let mut file_position = None; | ||
134 | |||
135 | for entry in fixture { | ||
136 | let text = if entry.text.contains(CURSOR_MARKER) { | ||
137 | let (range_or_offset, text) = extract_range_or_offset(&entry.text); | ||
138 | assert!(file_position.is_none()); | ||
139 | file_position = Some((file_id, range_or_offset)); | ||
140 | text.to_string() | ||
141 | } else { | ||
142 | entry.text.clone() | ||
143 | }; | ||
144 | 124 | ||
145 | let meta = FileMeta::from(entry); | 125 | impl ChangeFixture { |
146 | assert!(meta.path.starts_with(&source_root_prefix)); | 126 | fn parse(ra_fixture: &str) -> ChangeFixture { |
127 | let fixture = Fixture::parse(ra_fixture); | ||
128 | let mut change = Change::new(); | ||
129 | |||
130 | let mut files = Vec::new(); | ||
131 | let mut crate_graph = CrateGraph::default(); | ||
132 | let mut crates = FxHashMap::default(); | ||
133 | let mut crate_deps = Vec::new(); | ||
134 | let mut default_crate_root: Option<FileId> = None; | ||
135 | |||
136 | let mut file_set = FileSet::default(); | ||
137 | let source_root_prefix = "/".to_string(); | ||
138 | let mut file_id = FileId(0); | ||
139 | |||
140 | let mut file_position = None; | ||
141 | |||
142 | for entry in fixture { | ||
143 | let text = if entry.text.contains(CURSOR_MARKER) { | ||
144 | let (range_or_offset, text) = extract_range_or_offset(&entry.text); | ||
145 | assert!(file_position.is_none()); | ||
146 | file_position = Some((file_id, range_or_offset)); | ||
147 | text.to_string() | ||
148 | } else { | ||
149 | entry.text.clone() | ||
150 | }; | ||
151 | |||
152 | let meta = FileMeta::from(entry); | ||
153 | assert!(meta.path.starts_with(&source_root_prefix)); | ||
154 | |||
155 | if let Some(krate) = meta.krate { | ||
156 | let crate_id = crate_graph.add_crate_root( | ||
157 | file_id, | ||
158 | meta.edition, | ||
159 | Some(krate.clone()), | ||
160 | meta.cfg, | ||
161 | meta.env, | ||
162 | Default::default(), | ||
163 | ); | ||
164 | let crate_name = CrateName::new(&krate).unwrap(); | ||
165 | let prev = crates.insert(crate_name.clone(), crate_id); | ||
166 | assert!(prev.is_none()); | ||
167 | for dep in meta.deps { | ||
168 | let dep = CrateName::new(&dep).unwrap(); | ||
169 | crate_deps.push((crate_name.clone(), dep)) | ||
170 | } | ||
171 | } else if meta.path == "/main.rs" || meta.path == "/lib.rs" { | ||
172 | assert!(default_crate_root.is_none()); | ||
173 | default_crate_root = Some(file_id); | ||
174 | } | ||
175 | |||
176 | change.change_file(file_id, Some(Arc::new(text))); | ||
177 | let path = VfsPath::new_virtual_path(meta.path); | ||
178 | file_set.insert(file_id, path.into()); | ||
179 | files.push(file_id); | ||
180 | file_id.0 += 1; | ||
181 | } | ||
147 | 182 | ||
148 | if let Some(krate) = meta.krate { | 183 | if crates.is_empty() { |
149 | let crate_id = crate_graph.add_crate_root( | 184 | let crate_root = default_crate_root.unwrap(); |
150 | file_id, | 185 | crate_graph.add_crate_root( |
151 | meta.edition, | 186 | crate_root, |
152 | Some(krate.clone()), | 187 | Edition::Edition2018, |
153 | meta.cfg, | 188 | None, |
154 | meta.env, | 189 | CfgOptions::default(), |
190 | Env::default(), | ||
155 | Default::default(), | 191 | Default::default(), |
156 | ); | 192 | ); |
157 | let crate_name = CrateName::new(&krate).unwrap(); | 193 | } else { |
158 | let prev = crates.insert(crate_name.clone(), crate_id); | 194 | for (from, to) in crate_deps { |
159 | assert!(prev.is_none()); | 195 | let from_id = crates[&from]; |
160 | for dep in meta.deps { | 196 | let to_id = crates[&to]; |
161 | let dep = CrateName::new(&dep).unwrap(); | 197 | crate_graph.add_dep(from_id, CrateName::new(&to).unwrap(), to_id).unwrap(); |
162 | crate_deps.push((crate_name.clone(), dep)) | ||
163 | } | 198 | } |
164 | } else if meta.path == "/main.rs" || meta.path == "/lib.rs" { | ||
165 | assert!(default_crate_root.is_none()); | ||
166 | default_crate_root = Some(file_id); | ||
167 | } | 199 | } |
168 | 200 | ||
169 | db.set_file_text(file_id, Arc::new(text)); | 201 | change.set_roots(vec![SourceRoot::new_local(file_set)]); |
170 | db.set_file_source_root(file_id, source_root_id); | 202 | change.set_crate_graph(crate_graph); |
171 | let path = VfsPath::new_virtual_path(meta.path); | ||
172 | file_set.insert(file_id, path.into()); | ||
173 | files.push(file_id); | ||
174 | file_id.0 += 1; | ||
175 | } | ||
176 | 203 | ||
177 | if crates.is_empty() { | 204 | ChangeFixture { file_position, files, change } |
178 | let crate_root = default_crate_root.unwrap(); | ||
179 | crate_graph.add_crate_root( | ||
180 | crate_root, | ||
181 | Edition::Edition2018, | ||
182 | None, | ||
183 | CfgOptions::default(), | ||
184 | Env::default(), | ||
185 | Default::default(), | ||
186 | ); | ||
187 | } else { | ||
188 | for (from, to) in crate_deps { | ||
189 | let from_id = crates[&from]; | ||
190 | let to_id = crates[&to]; | ||
191 | crate_graph.add_dep(from_id, CrateName::new(&to).unwrap(), to_id).unwrap(); | ||
192 | } | ||
193 | } | 205 | } |
194 | |||
195 | db.set_source_root(source_root_id, Arc::new(SourceRoot::new_local(file_set))); | ||
196 | db.set_crate_graph(Arc::new(crate_graph)); | ||
197 | |||
198 | (file_position, files) | ||
199 | } | 206 | } |
200 | 207 | ||
201 | struct FileMeta { | 208 | struct FileMeta { |