aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_vfs/src/roots.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_vfs/src/roots.rs')
-rw-r--r--crates/ra_vfs/src/roots.rs108
1 files changed, 0 insertions, 108 deletions
diff --git a/crates/ra_vfs/src/roots.rs b/crates/ra_vfs/src/roots.rs
deleted file mode 100644
index 4503458ee..000000000
--- a/crates/ra_vfs/src/roots.rs
+++ /dev/null
@@ -1,108 +0,0 @@
1use std::{
2 iter,
3 path::{Path, PathBuf},
4};
5
6use relative_path::{ RelativePath, RelativePathBuf};
7
8/// VfsRoot identifies a watched directory on the file system.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct VfsRoot(pub u32);
11
12/// Describes the contents of a single source root.
13///
14/// `RootConfig` can be thought of as a glob pattern like `src/**.rs` which
15/// specifies the source root or as a function which takes a `PathBuf` and
16/// returns `true` iff path belongs to the source root
17struct RootData {
18 path: PathBuf,
19 // result of `root.canonicalize()` if that differs from `root`; `None` otherwise.
20 canonical_path: Option<PathBuf>,
21 excluded_dirs: Vec<RelativePathBuf>,
22}
23
24pub(crate) struct Roots {
25 roots: Vec<RootData>,
26}
27
28impl Roots {
29 pub(crate) fn new(mut paths: Vec<PathBuf>) -> Roots {
30 let mut roots = Vec::new();
31 // A hack to make nesting work.
32 paths.sort_by_key(|it| std::cmp::Reverse(it.as_os_str().len()));
33 paths.dedup();
34 for (i, path) in paths.iter().enumerate() {
35 let nested_roots =
36 paths[..i].iter().filter_map(|it| rel_path(path, it)).collect::<Vec<_>>();
37
38 roots.push(RootData::new(path.clone(), nested_roots));
39 }
40 Roots { roots }
41 }
42 pub(crate) fn find(&self, path: &Path) -> Option<(VfsRoot, RelativePathBuf)> {
43 self.iter().find_map(|root| {
44 let rel_path = self.contains(root, path)?;
45 Some((root, rel_path))
46 })
47 }
48 pub(crate) fn len(&self) -> usize {
49 self.roots.len()
50 }
51 pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = VfsRoot> + 'a {
52 (0..self.roots.len()).into_iter().map(|idx| VfsRoot(idx as u32))
53 }
54 pub(crate) fn path(&self, root: VfsRoot) -> &Path {
55 self.root(root).path.as_path()
56 }
57 /// Checks if root contains a path and returns a root-relative path.
58 pub(crate) fn contains(&self, root: VfsRoot, path: &Path) -> Option<RelativePathBuf> {
59 let data = self.root(root);
60 iter::once(&data.path)
61 .chain(data.canonical_path.as_ref().into_iter())
62 .find_map(|base| rel_path(base, path))
63 .filter(|path| !data.excluded_dirs.contains(path))
64 .filter(|path| !data.is_excluded(path))
65 }
66
67 fn root(&self, root: VfsRoot) -> &RootData {
68 &self.roots[root.0 as usize]
69 }
70}
71
72impl RootData {
73 fn new(path: PathBuf, excluded_dirs: Vec<RelativePathBuf>) -> RootData {
74 let mut canonical_path = path.canonicalize().ok();
75 if Some(&path) == canonical_path.as_ref() {
76 canonical_path = None;
77 }
78 RootData { path, canonical_path, excluded_dirs }
79 }
80
81 fn is_excluded(&self, path: &RelativePath) -> bool {
82 if self.excluded_dirs.iter().any(|it| it == path) {
83 return true;
84 }
85 // Ignore some common directories.
86 //
87 // FIXME: don't hard-code, specify at source-root creation time using
88 // gitignore
89 for (i, c) in path.components().enumerate() {
90 if let relative_path::Component::Normal(c) = c {
91 if (i == 0 && c == "target") || c == ".git" || c == "node_modules" {
92 return true;
93 }
94 }
95 }
96
97 match path.extension() {
98 None | Some("rs") => false,
99 _ => true,
100 }
101 }
102}
103
104fn rel_path(base: &Path, path: &Path) -> Option<RelativePathBuf> {
105 let path = path.strip_prefix(base).ok()?;
106 let path = RelativePathBuf::from_path(path).unwrap();
107 Some(path)
108}