From 4b71c8332daf9ef461891d278f2cf3530baaa833 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Tue, 12 Jan 2021 17:41:45 +0100 Subject: Document vfs private items --- crates/vfs/src/file_set.rs | 15 +++++++++++ crates/vfs/src/lib.rs | 20 +++++++++++++++ crates/vfs/src/loader.rs | 15 +++++++++++ crates/vfs/src/path_interner.rs | 14 +++++++++++ crates/vfs/src/vfs_path.rs | 55 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 117 insertions(+), 2 deletions(-) (limited to 'crates/vfs') 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 { /// ``` #[derive(Debug)] pub struct FileSetConfig { + /// Number of sets that `self` can partition a [`Vfs`] into. + /// + /// This should be the number of sets in `self.map` + 1 for files that don't fit in any + /// defined set. n_file_sets: usize, + /// Map from encoded paths to the set they belong to. map: fst::Map>, } @@ -111,9 +116,15 @@ impl FileSetConfig { } res } + + /// Number of sets that `self` can partition a [`Vfs`] into. fn len(&self) -> usize { self.n_file_sets } + + /// Returns the set index for the given `path`. + /// + /// `scratch_space` is used as a buffer and will be entirely replaced. fn classify(&self, path: &VfsPath, scratch_space: &mut Vec) -> usize { scratch_space.clear(); path.encode(scratch_space); @@ -169,11 +180,15 @@ impl FileSetConfigBuilder { } } +/// Implements [`fst::Automaton`] +/// +/// It will match if `prefix_of` is a prefix of the given data. struct PrefixOf<'a> { prefix_of: &'a [u8], } impl<'a> PrefixOf<'a> { + /// Creates a new `PrefixOf` from the given slice. fn new(prefix_of: &'a [u8]) -> Self { Self { prefix_of } } 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 { pub fn take_changes(&mut self) -> Vec { mem::take(&mut self.changes) } + + /// Returns the id associated with `path` + /// + /// - If `path` does not exists in the `Vfs`, allocate a new id for it, associated with a + /// deleted file; + /// - Else, returns `path`'s id. + /// + /// Does not record a change. fn alloc_file_id(&mut self, path: VfsPath) -> FileId { let file_id = self.interner.intern(path); let idx = file_id.0 as usize; @@ -183,9 +191,21 @@ impl Vfs { self.data.resize_with(len, || None); file_id } + + /// Returns the content associated with the given `file_id`. + /// + /// # Panics + /// + /// Panics if no file is associated to that id. fn get(&self, file_id: FileId) -> &Option> { &self.data[file_id.0 as usize] } + + /// Mutably returns the content associated with the given `file_id`. + /// + /// # Panics + /// + /// Panics if no file is associated to that id. fn get_mut(&mut self, file_id: FileId) -> &mut Option> { &mut self.data[file_id.0 as usize] } 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 { pub fn contains_dir(&self, path: &AbsPath) -> bool { self.includes_path(path) } + + /// Returns `true` if `path` is included in `self`. + /// + /// It is included if + /// - An element in `self.include` is a prefix of `path`. + /// - This path is longer than any element in `self.exclude` that is a prefix + /// of `path`. In case of equality, exclusion wins. fn includes_path(&self, path: &AbsPath) -> bool { let mut include: Option<&AbsPathBuf> = None; for incl in &self.include { @@ -170,6 +177,14 @@ impl Directories { } } +/// Returns : +/// ```text +/// Directories { +/// extensions: ["rs"], +/// include: [base], +/// exclude: [base/], +/// } +/// ``` fn dirs(base: AbsPathBuf, exclude: &[&str]) -> Directories { let exclude = exclude.iter().map(|it| base.join(it)).collect::>(); 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; use crate::{FileId, VfsPath}; +/// Structure to map between [`VfsPath`] and [`FileId`]. #[derive(Default)] pub(crate) struct PathInterner { map: FxHashMap, @@ -12,9 +13,17 @@ pub(crate) struct PathInterner { } impl PathInterner { + /// Get the id corresponding to `path`. + /// + /// If `path` does not exists in `self`, returns [`None`]. pub(crate) fn get(&self, path: &VfsPath) -> Option { self.map.get(path).copied() } + + /// Insert `path` in `self`. + /// + /// - If `path` already exists in `self`, returns its associated id; + /// - Else, returns a newly allocated id. pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { if let Some(id) = self.get(&path) { return id; @@ -25,6 +34,11 @@ impl PathInterner { id } + /// Returns the path corresponding to `id`. + /// + /// # Panics + /// + /// Panics if `id` does not exists in `self`. pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { &self.vec[id.0 as usize] } 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 { } } - // Don't make this `pub` + /// **Don't make this `pub`** + /// + /// Encode the path in the given buffer. + /// + /// The encoding will be `0` if [`AbsPathBuf`], `1` if [`VirtualPath`], followed + /// by `self`'s representation. + /// + /// Note that this encoding is dependent on the operating system. pub(crate) fn encode(&self, buf: &mut Vec) { let tag = match &self.0 { VfsPathRepr::PathBuf(_) => 0, @@ -259,6 +266,7 @@ mod windows_paths { } } +/// Internal, private representation of [`VfsPath`]. #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] enum VfsPathRepr { PathBuf(AbsPathBuf), @@ -295,13 +303,34 @@ impl fmt::Debug for VfsPathRepr { } } +/// `/`-separated virtual path. +/// +/// This is used to describe files that do not reside on the file system. #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] struct VirtualPath(String); impl VirtualPath { + /// Returns `true` if `other` is a prefix of `self` (as strings). fn starts_with(&self, other: &VirtualPath) -> bool { self.0.starts_with(&other.0) } + + /// Remove the last component of `self`. + /// + /// This will find the last `'/'` in `self`, and remove everything after it, + /// including the `'/'`. + /// + /// If `self` contains no `'/'`, returns `false`; else returns `true`. + /// + /// # Example + /// + /// ```rust,ignore + /// let mut path = VirtualPath("/foo/bar".to_string()); + /// path.pop(); + /// assert_eq!(path.0, "/foo"); + /// path.pop(); + /// assert_eq!(path.0, ""); + /// ``` fn pop(&mut self) -> bool { let pos = match self.0.rfind('/') { Some(pos) => pos, @@ -310,6 +339,17 @@ impl VirtualPath { self.0 = self.0[..pos].to_string(); true } + + /// Append the given *relative* path `path` to `self`. + /// + /// This will resolve any leading `"../"` in `path` before appending it. + /// + /// Returns [`None`] if `path` has more leading `"../"` than the number of + /// components in `self`. + /// + /// # Notes + /// + /// In practice, appending here means `self/path` as strings. fn join(&self, mut path: &str) -> Option { let mut res = self.clone(); while path.starts_with("../") { @@ -322,7 +362,18 @@ impl VirtualPath { Some(res) } - pub(crate) fn name_and_extension(&self) -> Option<(&str, Option<&str>)> { + /// Returns `self`'s base name and file extension. + /// + /// # Returns + /// - `None` if `self` ends with `"//"`. + /// - `Some((name, None))` if `self`'s base contains no `.`, or only one `.` at + /// the start. + /// - `Some((name, Some(extension))` else. + /// + /// # Note + /// The extension will not contains `.`. This means `"/foo/bar.baz.rs"` will + /// return `Some(("bar.baz", Some("rs"))`. + fn name_and_extension(&self) -> Option<(&str, Option<&str>)> { let file_path = if self.0.ends_with('/') { &self.0[..&self.0.len() - 1] } else { &self.0 }; let file_name = match file_path.rfind('/') { Some(position) => &file_path[position + 1..], -- cgit v1.2.3