diff options
Diffstat (limited to 'crates/ra_vfs/src/roots.rs')
-rw-r--r-- | crates/ra_vfs/src/roots.rs | 108 |
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 @@ | |||
1 | use std::{ | ||
2 | iter, | ||
3 | path::{Path, PathBuf}, | ||
4 | }; | ||
5 | |||
6 | use 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)] | ||
10 | pub 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 | ||
17 | struct 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 | |||
24 | pub(crate) struct Roots { | ||
25 | roots: Vec<RootData>, | ||
26 | } | ||
27 | |||
28 | impl 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 | |||
72 | impl 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 | |||
104 | fn 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 | } | ||