mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 12:51:57 +00:00
fix(vscode): don't lint files in .gitignore and .eslintignore (#1765)
Closed https://github.com/oxc-project/oxc/issues/1752
This commit is contained in:
parent
2e707bc1c7
commit
fc7c857f80
3 changed files with 59 additions and 4 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1987,6 +1987,7 @@ dependencies = [
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
|
"globset",
|
||||||
"ignore",
|
"ignore",
|
||||||
"log",
|
"log",
|
||||||
"miette",
|
"miette",
|
||||||
|
|
|
||||||
|
|
@ -39,3 +39,4 @@ tower-lsp = { workspace = true, features = ["proposed"] }
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
globset = "0.4.14"
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,13 @@ mod options;
|
||||||
mod walk;
|
mod walk;
|
||||||
|
|
||||||
use crate::linter::{DiagnosticReport, ServerLinter};
|
use crate::linter::{DiagnosticReport, ServerLinter};
|
||||||
|
use globset::Glob;
|
||||||
|
use ignore::gitignore::Gitignore;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
|
|
@ -33,6 +35,7 @@ struct Backend {
|
||||||
server_linter: ServerLinter,
|
server_linter: ServerLinter,
|
||||||
diagnostics_report_map: DashMap<String, Vec<DiagnosticReport>>,
|
diagnostics_report_map: DashMap<String, Vec<DiagnosticReport>>,
|
||||||
options: Mutex<Options>,
|
options: Mutex<Options>,
|
||||||
|
gitignore_glob: Mutex<Option<Gitignore>>,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Serialize, Deserialize, Default, PartialEq, PartialOrd, Clone, Copy)]
|
#[derive(Debug, Serialize, Deserialize, Default, PartialEq, PartialOrd, Clone, Copy)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|
@ -71,6 +74,7 @@ enum SyntheticRunLevel {
|
||||||
impl LanguageServer for Backend {
|
impl LanguageServer for Backend {
|
||||||
async fn initialize(&self, params: InitializeParams) -> Result<InitializeResult> {
|
async fn initialize(&self, params: InitializeParams) -> Result<InitializeResult> {
|
||||||
self.init(params.root_uri)?;
|
self.init(params.root_uri)?;
|
||||||
|
self.init_ignore_glob().await;
|
||||||
let options = params.initialization_options.and_then(|mut value| {
|
let options = params.initialization_options.and_then(|mut value| {
|
||||||
let settings = value.get_mut("settings")?.take();
|
let settings = value.get_mut("settings")?.take();
|
||||||
serde_json::from_value::<Options>(settings).ok()
|
serde_json::from_value::<Options>(settings).ok()
|
||||||
|
|
@ -166,6 +170,9 @@ impl LanguageServer for Backend {
|
||||||
if run_level < SyntheticRunLevel::OnSave {
|
if run_level < SyntheticRunLevel::OnSave {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if self.is_ignored(¶ms.text_document.uri).await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
self.handle_file_update(params.text_document.uri, None).await;
|
self.handle_file_update(params.text_document.uri, None).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,6 +183,10 @@ impl LanguageServer for Backend {
|
||||||
if run_level < SyntheticRunLevel::OnType {
|
if run_level < SyntheticRunLevel::OnType {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.is_ignored(¶ms.text_document.uri).await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let content = params.content_changes.first().map(|c| c.text.clone());
|
let content = params.content_changes.first().map(|c| c.text.clone());
|
||||||
self.handle_file_update(params.text_document.uri, content).await;
|
self.handle_file_update(params.text_document.uri, content).await;
|
||||||
}
|
}
|
||||||
|
|
@ -185,6 +196,9 @@ impl LanguageServer for Backend {
|
||||||
if run_level < SyntheticRunLevel::OnType {
|
if run_level < SyntheticRunLevel::OnType {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if self.is_ignored(¶ms.text_document.uri).await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
self.handle_file_update(params.text_document.uri, None).await;
|
self.handle_file_update(params.text_document.uri, None).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,12 +258,42 @@ impl Backend {
|
||||||
};
|
};
|
||||||
|
|
||||||
Error { code: ErrorCode::ParseError, message, data: None }
|
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)]
|
#[allow(clippy::ptr_arg)]
|
||||||
async fn publish_all_diagnostics(&self, result: &Vec<(PathBuf, Vec<Diagnostic>)>) {
|
async fn publish_all_diagnostics(&self, result: &Vec<(PathBuf, Vec<Diagnostic>)>) {
|
||||||
debug!("{:?}", result);
|
|
||||||
join_all(result.iter().map(|(path, diagnostics)| {
|
join_all(result.iter().map(|(path, diagnostics)| {
|
||||||
self.client.publish_diagnostics(
|
self.client.publish_diagnostics(
|
||||||
Url::from_file_path(path).unwrap(),
|
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]
|
#[tokio::main]
|
||||||
|
|
@ -293,7 +345,8 @@ async fn main() {
|
||||||
root_uri: OnceCell::new(),
|
root_uri: OnceCell::new(),
|
||||||
server_linter,
|
server_linter,
|
||||||
diagnostics_report_map,
|
diagnostics_report_map,
|
||||||
options: tokio::sync::Mutex::new(Options::default()),
|
options: Mutex::new(Options::default()),
|
||||||
|
gitignore_glob: Mutex::new(None),
|
||||||
})
|
})
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue