From 34203256bf8f8ea12b233e0fb49b42bd8c423281 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 6 Aug 2019 13:00:37 +0200 Subject: introduce ra_vfs_glob crate It manages exclusion rules for the vfs crate --- crates/ra_vfs_glob/Cargo.toml | 9 +++++ crates/ra_vfs_glob/src/lib.rs | 93 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 crates/ra_vfs_glob/Cargo.toml create mode 100644 crates/ra_vfs_glob/src/lib.rs (limited to 'crates/ra_vfs_glob') diff --git a/crates/ra_vfs_glob/Cargo.toml b/crates/ra_vfs_glob/Cargo.toml new file mode 100644 index 000000000..0390d7da1 --- /dev/null +++ b/crates/ra_vfs_glob/Cargo.toml @@ -0,0 +1,9 @@ +[package] +edition = "2018" +name = "ra_vfs_glob" +version = "0.1.0" +authors = ["rust-analyzer developers"] + +[dependencies] +ra_vfs = "0.2.0" +globset = "0.4.4" 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 @@ +//! `ra_vfs_glob` crate implements exclusion rules for vfs. +//! +//! By default, we include only `.rs` files, and skip some know offenders like +//! `/target` or `/node_modules` altogether. +//! +//! It's also possible to add custom exclusion globs. + +use globset::{Glob, GlobSet, GlobSetBuilder}; +use ra_vfs::{Filter, RelativePath}; + +const ALWAYS_IGNORED: &[&str] = &["target/**", "**/node_modules/**", "**/.git/**"]; +const IGNORED_FOR_NON_MEMBERS: &[&str] = &["examples/**", "tests/**", "benches/**"]; + +pub struct RustPackageFilterBuilder { + is_member: bool, + exclude: GlobSetBuilder, +} + +impl Default for RustPackageFilterBuilder { + fn default() -> RustPackageFilterBuilder { + RustPackageFilterBuilder { is_member: false, exclude: GlobSetBuilder::new() } + } +} + +impl RustPackageFilterBuilder { + pub fn set_member(mut self, is_member: bool) -> RustPackageFilterBuilder { + self.is_member = is_member; + self + } + pub fn exclude(mut self, glob: &str) -> Result { + self.exclude.add(Glob::new(glob)?); + Ok(self) + } + pub fn into_vfs_filter(self) -> Box { + let RustPackageFilterBuilder { is_member, mut exclude } = self; + for &glob in ALWAYS_IGNORED { + exclude.add(Glob::new(glob).unwrap()); + } + if !is_member { + for &glob in IGNORED_FOR_NON_MEMBERS { + exclude.add(Glob::new(glob).unwrap()); + } + } + Box::new(RustPackageFilter { exclude: exclude.build().unwrap() }) + } +} + +struct RustPackageFilter { + exclude: GlobSet, +} + +impl Filter for RustPackageFilter { + fn include_dir(&self, dir_path: &RelativePath) -> bool { + !self.exclude.is_match(dir_path.as_str()) + } + + fn include_file(&self, file_path: &RelativePath) -> bool { + file_path.extension() == Some("rs") + } +} + +#[test] +fn test_globs() { + let filter = RustPackageFilterBuilder::default().set_member(true).into_vfs_filter(); + + assert!(filter.include_dir(RelativePath::new("src/tests"))); + assert!(filter.include_dir(RelativePath::new("src/target"))); + assert!(filter.include_dir(RelativePath::new("tests"))); + assert!(filter.include_dir(RelativePath::new("benches"))); + + assert!(!filter.include_dir(RelativePath::new("target"))); + assert!(!filter.include_dir(RelativePath::new("src/foo/.git"))); + assert!(!filter.include_dir(RelativePath::new("foo/node_modules"))); + + let filter = RustPackageFilterBuilder::default().set_member(false).into_vfs_filter(); + + assert!(filter.include_dir(RelativePath::new("src/tests"))); + assert!(filter.include_dir(RelativePath::new("src/target"))); + + assert!(!filter.include_dir(RelativePath::new("target"))); + assert!(!filter.include_dir(RelativePath::new("src/foo/.git"))); + assert!(!filter.include_dir(RelativePath::new("foo/node_modules"))); + assert!(!filter.include_dir(RelativePath::new("tests"))); + assert!(!filter.include_dir(RelativePath::new("benches"))); + + let filter = RustPackageFilterBuilder::default() + .set_member(true) + .exclude("src/llvm-project/**") + .unwrap() + .into_vfs_filter(); + + assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang"))); +} -- cgit v1.2.3