diff options
Diffstat (limited to 'crates/ra_vfs')
-rw-r--r-- | crates/ra_vfs/src/io.rs | 57 | ||||
-rw-r--r-- | crates/ra_vfs/src/lib.rs | 86 | ||||
-rw-r--r-- | crates/ra_vfs/tests/vfs.rs | 62 |
3 files changed, 45 insertions, 160 deletions
diff --git a/crates/ra_vfs/src/io.rs b/crates/ra_vfs/src/io.rs index d764c534a..ff5ae3a19 100644 --- a/crates/ra_vfs/src/io.rs +++ b/crates/ra_vfs/src/io.rs | |||
@@ -14,32 +14,15 @@ use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher as _Watc | |||
14 | use crate::{RootConfig, Roots, VfsRoot}; | 14 | use crate::{RootConfig, Roots, VfsRoot}; |
15 | 15 | ||
16 | pub(crate) enum Task { | 16 | pub(crate) enum Task { |
17 | AddRoot { | 17 | AddRoot { root: VfsRoot, config: Arc<RootConfig> }, |
18 | root: VfsRoot, | ||
19 | config: Arc<RootConfig>, | ||
20 | }, | ||
21 | } | 18 | } |
22 | 19 | ||
23 | #[derive(Debug)] | 20 | #[derive(Debug)] |
24 | pub enum TaskResult { | 21 | pub enum TaskResult { |
25 | BulkLoadRoot { | 22 | BulkLoadRoot { root: VfsRoot, files: Vec<(RelativePathBuf, String)> }, |
26 | root: VfsRoot, | 23 | AddSingleFile { root: VfsRoot, path: RelativePathBuf, text: String }, |
27 | files: Vec<(RelativePathBuf, String)>, | 24 | ChangeSingleFile { root: VfsRoot, path: RelativePathBuf, text: String }, |
28 | }, | 25 | RemoveSingleFile { root: VfsRoot, path: RelativePathBuf }, |
29 | AddSingleFile { | ||
30 | root: VfsRoot, | ||
31 | path: RelativePathBuf, | ||
32 | text: String, | ||
33 | }, | ||
34 | ChangeSingleFile { | ||
35 | root: VfsRoot, | ||
36 | path: RelativePathBuf, | ||
37 | text: String, | ||
38 | }, | ||
39 | RemoveSingleFile { | ||
40 | root: VfsRoot, | ||
41 | path: RelativePathBuf, | ||
42 | }, | ||
43 | } | 26 | } |
44 | 27 | ||
45 | #[derive(Debug)] | 28 | #[derive(Debug)] |
@@ -127,10 +110,7 @@ impl Worker { | |||
127 | }, | 110 | }, |
128 | ); | 111 | ); |
129 | 112 | ||
130 | Worker { | 113 | Worker { worker, worker_handle } |
131 | worker, | ||
132 | worker_handle, | ||
133 | } | ||
134 | } | 114 | } |
135 | 115 | ||
136 | pub(crate) fn sender(&self) -> &Sender<Task> { | 116 | pub(crate) fn sender(&self) -> &Sender<Task> { |
@@ -162,9 +142,7 @@ fn watch_root( | |||
162 | Some((path, text)) | 142 | Some((path, text)) |
163 | }) | 143 | }) |
164 | .collect(); | 144 | .collect(); |
165 | sender | 145 | sender.send(TaskResult::BulkLoadRoot { root, files }).unwrap(); |
166 | .send(TaskResult::BulkLoadRoot { root, files }) | ||
167 | .unwrap(); | ||
168 | log::debug!("... loaded {}", config.root.as_path().display()); | 146 | log::debug!("... loaded {}", config.root.as_path().display()); |
169 | } | 147 | } |
170 | 148 | ||
@@ -233,21 +211,12 @@ fn handle_change( | |||
233 | } | 211 | } |
234 | ChangeKind::Write => { | 212 | ChangeKind::Write => { |
235 | if let Some(text) = read_to_string(&path) { | 213 | if let Some(text) = read_to_string(&path) { |
236 | sender | 214 | sender.send(TaskResult::ChangeSingleFile { root, path: rel_path, text }).unwrap(); |
237 | .send(TaskResult::ChangeSingleFile { | ||
238 | root, | ||
239 | path: rel_path, | ||
240 | text, | ||
241 | }) | ||
242 | .unwrap(); | ||
243 | } | 215 | } |
244 | } | 216 | } |
245 | ChangeKind::Remove => sender | 217 | ChangeKind::Remove => { |
246 | .send(TaskResult::RemoveSingleFile { | 218 | sender.send(TaskResult::RemoveSingleFile { root, path: rel_path }).unwrap() |
247 | root, | 219 | } |
248 | path: rel_path, | ||
249 | }) | ||
250 | .unwrap(), | ||
251 | } | 220 | } |
252 | } | 221 | } |
253 | 222 | ||
@@ -282,7 +251,5 @@ fn watch_one(watcher: &mut RecommendedWatcher, dir: &Path) { | |||
282 | } | 251 | } |
283 | 252 | ||
284 | fn read_to_string(path: &Path) -> Option<String> { | 253 | fn read_to_string(path: &Path) -> Option<String> { |
285 | fs::read_to_string(&path) | 254 | fs::read_to_string(&path).map_err(|e| log::warn!("failed to read file {}", e)).ok() |
286 | .map_err(|e| log::warn!("failed to read file {}", e)) | ||
287 | .ok() | ||
288 | } | 255 | } |
diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs index 71a3f807d..6b4eb6842 100644 --- a/crates/ra_vfs/src/lib.rs +++ b/crates/ra_vfs/src/lib.rs | |||
@@ -58,10 +58,7 @@ impl std::ops::Deref for Roots { | |||
58 | 58 | ||
59 | impl RootConfig { | 59 | impl RootConfig { |
60 | fn new(root: PathBuf, excluded_dirs: Vec<PathBuf>) -> RootConfig { | 60 | fn new(root: PathBuf, excluded_dirs: Vec<PathBuf>) -> RootConfig { |
61 | RootConfig { | 61 | RootConfig { root, excluded_dirs } |
62 | root, | ||
63 | excluded_dirs, | ||
64 | } | ||
65 | } | 62 | } |
66 | /// Cheks if root contains a path and returns a root-relative path. | 63 | /// Cheks if root contains a path and returns a root-relative path. |
67 | pub(crate) fn contains(&self, path: &Path) -> Option<RelativePathBuf> { | 64 | pub(crate) fn contains(&self, path: &Path) -> Option<RelativePathBuf> { |
@@ -111,9 +108,7 @@ impl Roots { | |||
111 | Roots { roots } | 108 | Roots { roots } |
112 | } | 109 | } |
113 | pub(crate) fn find(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf)> { | 110 | pub(crate) fn find(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf)> { |
114 | self.roots | 111 | self.roots.iter().find_map(|(root, data)| data.contains(path).map(|it| (root, it))) |
115 | .iter() | ||
116 | .find_map(|(root, data)| data.contains(path).map(|it| (root, it))) | ||
117 | } | 112 | } |
118 | } | 113 | } |
119 | 114 | ||
@@ -154,21 +149,10 @@ impl Vfs { | |||
154 | 149 | ||
155 | for (root, config) in roots.iter() { | 150 | for (root, config) in roots.iter() { |
156 | root2files.insert(root, Default::default()); | 151 | root2files.insert(root, Default::default()); |
157 | worker | 152 | worker.sender().send(io::Task::AddRoot { root, config: Arc::clone(config) }).unwrap(); |
158 | .sender() | ||
159 | .send(io::Task::AddRoot { | ||
160 | root, | ||
161 | config: Arc::clone(config), | ||
162 | }) | ||
163 | .unwrap(); | ||
164 | } | 153 | } |
165 | let res = Vfs { | 154 | let res = |
166 | roots, | 155 | Vfs { roots, files: Arena::default(), root2files, worker, pending_changes: Vec::new() }; |
167 | files: Arena::default(), | ||
168 | root2files, | ||
169 | worker, | ||
170 | pending_changes: Vec::new(), | ||
171 | }; | ||
172 | let vfs_roots = res.roots.iter().map(|(id, _)| id).collect(); | 156 | let vfs_roots = res.roots.iter().map(|(id, _)| id).collect(); |
173 | (res, vfs_roots) | 157 | (res, vfs_roots) |
174 | } | 158 | } |
@@ -205,12 +189,7 @@ impl Vfs { | |||
205 | let text = fs::read_to_string(path).unwrap_or_default(); | 189 | let text = fs::read_to_string(path).unwrap_or_default(); |
206 | let text = Arc::new(text); | 190 | let text = Arc::new(text); |
207 | let file = self.add_file(root, rel_path.clone(), Arc::clone(&text), false); | 191 | let file = self.add_file(root, rel_path.clone(), Arc::clone(&text), false); |
208 | let change = VfsChange::AddFile { | 192 | let change = VfsChange::AddFile { file, text, root, path: rel_path }; |
209 | file, | ||
210 | text, | ||
211 | root, | ||
212 | path: rel_path, | ||
213 | }; | ||
214 | self.pending_changes.push(change); | 193 | self.pending_changes.push(change); |
215 | Some(file) | 194 | Some(file) |
216 | }; | 195 | }; |
@@ -243,10 +222,7 @@ impl Vfs { | |||
243 | cur_files.push((file, path, text)); | 222 | cur_files.push((file, path, text)); |
244 | } | 223 | } |
245 | 224 | ||
246 | let change = VfsChange::AddRoot { | 225 | let change = VfsChange::AddRoot { root, files: cur_files }; |
247 | root, | ||
248 | files: cur_files, | ||
249 | }; | ||
250 | self.pending_changes.push(change); | 226 | self.pending_changes.push(change); |
251 | } | 227 | } |
252 | TaskResult::AddSingleFile { root, path, text } => { | 228 | TaskResult::AddSingleFile { root, path, text } => { |
@@ -278,12 +254,7 @@ impl Vfs { | |||
278 | ) -> Option<VfsFile> { | 254 | ) -> Option<VfsFile> { |
279 | let text = Arc::new(text); | 255 | let text = Arc::new(text); |
280 | let file = self.add_file(root, path.clone(), text.clone(), is_overlay); | 256 | let file = self.add_file(root, path.clone(), text.clone(), is_overlay); |
281 | self.pending_changes.push(VfsChange::AddFile { | 257 | self.pending_changes.push(VfsChange::AddFile { file, root, path, text }); |
282 | file, | ||
283 | root, | ||
284 | path, | ||
285 | text, | ||
286 | }); | ||
287 | Some(file) | 258 | Some(file) |
288 | } | 259 | } |
289 | 260 | ||
@@ -293,8 +264,7 @@ impl Vfs { | |||
293 | } | 264 | } |
294 | let text = Arc::new(text); | 265 | let text = Arc::new(text); |
295 | self.change_file(file, text.clone(), is_overlay); | 266 | self.change_file(file, text.clone(), is_overlay); |
296 | self.pending_changes | 267 | self.pending_changes.push(VfsChange::ChangeFile { file, text }); |
297 | .push(VfsChange::ChangeFile { file, text }); | ||
298 | } | 268 | } |
299 | 269 | ||
300 | fn do_remove_file( | 270 | fn do_remove_file( |
@@ -308,8 +278,7 @@ impl Vfs { | |||
308 | return; | 278 | return; |
309 | } | 279 | } |
310 | self.remove_file(file); | 280 | self.remove_file(file); |
311 | self.pending_changes | 281 | self.pending_changes.push(VfsChange::RemoveFile { root, path, file }); |
312 | .push(VfsChange::RemoveFile { root, path, file }); | ||
313 | } | 282 | } |
314 | 283 | ||
315 | pub fn add_file_overlay(&mut self, path: &Path, text: String) -> Option<VfsFile> { | 284 | pub fn add_file_overlay(&mut self, path: &Path, text: String) -> Option<VfsFile> { |
@@ -363,12 +332,7 @@ impl Vfs { | |||
363 | text: Arc<String>, | 332 | text: Arc<String>, |
364 | is_overlayed: bool, | 333 | is_overlayed: bool, |
365 | ) -> VfsFile { | 334 | ) -> VfsFile { |
366 | let data = VfsFileData { | 335 | let data = VfsFileData { root, path, text, is_overlayed }; |
367 | root, | ||
368 | path, | ||
369 | text, | ||
370 | is_overlayed, | ||
371 | }; | ||
372 | let file = self.files.alloc(data); | 336 | let file = self.files.alloc(data); |
373 | self.root2files.get_mut(root).unwrap().insert(file); | 337 | self.root2files.get_mut(root).unwrap().insert(file); |
374 | file | 338 | file |
@@ -396,32 +360,14 @@ impl Vfs { | |||
396 | } | 360 | } |
397 | 361 | ||
398 | fn find_file(&self, root: VfsRoot, path: &RelativePath) -> Option<VfsFile> { | 362 | fn find_file(&self, root: VfsRoot, path: &RelativePath) -> Option<VfsFile> { |
399 | self.root2files[root] | 363 | self.root2files[root].iter().map(|&it| it).find(|&file| self.files[file].path == path) |
400 | .iter() | ||
401 | .map(|&it| it) | ||
402 | .find(|&file| self.files[file].path == path) | ||
403 | } | 364 | } |
404 | } | 365 | } |
405 | 366 | ||
406 | #[derive(Debug, Clone)] | 367 | #[derive(Debug, Clone)] |
407 | pub enum VfsChange { | 368 | pub enum VfsChange { |
408 | AddRoot { | 369 | AddRoot { root: VfsRoot, files: Vec<(VfsFile, RelativePathBuf, Arc<String>)> }, |
409 | root: VfsRoot, | 370 | AddFile { root: VfsRoot, file: VfsFile, path: RelativePathBuf, text: Arc<String> }, |
410 | files: Vec<(VfsFile, RelativePathBuf, Arc<String>)>, | 371 | RemoveFile { root: VfsRoot, file: VfsFile, path: RelativePathBuf }, |
411 | }, | 372 | ChangeFile { file: VfsFile, text: Arc<String> }, |
412 | AddFile { | ||
413 | root: VfsRoot, | ||
414 | file: VfsFile, | ||
415 | path: RelativePathBuf, | ||
416 | text: Arc<String>, | ||
417 | }, | ||
418 | RemoveFile { | ||
419 | root: VfsRoot, | ||
420 | file: VfsFile, | ||
421 | path: RelativePathBuf, | ||
422 | }, | ||
423 | ChangeFile { | ||
424 | file: VfsFile, | ||
425 | text: Arc<String>, | ||
426 | }, | ||
427 | } | 373 | } |
diff --git a/crates/ra_vfs/tests/vfs.rs b/crates/ra_vfs/tests/vfs.rs index 545e1dbdd..649ef96c9 100644 --- a/crates/ra_vfs/tests/vfs.rs +++ b/crates/ra_vfs/tests/vfs.rs | |||
@@ -7,10 +7,7 @@ use tempfile::tempdir; | |||
7 | 7 | ||
8 | fn process_tasks(vfs: &mut Vfs, num_tasks: u32) { | 8 | fn process_tasks(vfs: &mut Vfs, num_tasks: u32) { |
9 | for _ in 0..num_tasks { | 9 | for _ in 0..num_tasks { |
10 | let task = vfs | 10 | let task = vfs.task_receiver().recv_timeout(Duration::from_secs(3)).unwrap(); |
11 | .task_receiver() | ||
12 | .recv_timeout(Duration::from_secs(3)) | ||
13 | .unwrap(); | ||
14 | log::debug!("{:?}", task); | 11 | log::debug!("{:?}", task); |
15 | vfs.handle_task(task); | 12 | vfs.handle_task(task); |
16 | } | 13 | } |
@@ -32,11 +29,7 @@ macro_rules! assert_match { | |||
32 | fn test_vfs_works() -> std::io::Result<()> { | 29 | fn test_vfs_works() -> std::io::Result<()> { |
33 | // Logger::with_str("vfs=debug,ra_vfs=debug").start().unwrap(); | 30 | // Logger::with_str("vfs=debug,ra_vfs=debug").start().unwrap(); |
34 | 31 | ||
35 | let files = [ | 32 | let files = [("a/foo.rs", "hello"), ("a/bar.rs", "world"), ("a/b/baz.rs", "nested hello")]; |
36 | ("a/foo.rs", "hello"), | ||
37 | ("a/bar.rs", "world"), | ||
38 | ("a/b/baz.rs", "nested hello"), | ||
39 | ]; | ||
40 | 33 | ||
41 | let dir = tempdir().unwrap(); | 34 | let dir = tempdir().unwrap(); |
42 | for (path, text) in files.iter() { | 35 | for (path, text) in files.iter() { |
@@ -66,14 +59,10 @@ fn test_vfs_works() -> std::io::Result<()> { | |||
66 | }) | 59 | }) |
67 | .collect::<HashSet<_>>(); | 60 | .collect::<HashSet<_>>(); |
68 | 61 | ||
69 | let expected_files = [ | 62 | let expected_files = [("foo.rs", "hello"), ("bar.rs", "world"), ("baz.rs", "nested hello")] |
70 | ("foo.rs", "hello"), | 63 | .iter() |
71 | ("bar.rs", "world"), | 64 | .map(|(path, text)| (path.to_string(), text.to_string())) |
72 | ("baz.rs", "nested hello"), | 65 | .collect::<HashSet<_>>(); |
73 | ] | ||
74 | .iter() | ||
75 | .map(|(path, text)| (path.to_string(), text.to_string())) | ||
76 | .collect::<HashSet<_>>(); | ||
77 | 66 | ||
78 | assert_eq!(files, expected_files); | 67 | assert_eq!(files, expected_files); |
79 | } | 68 | } |
@@ -107,14 +96,10 @@ fn test_vfs_works() -> std::io::Result<()> { | |||
107 | ); | 96 | ); |
108 | 97 | ||
109 | vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), "spam".to_string()); | 98 | vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), "spam".to_string()); |
110 | assert_match!( | 99 | assert_match!(vfs.commit_changes().as_slice(), [VfsChange::AddFile { text, path, .. }], { |
111 | vfs.commit_changes().as_slice(), | 100 | assert_eq!(text.as_str(), "spam"); |
112 | [VfsChange::AddFile { text, path, .. }], | 101 | assert_eq!(path, "spam.rs"); |
113 | { | 102 | }); |
114 | assert_eq!(text.as_str(), "spam"); | ||
115 | assert_eq!(path, "spam.rs"); | ||
116 | } | ||
117 | ); | ||
118 | 103 | ||
119 | vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs")); | 104 | vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs")); |
120 | assert_match!( | 105 | assert_match!( |
@@ -126,30 +111,17 @@ fn test_vfs_works() -> std::io::Result<()> { | |||
126 | fs::create_dir_all(dir.path().join("a/sub1/sub2")).unwrap(); | 111 | fs::create_dir_all(dir.path().join("a/sub1/sub2")).unwrap(); |
127 | fs::write(dir.path().join("a/sub1/sub2/new.rs"), "new hello").unwrap(); | 112 | fs::write(dir.path().join("a/sub1/sub2/new.rs"), "new hello").unwrap(); |
128 | process_tasks(&mut vfs, 1); | 113 | process_tasks(&mut vfs, 1); |
129 | assert_match!( | 114 | assert_match!(vfs.commit_changes().as_slice(), [VfsChange::AddFile { text, path, .. }], { |
130 | vfs.commit_changes().as_slice(), | 115 | assert_eq!(text.as_str(), "new hello"); |
131 | [VfsChange::AddFile { text, path, .. }], | 116 | assert_eq!(path, "sub1/sub2/new.rs"); |
132 | { | 117 | }); |
133 | assert_eq!(text.as_str(), "new hello"); | ||
134 | assert_eq!(path, "sub1/sub2/new.rs"); | ||
135 | } | ||
136 | ); | ||
137 | 118 | ||
138 | fs::rename( | 119 | fs::rename(&dir.path().join("a/sub1/sub2/new.rs"), &dir.path().join("a/sub1/sub2/new1.rs")) |
139 | &dir.path().join("a/sub1/sub2/new.rs"), | 120 | .unwrap(); |
140 | &dir.path().join("a/sub1/sub2/new1.rs"), | ||
141 | ) | ||
142 | .unwrap(); | ||
143 | process_tasks(&mut vfs, 2); | 121 | process_tasks(&mut vfs, 2); |
144 | assert_match!( | 122 | assert_match!( |
145 | vfs.commit_changes().as_slice(), | 123 | vfs.commit_changes().as_slice(), |
146 | [VfsChange::RemoveFile { | 124 | [VfsChange::RemoveFile { path: removed_path, .. }, VfsChange::AddFile { text, path: added_path, .. }], |
147 | path: removed_path, .. | ||
148 | }, VfsChange::AddFile { | ||
149 | text, | ||
150 | path: added_path, | ||
151 | .. | ||
152 | }], | ||
153 | { | 125 | { |
154 | assert_eq!(removed_path, "sub1/sub2/new.rs"); | 126 | assert_eq!(removed_path, "sub1/sub2/new.rs"); |
155 | assert_eq!(added_path, "sub1/sub2/new1.rs"); | 127 | assert_eq!(added_path, "sub1/sub2/new1.rs"); |