aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_vfs_glob/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-08-06 12:00:37 +0100
committerAleksey Kladov <[email protected]>2019-08-06 13:28:31 +0100
commit34203256bf8f8ea12b233e0fb49b42bd8c423281 (patch)
tree79ac51baa1696e06955ced637b6132c6a4eabf48 /crates/ra_vfs_glob/src
parentc9718691043b041f5db878caea687b5a029d4475 (diff)
introduce ra_vfs_glob crate
It manages exclusion rules for the vfs crate
Diffstat (limited to 'crates/ra_vfs_glob/src')
-rw-r--r--crates/ra_vfs_glob/src/lib.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/crates/ra_vfs_glob/src/lib.rs b/crates/ra_vfs_glob/src/lib.rs
new file mode 100644
index 000000000..3e54da5fe
--- /dev/null
+++ b/crates/ra_vfs_glob/src/lib.rs
@@ -0,0 +1,93 @@
1//! `ra_vfs_glob` crate implements exclusion rules for vfs.
2//!
3//! By default, we include only `.rs` files, and skip some know offenders like
4//! `/target` or `/node_modules` altogether.
5//!
6//! It's also possible to add custom exclusion globs.
7
8use globset::{Glob, GlobSet, GlobSetBuilder};
9use ra_vfs::{Filter, RelativePath};
10
11const ALWAYS_IGNORED: &[&str] = &["target/**", "**/node_modules/**", "**/.git/**"];
12const IGNORED_FOR_NON_MEMBERS: &[&str] = &["examples/**", "tests/**", "benches/**"];
13
14pub struct RustPackageFilterBuilder {
15 is_member: bool,
16 exclude: GlobSetBuilder,
17}
18
19impl Default for RustPackageFilterBuilder {
20 fn default() -> RustPackageFilterBuilder {
21 RustPackageFilterBuilder { is_member: false, exclude: GlobSetBuilder::new() }
22 }
23}
24
25impl RustPackageFilterBuilder {
26 pub fn set_member(mut self, is_member: bool) -> RustPackageFilterBuilder {
27 self.is_member = is_member;
28 self
29 }
30 pub fn exclude(mut self, glob: &str) -> Result<RustPackageFilterBuilder, globset::Error> {
31 self.exclude.add(Glob::new(glob)?);
32 Ok(self)
33 }
34 pub fn into_vfs_filter(self) -> Box<dyn Filter> {
35 let RustPackageFilterBuilder { is_member, mut exclude } = self;
36 for &glob in ALWAYS_IGNORED {
37 exclude.add(Glob::new(glob).unwrap());
38 }
39 if !is_member {
40 for &glob in IGNORED_FOR_NON_MEMBERS {
41 exclude.add(Glob::new(glob).unwrap());
42 }
43 }
44 Box::new(RustPackageFilter { exclude: exclude.build().unwrap() })
45 }
46}
47
48struct RustPackageFilter {
49 exclude: GlobSet,
50}
51
52impl Filter for RustPackageFilter {
53 fn include_dir(&self, dir_path: &RelativePath) -> bool {
54 !self.exclude.is_match(dir_path.as_str())
55 }
56
57 fn include_file(&self, file_path: &RelativePath) -> bool {
58 file_path.extension() == Some("rs")
59 }
60}
61
62#[test]
63fn test_globs() {
64 let filter = RustPackageFilterBuilder::default().set_member(true).into_vfs_filter();
65
66 assert!(filter.include_dir(RelativePath::new("src/tests")));
67 assert!(filter.include_dir(RelativePath::new("src/target")));
68 assert!(filter.include_dir(RelativePath::new("tests")));
69 assert!(filter.include_dir(RelativePath::new("benches")));
70
71 assert!(!filter.include_dir(RelativePath::new("target")));
72 assert!(!filter.include_dir(RelativePath::new("src/foo/.git")));
73 assert!(!filter.include_dir(RelativePath::new("foo/node_modules")));
74
75 let filter = RustPackageFilterBuilder::default().set_member(false).into_vfs_filter();
76
77 assert!(filter.include_dir(RelativePath::new("src/tests")));
78 assert!(filter.include_dir(RelativePath::new("src/target")));
79
80 assert!(!filter.include_dir(RelativePath::new("target")));
81 assert!(!filter.include_dir(RelativePath::new("src/foo/.git")));
82 assert!(!filter.include_dir(RelativePath::new("foo/node_modules")));
83 assert!(!filter.include_dir(RelativePath::new("tests")));
84 assert!(!filter.include_dir(RelativePath::new("benches")));
85
86 let filter = RustPackageFilterBuilder::default()
87 .set_member(true)
88 .exclude("src/llvm-project/**")
89 .unwrap()
90 .into_vfs_filter();
91
92 assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang")));
93}