From fc7c857f8092b24a44f063c8d6281893f734de98 Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Thu, 21 Dec 2023 21:45:32 +0800 Subject: [PATCH] fix(vscode): don't lint files in .gitignore and .eslintignore (#1765) Closed https://github.com/oxc-project/oxc/issues/1752 --- Cargo.lock | 1 + editors/vscode/server/Cargo.toml | 1 + editors/vscode/server/src/main.rs | 61 +++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bd7acf06..66aa52862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1987,6 +1987,7 @@ dependencies = [ "dashmap", "env_logger", "futures", + "globset", "ignore", "log", "miette", diff --git a/editors/vscode/server/Cargo.toml b/editors/vscode/server/Cargo.toml index 9185b9983..127e287b0 100644 --- a/editors/vscode/server/Cargo.toml +++ b/editors/vscode/server/Cargo.toml @@ -39,3 +39,4 @@ tower-lsp = { workspace = true, features = ["proposed"] } log = "0.4.20" serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +globset = "0.4.14" diff --git a/editors/vscode/server/src/main.rs b/editors/vscode/server/src/main.rs index 1d8cfe746..f92a1f7ae 100644 --- a/editors/vscode/server/src/main.rs +++ b/editors/vscode/server/src/main.rs @@ -4,11 +4,13 @@ mod options; mod walk; use crate::linter::{DiagnosticReport, ServerLinter}; +use globset::Glob; +use ignore::gitignore::Gitignore; use log::{debug, error}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt::Debug; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::str::FromStr; use dashmap::DashMap; @@ -33,6 +35,7 @@ struct Backend { server_linter: ServerLinter, diagnostics_report_map: DashMap>, options: Mutex, + gitignore_glob: Mutex>, } #[derive(Debug, Serialize, Deserialize, Default, PartialEq, PartialOrd, Clone, Copy)] #[serde(rename_all = "camelCase")] @@ -71,6 +74,7 @@ enum SyntheticRunLevel { impl LanguageServer for Backend { async fn initialize(&self, params: InitializeParams) -> Result { self.init(params.root_uri)?; + self.init_ignore_glob().await; let options = params.initialization_options.and_then(|mut value| { let settings = value.get_mut("settings")?.take(); serde_json::from_value::(settings).ok() @@ -166,6 +170,9 @@ impl LanguageServer for Backend { if run_level < SyntheticRunLevel::OnSave { return; } + if self.is_ignored(¶ms.text_document.uri).await { + return; + } self.handle_file_update(params.text_document.uri, None).await; } @@ -176,6 +183,10 @@ impl LanguageServer for Backend { if run_level < SyntheticRunLevel::OnType { return; } + + if self.is_ignored(¶ms.text_document.uri).await { + return; + } let content = params.content_changes.first().map(|c| c.text.clone()); self.handle_file_update(params.text_document.uri, content).await; } @@ -185,6 +196,9 @@ impl LanguageServer for Backend { if run_level < SyntheticRunLevel::OnType { return; } + if self.is_ignored(¶ms.text_document.uri).await { + return; + } self.handle_file_update(params.text_document.uri, None).await; } @@ -244,12 +258,42 @@ impl Backend { }; Error { code: ErrorCode::ParseError, message, data: None } - }) + })?; + + Ok(()) + } + + async fn init_ignore_glob(&self) { + let uri = self + .root_uri + .get() + .expect("The root uri should be initialized already") + .as_ref() + .expect("should get uri"); + let mut builder = globset::GlobSetBuilder::new(); + // Collecting all ignore files + builder.add(Glob::new("**/.eslintignore").unwrap()); + builder.add(Glob::new("**/.gitignore").unwrap()); + + let ignore_file_glob_set = builder.build().unwrap(); + + let mut gitignore_builder = ignore::gitignore::GitignoreBuilder::new(uri.path()); + let walk = ignore::WalkBuilder::new(uri.path()) + .ignore(true) + .hidden(false) + .git_global(false) + .build(); + for entry in walk.flatten() { + if ignore_file_glob_set.is_match(entry.path()) { + gitignore_builder.add(entry.path()); + } + } + + *self.gitignore_glob.lock().await = gitignore_builder.build().ok(); } #[allow(clippy::ptr_arg)] async fn publish_all_diagnostics(&self, result: &Vec<(PathBuf, Vec)>) { - debug!("{:?}", result); join_all(result.iter().map(|(path, diagnostics)| { self.client.publish_diagnostics( Url::from_file_path(path).unwrap(), @@ -276,6 +320,14 @@ impl Backend { } } } + + async fn is_ignored(&self, uri: &Url) -> bool { + let Some(ref gitignore_globs) = *self.gitignore_glob.lock().await else { + return false; + }; + let path = PathBuf::from(uri.path()); + gitignore_globs.matched_path_or_any_parents(&path, path.is_dir()).is_ignore() + } } #[tokio::main] @@ -293,7 +345,8 @@ async fn main() { root_uri: OnceCell::new(), server_linter, diagnostics_report_map, - options: tokio::sync::Mutex::new(Options::default()), + options: Mutex::new(Options::default()), + gitignore_glob: Mutex::new(None), }) .finish();