diff --git a/crates/oxc_language_server/src/linter/server_linter.rs b/crates/oxc_language_server/src/linter/server_linter.rs index 7c7b806d831a2..8cf9f25c458a4 100644 --- a/crates/oxc_language_server/src/linter/server_linter.rs +++ b/crates/oxc_language_server/src/linter/server_linter.rs @@ -29,37 +29,10 @@ pub struct ServerLinter { isolated_linter: Arc>, ignore_matcher: LintIgnoreMatcher, gitignore_glob: Vec, - diagnostics: ServerLinterDiagnostics, + diagnostics: Arc>>>, extended_paths: FxHashSet, } -#[derive(Debug, Default)] -struct ServerLinterDiagnostics { - isolated_linter: Arc>>>, -} - -impl ServerLinterDiagnostics { - pub fn get_diagnostics(&self, path: &str) -> Option> { - let mut reports = Vec::new(); - let mut found = false; - if let Some(entry) = self.isolated_linter.pin().get(path) { - found = true; - if let Some(diagnostics) = entry { - reports.extend(diagnostics.clone()); - } - } - if found { Some(reports) } else { None } - } - - pub fn remove_diagnostics(&self, path: &str) { - self.isolated_linter.pin().remove(path); - } - - pub fn get_cached_files_of_diagnostics(&self) -> Vec { - self.isolated_linter.pin().keys().cloned().collect::>() - } -} - impl ServerLinter { /// # Panics /// Panics if the root URI cannot be converted to a file path. @@ -153,7 +126,7 @@ impl ServerLinter { ), gitignore_glob: Self::create_ignore_glob(&root_path), extended_paths, - diagnostics: ServerLinterDiagnostics::default(), + diagnostics: Arc::new(ConcurrentHashMap::default()), } } @@ -242,19 +215,20 @@ impl ServerLinter { } pub fn remove_diagnostics(&self, uri: &Uri) { - self.diagnostics.remove_diagnostics(&uri.to_string()); + self.diagnostics.pin().remove(&uri.to_string()); } pub fn get_cached_diagnostics(&self, uri: &Uri) -> Option> { - self.diagnostics.get_diagnostics(&uri.to_string()) + if let Some(diagnostics) = self.diagnostics.pin().get(&uri.to_string()) { + // when the uri is ignored, diagnostics is None. + // We want to return Some(vec![]), so the Worker knows there are no diagnostics for this file. + return Some(diagnostics.clone().unwrap_or_default()); + } + None } pub fn get_cached_files_of_diagnostics(&self) -> Vec { - self.diagnostics - .get_cached_files_of_diagnostics() - .into_iter() - .filter_map(|s| Uri::from_str(&s).ok()) - .collect() + self.diagnostics.pin().keys().filter_map(|s| Uri::from_str(s).ok()).collect() } pub async fn revalidate_diagnostics(&self, uris: Vec) -> Vec<(String, Vec)> { @@ -306,7 +280,7 @@ impl ServerLinter { isolated_linter.run_single(uri, content.clone()) }; - self.diagnostics.isolated_linter.pin().insert(uri.to_string(), diagnostics.clone()); + self.diagnostics.pin().insert(uri.to_string(), diagnostics.clone()); diagnostics } @@ -360,11 +334,9 @@ mod test { use std::path::{Path, PathBuf}; use crate::{ - ConcurrentHashMap, linter::{ - error_with_position::DiagnosticReport, options::{LintFixKindFlag, LintOptions, Run, UnusedDisableDirectives}, - server_linter::{ServerLinter, ServerLinterDiagnostics}, + server_linter::ServerLinter, }, tester::{Tester, get_file_path}, }; @@ -400,37 +372,6 @@ mod test { assert!(configs_dirs[0].ends_with("init_nested_configs")); } - #[test] - fn test_get_diagnostics_found_and_none_entries() { - let key = "file:///test.js".to_string(); - - // Case 1: Entry present, Some diagnostics - let diag = DiagnosticReport::default(); - let diag_map = ConcurrentHashMap::default(); - diag_map.pin().insert(key.clone(), Some(vec![diag])); - - let server_diag = - super::ServerLinterDiagnostics { isolated_linter: std::sync::Arc::new(diag_map) }; - let result = server_diag.get_diagnostics(&key); - assert!(result.is_some()); - assert_eq!(result.unwrap().len(), 1); - - // Case 2: Entry present, but value is None - let diag_map_none = ConcurrentHashMap::default(); - diag_map_none.pin().insert(key.clone(), None); - - let server_diag_none = - ServerLinterDiagnostics { isolated_linter: std::sync::Arc::new(diag_map_none) }; - let result_none = server_diag_none.get_diagnostics(&key); - assert!(result_none.is_some()); - assert_eq!(result_none.unwrap().len(), 0); - - // Case 3: No entry at all - let server_diag_empty = ServerLinterDiagnostics::default(); - let result_empty = server_diag_empty.get_diagnostics(&key); - assert!(result_empty.is_none()); - } - #[test] fn test_no_errors() { Tester::new("fixtures/linter/no_errors", None)