diff options
-rw-r--r-- | crates/ra_vfs/src/lib.rs | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs index f6b45c18a..cba3a463a 100644 --- a/crates/ra_vfs/src/lib.rs +++ b/crates/ra_vfs/src/lib.rs | |||
@@ -18,6 +18,7 @@ mod io; | |||
18 | use std::{ | 18 | use std::{ |
19 | cmp::Reverse, | 19 | cmp::Reverse, |
20 | fmt, fs, mem, | 20 | fmt, fs, mem, |
21 | ops::{Deref, DerefMut}, | ||
21 | path::{Path, PathBuf}, | 22 | path::{Path, PathBuf}, |
22 | sync::Arc, | 23 | sync::Arc, |
23 | thread, | 24 | thread, |
@@ -88,8 +89,38 @@ struct VfsFileData { | |||
88 | text: Arc<String>, | 89 | text: Arc<String>, |
89 | } | 90 | } |
90 | 91 | ||
91 | pub struct Vfs { | 92 | pub(crate) struct Roots { |
92 | roots: Arena<VfsRoot, Arc<RootFilter>>, | 93 | roots: Arena<VfsRoot, Arc<RootFilter>>, |
94 | } | ||
95 | |||
96 | impl Roots { | ||
97 | pub(crate) fn new() -> Roots { | ||
98 | Roots { | ||
99 | roots: Arena::default(), | ||
100 | } | ||
101 | } | ||
102 | pub(crate) fn find(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf)> { | ||
103 | self.roots | ||
104 | .iter() | ||
105 | .find_map(|(root, data)| data.can_contain(path).map(|it| (root, it))) | ||
106 | } | ||
107 | } | ||
108 | |||
109 | impl Deref for Roots { | ||
110 | type Target = Arena<VfsRoot, Arc<RootFilter>>; | ||
111 | fn deref(&self) -> &Self::Target { | ||
112 | &self.roots | ||
113 | } | ||
114 | } | ||
115 | |||
116 | impl DerefMut for Roots { | ||
117 | fn deref_mut(&mut self) -> &mut Self::Target { | ||
118 | &mut self.roots | ||
119 | } | ||
120 | } | ||
121 | |||
122 | pub struct Vfs { | ||
123 | roots: Arc<Roots>, | ||
93 | files: Arena<VfsFile, VfsFileData>, | 124 | files: Arena<VfsFile, VfsFileData>, |
94 | root2files: FxHashMap<VfsRoot, FxHashSet<VfsFile>>, | 125 | root2files: FxHashMap<VfsRoot, FxHashSet<VfsFile>>, |
95 | pending_changes: Vec<VfsChange>, | 126 | pending_changes: Vec<VfsChange>, |
@@ -103,26 +134,22 @@ impl fmt::Debug for Vfs { | |||
103 | } | 134 | } |
104 | 135 | ||
105 | impl Vfs { | 136 | impl Vfs { |
106 | pub fn new(mut roots: Vec<PathBuf>) -> (Vfs, Vec<VfsRoot>) { | 137 | pub fn new(roots: Vec<PathBuf>) -> (Vfs, Vec<VfsRoot>) { |
138 | let mut root_paths = roots; | ||
107 | let worker = io::Worker::start(); | 139 | let worker = io::Worker::start(); |
108 | 140 | ||
109 | let mut res = Vfs { | 141 | let mut roots = Roots::new(); |
110 | roots: Arena::default(), | 142 | let mut root2files = FxHashMap::default(); |
111 | files: Arena::default(), | ||
112 | root2files: FxHashMap::default(), | ||
113 | worker, | ||
114 | pending_changes: Vec::new(), | ||
115 | }; | ||
116 | 143 | ||
117 | // A hack to make nesting work. | 144 | // A hack to make nesting work. |
118 | roots.sort_by_key(|it| Reverse(it.as_os_str().len())); | 145 | root_paths.sort_by_key(|it| Reverse(it.as_os_str().len())); |
119 | for (i, path) in roots.iter().enumerate() { | 146 | for (i, path) in root_paths.iter().enumerate() { |
120 | let root_filter = Arc::new(RootFilter::new(path.clone())); | 147 | let root_filter = Arc::new(RootFilter::new(path.clone())); |
121 | 148 | ||
122 | let root = res.roots.alloc(root_filter.clone()); | 149 | let root = roots.alloc(root_filter.clone()); |
123 | res.root2files.insert(root, Default::default()); | 150 | root2files.insert(root, Default::default()); |
124 | 151 | ||
125 | let nested_roots = roots[..i] | 152 | let nested_roots = root_paths[..i] |
126 | .iter() | 153 | .iter() |
127 | .filter(|it| it.starts_with(path)) | 154 | .filter(|it| it.starts_with(path)) |
128 | .map(|it| it.clone()) | 155 | .map(|it| it.clone()) |
@@ -134,10 +161,17 @@ impl Vfs { | |||
134 | root_filter, | 161 | root_filter, |
135 | nested_roots, | 162 | nested_roots, |
136 | }; | 163 | }; |
137 | res.worker.sender().send(task).unwrap(); | 164 | worker.sender().send(task).unwrap(); |
138 | } | 165 | } |
139 | let roots = res.roots.iter().map(|(id, _)| id).collect(); | 166 | let res = Vfs { |
140 | (res, roots) | 167 | roots: Arc::new(roots), |
168 | files: Arena::default(), | ||
169 | root2files, | ||
170 | worker, | ||
171 | pending_changes: Vec::new(), | ||
172 | }; | ||
173 | let vfs_roots = res.roots.iter().map(|(id, _)| id).collect(); | ||
174 | (res, vfs_roots) | ||
141 | } | 175 | } |
142 | 176 | ||
143 | pub fn root2path(&self, root: VfsRoot) -> PathBuf { | 177 | pub fn root2path(&self, root: VfsRoot) -> PathBuf { |
@@ -399,10 +433,7 @@ impl Vfs { | |||
399 | } | 433 | } |
400 | 434 | ||
401 | fn find_root(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf, Option<VfsFile>)> { | 435 | fn find_root(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf, Option<VfsFile>)> { |
402 | let (root, path) = self | 436 | let (root, path) = self.roots.find(&path)?; |
403 | .roots | ||
404 | .iter() | ||
405 | .find_map(|(root, data)| data.can_contain(path).map(|it| (root, it)))?; | ||
406 | let file = self.root2files[&root] | 437 | let file = self.root2files[&root] |
407 | .iter() | 438 | .iter() |
408 | .map(|&it| it) | 439 | .map(|&it| it) |