diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-12-20 09:16:07 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-12-20 09:16:07 +0000 |
commit | 9a16cf2bf646a4a881f3f5acbf5582dacc4337bf (patch) | |
tree | ff90eb390a8f5af47b6d0c6ec4c49b4431b82d1c /crates/ra_vfs/src/io.rs | |
parent | dbb62b5baa36783bbca06f09c77794fce3ceff0c (diff) | |
parent | a084412f0698d5f54d586f707930e141c88b0673 (diff) |
Merge #292
292: Vfs r=matklad a=matklad
closes #243
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_vfs/src/io.rs')
-rw-r--r-- | crates/ra_vfs/src/io.rs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/crates/ra_vfs/src/io.rs b/crates/ra_vfs/src/io.rs new file mode 100644 index 000000000..be400bae9 --- /dev/null +++ b/crates/ra_vfs/src/io.rs | |||
@@ -0,0 +1,76 @@ | |||
1 | use std::{ | ||
2 | fmt, | ||
3 | fs, | ||
4 | path::{Path, PathBuf}, | ||
5 | }; | ||
6 | |||
7 | use walkdir::{DirEntry, WalkDir}; | ||
8 | use thread_worker::{WorkerHandle}; | ||
9 | use relative_path::RelativePathBuf; | ||
10 | |||
11 | use crate::VfsRoot; | ||
12 | |||
13 | pub(crate) struct Task { | ||
14 | pub(crate) root: VfsRoot, | ||
15 | pub(crate) path: PathBuf, | ||
16 | pub(crate) filter: Box<Fn(&DirEntry) -> bool + Send>, | ||
17 | } | ||
18 | |||
19 | pub struct TaskResult { | ||
20 | pub(crate) root: VfsRoot, | ||
21 | pub(crate) files: Vec<(RelativePathBuf, String)>, | ||
22 | } | ||
23 | |||
24 | impl fmt::Debug for TaskResult { | ||
25 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
26 | f.write_str("TaskResult { ... }") | ||
27 | } | ||
28 | } | ||
29 | |||
30 | pub(crate) type Worker = thread_worker::Worker<Task, TaskResult>; | ||
31 | |||
32 | pub(crate) fn start() -> (Worker, WorkerHandle) { | ||
33 | thread_worker::spawn("vfs", 128, |input_receiver, output_sender| { | ||
34 | input_receiver | ||
35 | .map(handle_task) | ||
36 | .for_each(|it| output_sender.send(it)) | ||
37 | }) | ||
38 | } | ||
39 | |||
40 | fn handle_task(task: Task) -> TaskResult { | ||
41 | let Task { root, path, filter } = task; | ||
42 | log::debug!("loading {} ...", path.as_path().display()); | ||
43 | let files = load_root(path.as_path(), &*filter); | ||
44 | log::debug!("... loaded {}", path.as_path().display()); | ||
45 | TaskResult { root, files } | ||
46 | } | ||
47 | |||
48 | fn load_root(root: &Path, filter: &dyn Fn(&DirEntry) -> bool) -> Vec<(RelativePathBuf, String)> { | ||
49 | let mut res = Vec::new(); | ||
50 | for entry in WalkDir::new(root).into_iter().filter_entry(filter) { | ||
51 | let entry = match entry { | ||
52 | Ok(entry) => entry, | ||
53 | Err(e) => { | ||
54 | log::warn!("watcher error: {}", e); | ||
55 | continue; | ||
56 | } | ||
57 | }; | ||
58 | if !entry.file_type().is_file() { | ||
59 | continue; | ||
60 | } | ||
61 | let path = entry.path(); | ||
62 | if path.extension().and_then(|os| os.to_str()) != Some("rs") { | ||
63 | continue; | ||
64 | } | ||
65 | let text = match fs::read_to_string(path) { | ||
66 | Ok(text) => text, | ||
67 | Err(e) => { | ||
68 | log::warn!("watcher error: {}", e); | ||
69 | continue; | ||
70 | } | ||
71 | }; | ||
72 | let path = RelativePathBuf::from_path(path.strip_prefix(root).unwrap()).unwrap(); | ||
73 | res.push((path.to_owned(), text)) | ||
74 | } | ||
75 | res | ||
76 | } | ||