aboutsummaryrefslogtreecommitdiff
path: root/crates/vfs
diff options
context:
space:
mode:
authorArnaud <[email protected]>2021-01-12 16:41:45 +0000
committerArnaud <[email protected]>2021-01-12 17:01:47 +0000
commit4b71c8332daf9ef461891d278f2cf3530baaa833 (patch)
tree1a0d16083438c999539c2c9e8a643e449e40fa53 /crates/vfs
parent311ec70d03c27b1b37457ef44510e735fcce0885 (diff)
Document vfs private items
Diffstat (limited to 'crates/vfs')
-rw-r--r--crates/vfs/src/file_set.rs15
-rw-r--r--crates/vfs/src/lib.rs20
-rw-r--r--crates/vfs/src/loader.rs15
-rw-r--r--crates/vfs/src/path_interner.rs14
-rw-r--r--crates/vfs/src/vfs_path.rs55
5 files changed, 117 insertions, 2 deletions
diff --git a/crates/vfs/src/file_set.rs b/crates/vfs/src/file_set.rs
index 348b6dbfd..0a4590c8d 100644
--- a/crates/vfs/src/file_set.rs
+++ b/crates/vfs/src/file_set.rs
@@ -83,7 +83,12 @@ impl fmt::Debug for FileSet {
83/// ``` 83/// ```
84#[derive(Debug)] 84#[derive(Debug)]
85pub struct FileSetConfig { 85pub struct FileSetConfig {
86 /// Number of sets that `self` can partition a [`Vfs`] into.
87 ///
88 /// This should be the number of sets in `self.map` + 1 for files that don't fit in any
89 /// defined set.
86 n_file_sets: usize, 90 n_file_sets: usize,
91 /// Map from encoded paths to the set they belong to.
87 map: fst::Map<Vec<u8>>, 92 map: fst::Map<Vec<u8>>,
88} 93}
89 94
@@ -111,9 +116,15 @@ impl FileSetConfig {
111 } 116 }
112 res 117 res
113 } 118 }
119
120 /// Number of sets that `self` can partition a [`Vfs`] into.
114 fn len(&self) -> usize { 121 fn len(&self) -> usize {
115 self.n_file_sets 122 self.n_file_sets
116 } 123 }
124
125 /// Returns the set index for the given `path`.
126 ///
127 /// `scratch_space` is used as a buffer and will be entirely replaced.
117 fn classify(&self, path: &VfsPath, scratch_space: &mut Vec<u8>) -> usize { 128 fn classify(&self, path: &VfsPath, scratch_space: &mut Vec<u8>) -> usize {
118 scratch_space.clear(); 129 scratch_space.clear();
119 path.encode(scratch_space); 130 path.encode(scratch_space);
@@ -169,11 +180,15 @@ impl FileSetConfigBuilder {
169 } 180 }
170} 181}
171 182
183/// Implements [`fst::Automaton`]
184///
185/// It will match if `prefix_of` is a prefix of the given data.
172struct PrefixOf<'a> { 186struct PrefixOf<'a> {
173 prefix_of: &'a [u8], 187 prefix_of: &'a [u8],
174} 188}
175 189
176impl<'a> PrefixOf<'a> { 190impl<'a> PrefixOf<'a> {
191 /// Creates a new `PrefixOf` from the given slice.
177 fn new(prefix_of: &'a [u8]) -> Self { 192 fn new(prefix_of: &'a [u8]) -> Self {
178 Self { prefix_of } 193 Self { prefix_of }
179 } 194 }
diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs
index bae2c6118..e075d752b 100644
--- a/crates/vfs/src/lib.rs
+++ b/crates/vfs/src/lib.rs
@@ -176,6 +176,14 @@ impl Vfs {
176 pub fn take_changes(&mut self) -> Vec<ChangedFile> { 176 pub fn take_changes(&mut self) -> Vec<ChangedFile> {
177 mem::take(&mut self.changes) 177 mem::take(&mut self.changes)
178 } 178 }
179
180 /// Returns the id associated with `path`
181 ///
182 /// - If `path` does not exists in the `Vfs`, allocate a new id for it, associated with a
183 /// deleted file;
184 /// - Else, returns `path`'s id.
185 ///
186 /// Does not record a change.
179 fn alloc_file_id(&mut self, path: VfsPath) -> FileId { 187 fn alloc_file_id(&mut self, path: VfsPath) -> FileId {
180 let file_id = self.interner.intern(path); 188 let file_id = self.interner.intern(path);
181 let idx = file_id.0 as usize; 189 let idx = file_id.0 as usize;
@@ -183,9 +191,21 @@ impl Vfs {
183 self.data.resize_with(len, || None); 191 self.data.resize_with(len, || None);
184 file_id 192 file_id
185 } 193 }
194
195 /// Returns the content associated with the given `file_id`.
196 ///
197 /// # Panics
198 ///
199 /// Panics if no file is associated to that id.
186 fn get(&self, file_id: FileId) -> &Option<Vec<u8>> { 200 fn get(&self, file_id: FileId) -> &Option<Vec<u8>> {
187 &self.data[file_id.0 as usize] 201 &self.data[file_id.0 as usize]
188 } 202 }
203
204 /// Mutably returns the content associated with the given `file_id`.
205 ///
206 /// # Panics
207 ///
208 /// Panics if no file is associated to that id.
189 fn get_mut(&mut self, file_id: FileId) -> &mut Option<Vec<u8>> { 209 fn get_mut(&mut self, file_id: FileId) -> &mut Option<Vec<u8>> {
190 &mut self.data[file_id.0 as usize] 210 &mut self.data[file_id.0 as usize]
191 } 211 }
diff --git a/crates/vfs/src/loader.rs b/crates/vfs/src/loader.rs
index 399015043..d3bdae562 100644
--- a/crates/vfs/src/loader.rs
+++ b/crates/vfs/src/loader.rs
@@ -147,6 +147,13 @@ impl Directories {
147 pub fn contains_dir(&self, path: &AbsPath) -> bool { 147 pub fn contains_dir(&self, path: &AbsPath) -> bool {
148 self.includes_path(path) 148 self.includes_path(path)
149 } 149 }
150
151 /// Returns `true` if `path` is included in `self`.
152 ///
153 /// It is included if
154 /// - An element in `self.include` is a prefix of `path`.
155 /// - This path is longer than any element in `self.exclude` that is a prefix
156 /// of `path`. In case of equality, exclusion wins.
150 fn includes_path(&self, path: &AbsPath) -> bool { 157 fn includes_path(&self, path: &AbsPath) -> bool {
151 let mut include: Option<&AbsPathBuf> = None; 158 let mut include: Option<&AbsPathBuf> = None;
152 for incl in &self.include { 159 for incl in &self.include {
@@ -170,6 +177,14 @@ impl Directories {
170 } 177 }
171} 178}
172 179
180/// Returns :
181/// ```text
182/// Directories {
183/// extensions: ["rs"],
184/// include: [base],
185/// exclude: [base/<exclude>],
186/// }
187/// ```
173fn dirs(base: AbsPathBuf, exclude: &[&str]) -> Directories { 188fn dirs(base: AbsPathBuf, exclude: &[&str]) -> Directories {
174 let exclude = exclude.iter().map(|it| base.join(it)).collect::<Vec<_>>(); 189 let exclude = exclude.iter().map(|it| base.join(it)).collect::<Vec<_>>();
175 Directories { extensions: vec!["rs".to_string()], include: vec![base], exclude } 190 Directories { extensions: vec!["rs".to_string()], include: vec![base], exclude }
diff --git a/crates/vfs/src/path_interner.rs b/crates/vfs/src/path_interner.rs
index 4f70d61e8..2189e5e25 100644
--- a/crates/vfs/src/path_interner.rs
+++ b/crates/vfs/src/path_interner.rs
@@ -5,6 +5,7 @@ use rustc_hash::FxHashMap;
5 5
6use crate::{FileId, VfsPath}; 6use crate::{FileId, VfsPath};
7 7
8/// Structure to map between [`VfsPath`] and [`FileId`].
8#[derive(Default)] 9#[derive(Default)]
9pub(crate) struct PathInterner { 10pub(crate) struct PathInterner {
10 map: FxHashMap<VfsPath, FileId>, 11 map: FxHashMap<VfsPath, FileId>,
@@ -12,9 +13,17 @@ pub(crate) struct PathInterner {
12} 13}
13 14
14impl PathInterner { 15impl PathInterner {
16 /// Get the id corresponding to `path`.
17 ///
18 /// If `path` does not exists in `self`, returns [`None`].
15 pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> { 19 pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> {
16 self.map.get(path).copied() 20 self.map.get(path).copied()
17 } 21 }
22
23 /// Insert `path` in `self`.
24 ///
25 /// - If `path` already exists in `self`, returns its associated id;
26 /// - Else, returns a newly allocated id.
18 pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { 27 pub(crate) fn intern(&mut self, path: VfsPath) -> FileId {
19 if let Some(id) = self.get(&path) { 28 if let Some(id) = self.get(&path) {
20 return id; 29 return id;
@@ -25,6 +34,11 @@ impl PathInterner {
25 id 34 id
26 } 35 }
27 36
37 /// Returns the path corresponding to `id`.
38 ///
39 /// # Panics
40 ///
41 /// Panics if `id` does not exists in `self`.
28 pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { 42 pub(crate) fn lookup(&self, id: FileId) -> &VfsPath {
29 &self.vec[id.0 as usize] 43 &self.vec[id.0 as usize]
30 } 44 }
diff --git a/crates/vfs/src/vfs_path.rs b/crates/vfs/src/vfs_path.rs
index 74b6333e2..2b3d7fd84 100644
--- a/crates/vfs/src/vfs_path.rs
+++ b/crates/vfs/src/vfs_path.rs
@@ -102,7 +102,14 @@ impl VfsPath {
102 } 102 }
103 } 103 }
104 104
105 // Don't make this `pub` 105 /// **Don't make this `pub`**
106 ///
107 /// Encode the path in the given buffer.
108 ///
109 /// The encoding will be `0` if [`AbsPathBuf`], `1` if [`VirtualPath`], followed
110 /// by `self`'s representation.
111 ///
112 /// Note that this encoding is dependent on the operating system.
106 pub(crate) fn encode(&self, buf: &mut Vec<u8>) { 113 pub(crate) fn encode(&self, buf: &mut Vec<u8>) {
107 let tag = match &self.0 { 114 let tag = match &self.0 {
108 VfsPathRepr::PathBuf(_) => 0, 115 VfsPathRepr::PathBuf(_) => 0,
@@ -259,6 +266,7 @@ mod windows_paths {
259 } 266 }
260} 267}
261 268
269/// Internal, private representation of [`VfsPath`].
262#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] 270#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
263enum VfsPathRepr { 271enum VfsPathRepr {
264 PathBuf(AbsPathBuf), 272 PathBuf(AbsPathBuf),
@@ -295,13 +303,34 @@ impl fmt::Debug for VfsPathRepr {
295 } 303 }
296} 304}
297 305
306/// `/`-separated virtual path.
307///
308/// This is used to describe files that do not reside on the file system.
298#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] 309#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
299struct VirtualPath(String); 310struct VirtualPath(String);
300 311
301impl VirtualPath { 312impl VirtualPath {
313 /// Returns `true` if `other` is a prefix of `self` (as strings).
302 fn starts_with(&self, other: &VirtualPath) -> bool { 314 fn starts_with(&self, other: &VirtualPath) -> bool {
303 self.0.starts_with(&other.0) 315 self.0.starts_with(&other.0)
304 } 316 }
317
318 /// Remove the last component of `self`.
319 ///
320 /// This will find the last `'/'` in `self`, and remove everything after it,
321 /// including the `'/'`.
322 ///
323 /// If `self` contains no `'/'`, returns `false`; else returns `true`.
324 ///
325 /// # Example
326 ///
327 /// ```rust,ignore
328 /// let mut path = VirtualPath("/foo/bar".to_string());
329 /// path.pop();
330 /// assert_eq!(path.0, "/foo");
331 /// path.pop();
332 /// assert_eq!(path.0, "");
333 /// ```
305 fn pop(&mut self) -> bool { 334 fn pop(&mut self) -> bool {
306 let pos = match self.0.rfind('/') { 335 let pos = match self.0.rfind('/') {
307 Some(pos) => pos, 336 Some(pos) => pos,
@@ -310,6 +339,17 @@ impl VirtualPath {
310 self.0 = self.0[..pos].to_string(); 339 self.0 = self.0[..pos].to_string();
311 true 340 true
312 } 341 }
342
343 /// Append the given *relative* path `path` to `self`.
344 ///
345 /// This will resolve any leading `"../"` in `path` before appending it.
346 ///
347 /// Returns [`None`] if `path` has more leading `"../"` than the number of
348 /// components in `self`.
349 ///
350 /// # Notes
351 ///
352 /// In practice, appending here means `self/path` as strings.
313 fn join(&self, mut path: &str) -> Option<VirtualPath> { 353 fn join(&self, mut path: &str) -> Option<VirtualPath> {
314 let mut res = self.clone(); 354 let mut res = self.clone();
315 while path.starts_with("../") { 355 while path.starts_with("../") {
@@ -322,7 +362,18 @@ impl VirtualPath {
322 Some(res) 362 Some(res)
323 } 363 }
324 364
325 pub(crate) fn name_and_extension(&self) -> Option<(&str, Option<&str>)> { 365 /// Returns `self`'s base name and file extension.
366 ///
367 /// # Returns
368 /// - `None` if `self` ends with `"//"`.
369 /// - `Some((name, None))` if `self`'s base contains no `.`, or only one `.` at
370 /// the start.
371 /// - `Some((name, Some(extension))` else.
372 ///
373 /// # Note
374 /// The extension will not contains `.`. This means `"/foo/bar.baz.rs"` will
375 /// return `Some(("bar.baz", Some("rs"))`.
376 fn name_and_extension(&self) -> Option<(&str, Option<&str>)> {
326 let file_path = if self.0.ends_with('/') { &self.0[..&self.0.len() - 1] } else { &self.0 }; 377 let file_path = if self.0.ends_with('/') { &self.0[..&self.0.len() - 1] } else { &self.0 };
327 let file_name = match file_path.rfind('/') { 378 let file_name = match file_path.rfind('/') {
328 Some(position) => &file_path[position + 1..], 379 Some(position) => &file_path[position + 1..],