diff options
Diffstat (limited to 'crates/ra_vfs/src/lib.rs')
-rw-r--r-- | crates/ra_vfs/src/lib.rs | 165 |
1 files changed, 124 insertions, 41 deletions
diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs index 889ed788d..2930f6b80 100644 --- a/crates/ra_vfs/src/lib.rs +++ b/crates/ra_vfs/src/lib.rs | |||
@@ -75,6 +75,7 @@ impl_arena_id!(VfsFile); | |||
75 | struct VfsFileData { | 75 | struct VfsFileData { |
76 | root: VfsRoot, | 76 | root: VfsRoot, |
77 | path: RelativePathBuf, | 77 | path: RelativePathBuf, |
78 | is_overlayed: bool, | ||
78 | text: Arc<String>, | 79 | text: Arc<String>, |
79 | } | 80 | } |
80 | 81 | ||
@@ -170,7 +171,7 @@ impl Vfs { | |||
170 | } else { | 171 | } else { |
171 | let text = fs::read_to_string(path).unwrap_or_default(); | 172 | let text = fs::read_to_string(path).unwrap_or_default(); |
172 | let text = Arc::new(text); | 173 | let text = Arc::new(text); |
173 | let file = self.add_file(root, rel_path.clone(), Arc::clone(&text)); | 174 | let file = self.add_file(root, rel_path.clone(), Arc::clone(&text), false); |
174 | let change = VfsChange::AddFile { | 175 | let change = VfsChange::AddFile { |
175 | file, | 176 | file, |
176 | text, | 177 | text, |
@@ -205,7 +206,7 @@ impl Vfs { | |||
205 | continue; | 206 | continue; |
206 | } | 207 | } |
207 | let text = Arc::new(text); | 208 | let text = Arc::new(text); |
208 | let file = self.add_file(task.root, path.clone(), Arc::clone(&text)); | 209 | let file = self.add_file(task.root, path.clone(), Arc::clone(&text), false); |
209 | files.push((file, path, text)); | 210 | files.push((file, path, text)); |
210 | } | 211 | } |
211 | 212 | ||
@@ -215,63 +216,132 @@ impl Vfs { | |||
215 | }; | 216 | }; |
216 | self.pending_changes.push(change); | 217 | self.pending_changes.push(change); |
217 | } | 218 | } |
218 | io::TaskResult::WatcherChange(change) => { | 219 | io::TaskResult::HandleChange(change) => match &change { |
219 | // TODO | 220 | watcher::WatcherChange::Create(path) |
220 | unimplemented!() | 221 | | watcher::WatcherChange::Remove(path) |
222 | | watcher::WatcherChange::Write(path) => { | ||
223 | if self.should_handle_change(&path) { | ||
224 | self.worker.inp.send(io::Task::LoadChange(change)).unwrap() | ||
225 | } | ||
226 | } | ||
227 | watcher::WatcherChange::Rescan => { | ||
228 | // TODO send Task::AddRoot? | ||
229 | } | ||
230 | }, | ||
231 | io::TaskResult::LoadChange(None) => {} | ||
232 | io::TaskResult::LoadChange(Some(change)) => match change { | ||
233 | io::WatcherChangeData::Create { path, text } | ||
234 | | io::WatcherChangeData::Write { path, text } => { | ||
235 | if let Some((root, path, file)) = self.find_root(&path) { | ||
236 | if let Some(file) = file { | ||
237 | self.do_change_file(file, text, false); | ||
238 | } else { | ||
239 | self.do_add_file(root, path, text, false); | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | io::WatcherChangeData::Remove { path } => { | ||
244 | if let Some((root, path, file)) = self.find_root(&path) { | ||
245 | if let Some(file) = file { | ||
246 | self.do_remove_file(root, path, file, false); | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | }, | ||
251 | } | ||
252 | } | ||
253 | |||
254 | fn should_handle_change(&self, path: &Path) -> bool { | ||
255 | if let Some((_root, _rel_path, file)) = self.find_root(&path) { | ||
256 | if let Some(file) = file { | ||
257 | if self.files[file].is_overlayed { | ||
258 | // file is overlayed | ||
259 | return false; | ||
260 | } | ||
221 | } | 261 | } |
262 | true | ||
263 | } else { | ||
264 | // file doesn't belong to any root | ||
265 | false | ||
222 | } | 266 | } |
223 | } | 267 | } |
224 | 268 | ||
269 | fn do_add_file( | ||
270 | &mut self, | ||
271 | root: VfsRoot, | ||
272 | path: RelativePathBuf, | ||
273 | text: String, | ||
274 | is_overlay: bool, | ||
275 | ) -> Option<VfsFile> { | ||
276 | let text = Arc::new(text); | ||
277 | let file = self.add_file(root, path.clone(), text.clone(), is_overlay); | ||
278 | self.pending_changes.push(VfsChange::AddFile { | ||
279 | file, | ||
280 | root, | ||
281 | path, | ||
282 | text, | ||
283 | }); | ||
284 | Some(file) | ||
285 | } | ||
286 | |||
287 | fn do_change_file(&mut self, file: VfsFile, text: String, is_overlay: bool) { | ||
288 | if !is_overlay && self.files[file].is_overlayed { | ||
289 | return; | ||
290 | } | ||
291 | let text = Arc::new(text); | ||
292 | self.change_file(file, text.clone(), is_overlay); | ||
293 | self.pending_changes | ||
294 | .push(VfsChange::ChangeFile { file, text }); | ||
295 | } | ||
296 | |||
297 | fn do_remove_file( | ||
298 | &mut self, | ||
299 | root: VfsRoot, | ||
300 | path: RelativePathBuf, | ||
301 | file: VfsFile, | ||
302 | is_overlay: bool, | ||
303 | ) { | ||
304 | if !is_overlay && self.files[file].is_overlayed { | ||
305 | return; | ||
306 | } | ||
307 | self.remove_file(file); | ||
308 | self.pending_changes | ||
309 | .push(VfsChange::RemoveFile { root, path, file }); | ||
310 | } | ||
311 | |||
225 | pub fn add_file_overlay(&mut self, path: &Path, text: String) -> Option<VfsFile> { | 312 | pub fn add_file_overlay(&mut self, path: &Path, text: String) -> Option<VfsFile> { |
226 | let mut res = None; | ||
227 | if let Some((root, rel_path, file)) = self.find_root(path) { | 313 | if let Some((root, rel_path, file)) = self.find_root(path) { |
228 | let text = Arc::new(text); | 314 | if let Some(file) = file { |
229 | let change = if let Some(file) = file { | 315 | self.do_change_file(file, text, true); |
230 | res = Some(file); | 316 | Some(file) |
231 | self.change_file(file, Arc::clone(&text)); | ||
232 | VfsChange::ChangeFile { file, text } | ||
233 | } else { | 317 | } else { |
234 | let file = self.add_file(root, rel_path.clone(), Arc::clone(&text)); | 318 | self.do_add_file(root, rel_path, text, true) |
235 | res = Some(file); | 319 | } |
236 | VfsChange::AddFile { | 320 | } else { |
237 | file, | 321 | None |
238 | text, | ||
239 | root, | ||
240 | path: rel_path, | ||
241 | } | ||
242 | }; | ||
243 | self.pending_changes.push(change); | ||
244 | } | 322 | } |
245 | res | ||
246 | } | 323 | } |
247 | 324 | ||
248 | pub fn change_file_overlay(&mut self, path: &Path, new_text: String) { | 325 | pub fn change_file_overlay(&mut self, path: &Path, new_text: String) { |
249 | if let Some((_root, _path, file)) = self.find_root(path) { | 326 | if let Some((_root, _path, file)) = self.find_root(path) { |
250 | let file = file.expect("can't change a file which wasn't added"); | 327 | let file = file.expect("can't change a file which wasn't added"); |
251 | let text = Arc::new(new_text); | 328 | self.do_change_file(file, new_text, true); |
252 | self.change_file(file, Arc::clone(&text)); | ||
253 | let change = VfsChange::ChangeFile { file, text }; | ||
254 | self.pending_changes.push(change); | ||
255 | } | 329 | } |
256 | } | 330 | } |
257 | 331 | ||
258 | pub fn remove_file_overlay(&mut self, path: &Path) -> Option<VfsFile> { | 332 | pub fn remove_file_overlay(&mut self, path: &Path) -> Option<VfsFile> { |
259 | let mut res = None; | ||
260 | if let Some((root, path, file)) = self.find_root(path) { | 333 | if let Some((root, path, file)) = self.find_root(path) { |
261 | let file = file.expect("can't remove a file which wasn't added"); | 334 | let file = file.expect("can't remove a file which wasn't added"); |
262 | res = Some(file); | ||
263 | let full_path = path.to_path(&self.roots[root].root); | 335 | let full_path = path.to_path(&self.roots[root].root); |
264 | let change = if let Ok(text) = fs::read_to_string(&full_path) { | 336 | if let Ok(text) = fs::read_to_string(&full_path) { |
265 | let text = Arc::new(text); | 337 | self.do_change_file(file, text, true); |
266 | self.change_file(file, Arc::clone(&text)); | ||
267 | VfsChange::ChangeFile { file, text } | ||
268 | } else { | 338 | } else { |
269 | self.remove_file(file); | 339 | self.do_remove_file(root, path, file, true); |
270 | VfsChange::RemoveFile { root, file, path } | 340 | } |
271 | }; | 341 | Some(file) |
272 | self.pending_changes.push(change); | 342 | } else { |
343 | None | ||
273 | } | 344 | } |
274 | res | ||
275 | } | 345 | } |
276 | 346 | ||
277 | pub fn commit_changes(&mut self) -> Vec<VfsChange> { | 347 | pub fn commit_changes(&mut self) -> Vec<VfsChange> { |
@@ -285,15 +355,28 @@ impl Vfs { | |||
285 | self.worker_handle.shutdown() | 355 | self.worker_handle.shutdown() |
286 | } | 356 | } |
287 | 357 | ||
288 | fn add_file(&mut self, root: VfsRoot, path: RelativePathBuf, text: Arc<String>) -> VfsFile { | 358 | fn add_file( |
289 | let data = VfsFileData { root, path, text }; | 359 | &mut self, |
360 | root: VfsRoot, | ||
361 | path: RelativePathBuf, | ||
362 | text: Arc<String>, | ||
363 | is_overlayed: bool, | ||
364 | ) -> VfsFile { | ||
365 | let data = VfsFileData { | ||
366 | root, | ||
367 | path, | ||
368 | text, | ||
369 | is_overlayed, | ||
370 | }; | ||
290 | let file = self.files.alloc(data); | 371 | let file = self.files.alloc(data); |
291 | self.root2files.get_mut(&root).unwrap().insert(file); | 372 | self.root2files.get_mut(&root).unwrap().insert(file); |
292 | file | 373 | file |
293 | } | 374 | } |
294 | 375 | ||
295 | fn change_file(&mut self, file: VfsFile, new_text: Arc<String>) { | 376 | fn change_file(&mut self, file: VfsFile, new_text: Arc<String>, is_overlayed: bool) { |
296 | self.files[file].text = new_text; | 377 | let mut file_data = &mut self.files[file]; |
378 | file_data.text = new_text; | ||
379 | file_data.is_overlayed = is_overlayed; | ||
297 | } | 380 | } |
298 | 381 | ||
299 | fn remove_file(&mut self, file: VfsFile) { | 382 | fn remove_file(&mut self, file: VfsFile) { |