aboutsummaryrefslogtreecommitdiff
path: root/crates/vfs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/vfs')
-rw-r--r--crates/vfs/src/loader.rs82
1 files changed, 73 insertions, 9 deletions
diff --git a/crates/vfs/src/loader.rs b/crates/vfs/src/loader.rs
index 6de2e5b3f..9c6e4b6a7 100644
--- a/crates/vfs/src/loader.rs
+++ b/crates/vfs/src/loader.rs
@@ -3,10 +3,25 @@ use std::fmt;
3 3
4use paths::{AbsPath, AbsPathBuf}; 4use paths::{AbsPath, AbsPathBuf};
5 5
6#[derive(Debug)] 6#[derive(Debug, Clone)]
7pub enum Entry { 7pub enum Entry {
8 Files(Vec<AbsPathBuf>), 8 Files(Vec<AbsPathBuf>),
9 Directory { path: AbsPathBuf, include: Vec<String> }, 9 Directories(Directories),
10}
11
12/// Specifies a set of files on the file system.
13///
14/// A file is included if:
15/// * it has included extension
16/// * it is under an `include` path
17/// * it is not under `exclude` path
18///
19/// If many include/exclude paths match, the longest one wins.
20#[derive(Debug, Clone)]
21pub struct Directories {
22 pub extensions: Vec<String>,
23 pub include: Vec<AbsPathBuf>,
24 pub exclude: Vec<AbsPathBuf>,
10} 25}
11 26
12#[derive(Debug)] 27#[derive(Debug)]
@@ -33,21 +48,70 @@ pub trait Handle: fmt::Debug {
33 48
34impl Entry { 49impl Entry {
35 pub fn rs_files_recursively(base: AbsPathBuf) -> Entry { 50 pub fn rs_files_recursively(base: AbsPathBuf) -> Entry {
36 Entry::Directory { path: base, include: globs(&["*.rs", "!/.git/"]) } 51 Entry::Directories(dirs(base, &[".git"]))
37 } 52 }
38 pub fn local_cargo_package(base: AbsPathBuf) -> Entry { 53 pub fn local_cargo_package(base: AbsPathBuf) -> Entry {
39 Entry::Directory { path: base, include: globs(&["*.rs", "!/target/", "!/.git/"]) } 54 Entry::Directories(dirs(base, &[".git", "target"]))
40 } 55 }
41 pub fn cargo_package_dependency(base: AbsPathBuf) -> Entry { 56 pub fn cargo_package_dependency(base: AbsPathBuf) -> Entry {
42 Entry::Directory { 57 Entry::Directories(dirs(base, &[".git", "/tests", "/examples", "/benches"]))
43 path: base, 58 }
44 include: globs(&["*.rs", "!/tests/", "!/examples/", "!/benches/", "!/.git/"]), 59
60 pub fn contains_file(&self, path: &AbsPath) -> bool {
61 match self {
62 Entry::Files(files) => files.iter().any(|it| it == path),
63 Entry::Directories(dirs) => dirs.contains_file(path),
64 }
65 }
66 pub fn contains_dir(&self, path: &AbsPath) -> bool {
67 match self {
68 Entry::Files(_) => false,
69 Entry::Directories(dirs) => dirs.contains_dir(path),
70 }
71 }
72}
73
74impl Directories {
75 pub fn contains_file(&self, path: &AbsPath) -> bool {
76 let ext = path.extension().unwrap_or_default();
77 if self.extensions.iter().all(|it| it.as_str() != ext) {
78 return false;
79 }
80 self.includes_path(path)
81 }
82 pub fn contains_dir(&self, path: &AbsPath) -> bool {
83 self.includes_path(path)
84 }
85 fn includes_path(&self, path: &AbsPath) -> bool {
86 let mut include = None;
87 for incl in &self.include {
88 if is_prefix(incl, path) {
89 include = Some(match include {
90 Some(prev) if is_prefix(incl, prev) => prev,
91 _ => incl,
92 })
93 }
94 }
95 let include = match include {
96 Some(it) => it,
97 None => return false,
98 };
99 for excl in &self.exclude {
100 if is_prefix(excl, path) && is_prefix(include, excl) {
101 return false;
102 }
103 }
104 return true;
105
106 fn is_prefix(short: &AbsPath, long: &AbsPath) -> bool {
107 long.strip_prefix(short).is_some()
45 } 108 }
46 } 109 }
47} 110}
48 111
49fn globs(globs: &[&str]) -> Vec<String> { 112fn dirs(base: AbsPathBuf, exclude: &[&str]) -> Directories {
50 globs.iter().map(|it| it.to_string()).collect() 113 let exclude = exclude.iter().map(|it| base.join(it)).collect::<Vec<_>>();
114 Directories { extensions: vec!["rs".to_string()], include: vec![base], exclude }
51} 115}
52 116
53impl fmt::Debug for Message { 117impl fmt::Debug for Message {