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/Cargo.toml | 2 +- crates/ra_lsp_server/src/args.rs | 5 ++ crates/ra_lsp_server/src/cli/load_cargo.rs | 3 +- crates/ra_lsp_server/src/lib.rs | 1 + crates/ra_lsp_server/src/main_loop.rs | 2 +- crates/ra_lsp_server/src/vfs_glob.rs | 94 ++++++++++++++++++++++++++++++ crates/ra_lsp_server/src/world.rs | 2 +- 7 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 crates/ra_lsp_server/src/vfs_glob.rs (limited to 'crates/ra_lsp_server') diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index be7982b2a..da523ba8a 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -12,6 +12,7 @@ anyhow = "1.0" crossbeam-channel = "0.4" either = "1.5" env_logger = { version = "0.7.1", default-features = false } +globset = "0.4.4" itertools = "0.8.0" jod-thread = "0.1.0" log = "0.4.3" @@ -33,7 +34,6 @@ ra_project_model = { path = "../ra_project_model" } ra_syntax = { path = "../ra_syntax" } ra_text_edit = { path = "../ra_text_edit" } ra_vfs = "0.5.0" -ra_vfs_glob = { path = "../ra_vfs_glob" } # This should only be used in CLI ra_db = { path = "../ra_db" } diff --git a/crates/ra_lsp_server/src/args.rs b/crates/ra_lsp_server/src/args.rs index 41959797c..89e2139ce 100644 --- a/crates/ra_lsp_server/src/args.rs +++ b/crates/ra_lsp_server/src/args.rs @@ -1,3 +1,8 @@ +//! Command like parsing for rust-analyzer. +//! +//! If run started args, we run the LSP server loop. With a subcommand, we do a +//! one-time batch processing. + use anyhow::{bail, Result}; use pico_args::Arguments; use ra_lsp_server::cli::{BenchWhat, Position, Verbosity}; diff --git a/crates/ra_lsp_server/src/cli/load_cargo.rs b/crates/ra_lsp_server/src/cli/load_cargo.rs index b9a4e6aba..bb3e1513b 100644 --- a/crates/ra_lsp_server/src/cli/load_cargo.rs +++ b/crates/ra_lsp_server/src/cli/load_cargo.rs @@ -7,9 +7,10 @@ use ra_db::{CrateGraph, FileId, SourceRootId}; use ra_ide::{AnalysisChange, AnalysisHost, FeatureFlags}; use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace}; use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; -use ra_vfs_glob::RustPackageFilterBuilder; use rustc_hash::FxHashMap; +use crate::vfs_glob::RustPackageFilterBuilder; + use anyhow::Result; fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId { diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index 2832b2605..958c70fe5 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs @@ -23,6 +23,7 @@ macro_rules! print { }; } +mod vfs_glob; mod caps; mod cargo_target_spec; mod conv; diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 7ae2e1e6f..944074118 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -135,7 +135,7 @@ pub fn main_loop( let globs = config .exclude_globs .iter() - .map(|glob| ra_vfs_glob::Glob::new(glob)) + .map(|glob| crate::vfs_glob::Glob::new(glob)) .collect::, _>>()?; if config.use_client_watching { 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"))); +} diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index d993c5fc4..71c95d4af 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -19,12 +19,12 @@ use ra_ide::{ }; use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace}; use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; -use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; use relative_path::RelativePathBuf; use crate::{ diagnostics::{CheckFixes, DiagnosticCollection}, main_loop::pending_requests::{CompletedRequest, LatestRequests}, + vfs_glob::{Glob, RustPackageFilterBuilder}, LspError, Result, }; -- cgit v1.2.3