//! `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::{GlobSet, GlobSetBuilder}; use ra_vfs::{Filter, RelativePath}; pub use globset::{Glob, GlobBuilder}; 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: Glob) -> RustPackageFilterBuilder { self.exclude.add(glob); self } pub fn into_vfs_filter(self) -> Box<dyn Filter> { 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(Glob::new("src/llvm-project/**").unwrap()) .into_vfs_filter(); assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang"))); }