From 6b5d90972ae2f288ae7cf57e209c0d5d8c7a1fd2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 17 Feb 2019 19:46:55 +0300 Subject: move roots to a module --- crates/ra_vfs/src/lib.rs | 108 +++++---------------------------------------- crates/ra_vfs/src/roots.rs | 102 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 98 deletions(-) create mode 100644 crates/ra_vfs/src/roots.rs (limited to 'crates/ra_vfs') diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs index cfdc1275f..a740e82ef 100644 --- a/crates/ra_vfs/src/lib.rs +++ b/crates/ra_vfs/src/lib.rs @@ -15,10 +15,10 @@ //! VFS is based on a concept of roots: a set of directories on the file system //! which are watched for changes. Typically, there will be a root for each //! Cargo package. +mod roots; mod io; use std::{ - cmp::Reverse, fmt, fs, mem, path::{Path, PathBuf}, sync::Arc, @@ -26,106 +26,18 @@ use std::{ use crossbeam_channel::Receiver; use ra_arena::{impl_arena_id, Arena, RawId, map::ArenaMap}; -use relative_path::{Component, RelativePath, RelativePathBuf}; +use relative_path::{RelativePath, RelativePathBuf}; use rustc_hash::{FxHashMap, FxHashSet}; -pub use crate::io::TaskResult as VfsTask; -use io::{TaskResult, Worker}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct VfsRoot(pub RawId); -impl_arena_id!(VfsRoot); - -/// Describes the contents of a single source root. -/// -/// `RootConfig` can be thought of as a glob pattern like `src/**.rs` which -/// specifies the source root or as a function which takes a `PathBuf` and -/// returns `true` iff path belongs to the source root -pub(crate) struct RootConfig { - root: PathBuf, - // result of `root.canonicalize()` if that differs from `root`; `None` otherwise. - canonical_root: Option, - excluded_dirs: Vec, -} - -pub(crate) struct Roots { - roots: Arena>, -} - -impl std::ops::Deref for Roots { - type Target = Arena>; - fn deref(&self) -> &Self::Target { - &self.roots - } -} - -impl RootConfig { - fn new(root: PathBuf, excluded_dirs: Vec) -> RootConfig { - let mut canonical_root = root.canonicalize().ok(); - if Some(&root) == canonical_root.as_ref() { - canonical_root = None; - } - RootConfig { root, canonical_root, excluded_dirs } - } - /// Checks if root contains a path and returns a root-relative path. - pub(crate) fn contains(&self, path: &Path) -> Option { - // First, check excluded dirs - if self.excluded_dirs.iter().any(|it| path.starts_with(it)) { - return None; - } - let rel_path = path - .strip_prefix(&self.root) - .or_else(|err_payload| { - self.canonical_root - .as_ref() - .map_or(Err(err_payload), |canonical_root| path.strip_prefix(canonical_root)) - }) - .ok()?; - let rel_path = RelativePathBuf::from_path(rel_path).ok()?; - - // Ignore some common directories. - // - // FIXME: don't hard-code, specify at source-root creation time using - // gitignore - for (i, c) in rel_path.components().enumerate() { - if let Component::Normal(c) = c { - if (i == 0 && c == "target") || c == ".git" || c == "node_modules" { - return None; - } - } - } - - if path.is_file() && rel_path.extension() != Some("rs") { - return None; - } - - Some(rel_path) - } -} +use crate::{ + io::{TaskResult, Worker}, + roots::{RootConfig, Roots}, +}; -impl Roots { - pub(crate) fn new(mut paths: Vec) -> Roots { - let mut roots = Arena::default(); - // A hack to make nesting work. - paths.sort_by_key(|it| Reverse(it.as_os_str().len())); - paths.dedup(); - for (i, path) in paths.iter().enumerate() { - let nested_roots = paths[..i] - .iter() - .filter(|it| it.starts_with(path)) - .map(|it| it.clone()) - .collect::>(); - - let config = Arc::new(RootConfig::new(path.clone(), nested_roots)); - - roots.alloc(config.clone()); - } - Roots { roots } - } - pub(crate) fn find(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf)> { - self.roots.iter().find_map(|(root, data)| data.contains(path).map(|it| (root, it))) - } -} +pub use crate::{ + io::TaskResult as VfsTask, + roots::VfsRoot, +}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct VfsFile(pub RawId); diff --git a/crates/ra_vfs/src/roots.rs b/crates/ra_vfs/src/roots.rs new file mode 100644 index 000000000..564e12239 --- /dev/null +++ b/crates/ra_vfs/src/roots.rs @@ -0,0 +1,102 @@ +use std::{ + sync::Arc, + path::{Path, PathBuf}, +}; + +use relative_path::RelativePathBuf; +use ra_arena::{impl_arena_id, Arena, RawId}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct VfsRoot(pub RawId); +impl_arena_id!(VfsRoot); + +/// Describes the contents of a single source root. +/// +/// `RootConfig` can be thought of as a glob pattern like `src/**.rs` which +/// specifies the source root or as a function which takes a `PathBuf` and +/// returns `true` iff path belongs to the source root +pub(crate) struct RootConfig { + pub(crate) root: PathBuf, + // result of `root.canonicalize()` if that differs from `root`; `None` otherwise. + canonical_root: Option, + excluded_dirs: Vec, +} + +pub(crate) struct Roots { + roots: Arena>, +} + +impl std::ops::Deref for Roots { + type Target = Arena>; + fn deref(&self) -> &Self::Target { + &self.roots + } +} + +impl RootConfig { + fn new(root: PathBuf, excluded_dirs: Vec) -> RootConfig { + let mut canonical_root = root.canonicalize().ok(); + if Some(&root) == canonical_root.as_ref() { + canonical_root = None; + } + RootConfig { root, canonical_root, excluded_dirs } + } + /// Checks if root contains a path and returns a root-relative path. + pub(crate) fn contains(&self, path: &Path) -> Option { + // First, check excluded dirs + if self.excluded_dirs.iter().any(|it| path.starts_with(it)) { + return None; + } + let rel_path = path + .strip_prefix(&self.root) + .or_else(|err_payload| { + self.canonical_root + .as_ref() + .map_or(Err(err_payload), |canonical_root| path.strip_prefix(canonical_root)) + }) + .ok()?; + let rel_path = RelativePathBuf::from_path(rel_path).ok()?; + + // Ignore some common directories. + // + // FIXME: don't hard-code, specify at source-root creation time using + // gitignore + for (i, c) in rel_path.components().enumerate() { + if let relative_path::Component::Normal(c) = c { + if (i == 0 && c == "target") || c == ".git" || c == "node_modules" { + return None; + } + } + } + + if path.is_file() && rel_path.extension() != Some("rs") { + return None; + } + + Some(rel_path) + } +} + +impl Roots { + pub(crate) fn new(mut paths: Vec) -> Roots { + let mut roots = Arena::default(); + // A hack to make nesting work. + paths.sort_by_key(|it| std::cmp::Reverse(it.as_os_str().len())); + paths.dedup(); + for (i, path) in paths.iter().enumerate() { + let nested_roots = paths[..i] + .iter() + .filter(|it| it.starts_with(path)) + .map(|it| it.clone()) + .collect::>(); + + let config = Arc::new(RootConfig::new(path.clone(), nested_roots)); + + roots.alloc(config.clone()); + } + Roots { roots } + } + pub(crate) fn find(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf)> { + self.roots.iter().find_map(|(root, data)| data.contains(path).map(|it| (root, it))) + } +} -- cgit v1.2.3