From 2c9b91ad326c387190bedab9dae9d08d3eb0705a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 17 Feb 2020 19:07:30 +0100 Subject: Merge ra_vfs_glob and ra_lsp_server --- crates/ra_lsp_server/src/vfs_glob.rs | 94 ++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 crates/ra_lsp_server/src/vfs_glob.rs (limited to 'crates/ra_lsp_server/src/vfs_glob.rs') diff --git a/crates/ra_lsp_server/src/vfs_glob.rs b/crates/ra_lsp_server/src/vfs_glob.rs new file mode 100644 index 000000000..12401d75a --- /dev/null +++ b/crates/ra_lsp_server/src/vfs_glob.rs @@ -0,0 +1,94 @@ +//! `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 { + 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"))); +} -- cgit v1.2.3