Skip to content

Commit 1f4a71b

Browse files
committed
refactor(language_server): move Diagnostics-map to WorkspaceWorker
1 parent 1c363a6 commit 1f4a71b

File tree

3 files changed

+141
-158
lines changed

3 files changed

+141
-158
lines changed

crates/oxc_language_server/src/backend.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ impl LanguageServer for Backend {
413413
else {
414414
continue;
415415
};
416-
cleared_diagnostics.extend(worker.get_clear_diagnostics().await);
416+
cleared_diagnostics.extend(worker.get_clear_diagnostics());
417417
removed_registrations.push(Unregistration {
418418
id: format!("watcher-{}", worker.get_root_uri().as_str()),
419419
method: "workspace/didChangeWatchedFiles".to_string(),
@@ -570,7 +570,7 @@ impl LanguageServer for Backend {
570570
if self.capabilities.get().is_some_and(|option| option.dynamic_formatting) {
571571
self.file_system.write().await.remove(uri);
572572
}
573-
worker.remove_diagnostics(&params.text_document.uri).await;
573+
worker.remove_diagnostics(&params.text_document.uri);
574574
}
575575

576576
/// It will return code actions or commands for the given range.
@@ -703,7 +703,7 @@ impl Backend {
703703
let mut cleared_diagnostics = vec![];
704704
let workers = &*self.workspace_workers.read().await;
705705
for worker in workers {
706-
cleared_diagnostics.extend(worker.get_clear_diagnostics().await);
706+
cleared_diagnostics.extend(worker.get_clear_diagnostics());
707707
}
708708
self.publish_all_diagnostics(&cleared_diagnostics).await;
709709
}

crates/oxc_language_server/src/linter/server_linter.rs

Lines changed: 12 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::path::{Path, PathBuf};
2-
use std::str::FromStr;
32
use std::sync::Arc;
43

54
use ignore::gitignore::Gitignore;
@@ -22,6 +21,7 @@ use crate::linter::{
2221
tsgo_linter::TsgoLinter,
2322
};
2423
use crate::utils::normalize_path;
24+
use crate::worker::WorkerDiagnostics;
2525
use crate::{ConcurrentHashMap, LINT_CONFIG_FILE};
2626

2727
use super::config_walker::ConfigWalker;
@@ -39,52 +39,9 @@ pub struct ServerLinter {
3939
ignore_matcher: LintIgnoreMatcher,
4040
gitignore_glob: Vec<Gitignore>,
4141
lint_on_run: Run,
42-
diagnostics: ServerLinterDiagnostics,
4342
extended_paths: FxHashSet<PathBuf>,
4443
}
4544

46-
#[derive(Debug, Default)]
47-
struct ServerLinterDiagnostics {
48-
isolated_linter: Arc<ConcurrentHashMap<String, Option<Vec<DiagnosticReport>>>>,
49-
tsgo_linter: Arc<ConcurrentHashMap<String, Option<Vec<DiagnosticReport>>>>,
50-
}
51-
52-
impl ServerLinterDiagnostics {
53-
pub fn get_diagnostics(&self, path: &str) -> Option<Vec<DiagnosticReport>> {
54-
let mut reports = Vec::new();
55-
let mut found = false;
56-
if let Some(entry) = self.isolated_linter.pin().get(path) {
57-
found = true;
58-
if let Some(diagnostics) = entry {
59-
reports.extend(diagnostics.clone());
60-
}
61-
}
62-
if let Some(entry) = self.tsgo_linter.pin().get(path) {
63-
found = true;
64-
if let Some(diagnostics) = entry {
65-
reports.extend(diagnostics.clone());
66-
}
67-
}
68-
if found { Some(reports) } else { None }
69-
}
70-
71-
pub fn remove_diagnostics(&self, path: &str) {
72-
self.isolated_linter.pin().remove(path);
73-
self.tsgo_linter.pin().remove(path);
74-
}
75-
76-
pub fn get_cached_files_of_diagnostics(&self) -> Vec<String> {
77-
let isolated_files = self.isolated_linter.pin().keys().cloned().collect::<Vec<_>>();
78-
let tsgo_files = self.tsgo_linter.pin().keys().cloned().collect::<Vec<_>>();
79-
80-
let mut files = Vec::with_capacity(isolated_files.len() + tsgo_files.len());
81-
files.extend(isolated_files);
82-
files.extend(tsgo_files);
83-
files.dedup();
84-
files
85-
}
86-
}
87-
8845
impl ServerLinter {
8946
pub fn new(root_uri: &Uri, options: &LSPLintOptions) -> Self {
9047
let root_path = root_uri.to_file_path().unwrap();
@@ -174,7 +131,6 @@ impl ServerLinter {
174131
gitignore_glob: Self::create_ignore_glob(&root_path),
175132
extended_paths,
176133
lint_on_run: options.run,
177-
diagnostics: ServerLinterDiagnostics::default(),
178134
tsgo_linter: if options.type_aware {
179135
Arc::new(Some(TsgoLinter::new(&root_path, config_store)))
180136
} else {
@@ -267,27 +223,15 @@ impl ServerLinter {
267223
gitignore_globs
268224
}
269225

270-
pub fn remove_diagnostics(&self, uri: &Uri) {
271-
self.diagnostics.remove_diagnostics(&uri.to_string());
272-
}
273-
274-
pub fn get_cached_diagnostics(&self, uri: &Uri) -> Option<Vec<DiagnosticReport>> {
275-
self.diagnostics.get_diagnostics(&uri.to_string())
276-
}
277-
278-
pub fn get_cached_files_of_diagnostics(&self) -> Vec<Uri> {
279-
self.diagnostics
280-
.get_cached_files_of_diagnostics()
281-
.into_iter()
282-
.filter_map(|s| Uri::from_str(&s).ok())
283-
.collect()
284-
}
285-
286-
pub async fn revalidate_diagnostics(&self, uris: Vec<Uri>) -> Vec<(String, Vec<Diagnostic>)> {
226+
pub async fn revalidate_diagnostics(
227+
&self,
228+
uris: Vec<Uri>,
229+
diagnostics_map: &WorkerDiagnostics,
230+
) -> Vec<(String, Vec<Diagnostic>)> {
287231
let mut diagnostics = Vec::with_capacity(uris.len());
288232
for uri in uris {
289233
if let Some(file_diagnostic) =
290-
self.run_single(&uri, None, ServerLinterRun::Always).await
234+
self.run_single(&uri, None, ServerLinterRun::Always, diagnostics_map).await
291235
{
292236
diagnostics.push((
293237
uri.to_string(),
@@ -325,6 +269,7 @@ impl ServerLinter {
325269
uri: &Uri,
326270
content: Option<String>,
327271
run_type: ServerLinterRun,
272+
diagnostics_map: &WorkerDiagnostics,
328273
) -> Option<Vec<DiagnosticReport>> {
329274
let (oxlint, tsgolint) = match (run_type, self.lint_on_run) {
330275
// run everything on save, or when it is forced
@@ -356,17 +301,17 @@ impl ServerLinter {
356301
let mut isolated_linter = self.isolated_linter.lock().await;
357302
isolated_linter.run_single(uri, content.clone())
358303
};
359-
self.diagnostics.isolated_linter.pin().insert(uri.to_string(), diagnostics);
304+
diagnostics_map.isolated_linter.pin().insert(uri.to_string(), diagnostics);
360305
}
361306

362307
if tsgolint && let Some(tsgo_linter) = self.tsgo_linter.as_ref() {
363-
self.diagnostics
308+
diagnostics_map
364309
.tsgo_linter
365310
.pin()
366311
.insert(uri.to_string(), tsgo_linter.lint_file(uri, content.clone()));
367312
}
368313

369-
self.diagnostics.get_diagnostics(&uri.to_string())
314+
diagnostics_map.get_diagnostics(&uri.to_string())
370315
}
371316

372317
pub fn needs_restart(old_options: &LSPLintOptions, new_options: &LSPLintOptions) -> bool {
@@ -423,11 +368,9 @@ mod test {
423368
use std::path::{Path, PathBuf};
424369

425370
use crate::{
426-
ConcurrentHashMap,
427371
linter::{
428-
error_with_position::DiagnosticReport,
429372
options::{LintOptions, Run, UnusedDisableDirectives},
430-
server_linter::{ServerLinter, ServerLinterDiagnostics},
373+
server_linter::ServerLinter,
431374
},
432375
tester::{Tester, get_file_path},
433376
};
@@ -467,45 +410,6 @@ mod test {
467410
assert!(configs_dirs[0].ends_with("init_nested_configs"));
468411
}
469412

470-
#[test]
471-
fn test_get_diagnostics_found_and_none_entries() {
472-
let key = "file:///test.js".to_string();
473-
474-
// Case 1: Both entries present, Some diagnostics
475-
let diag = DiagnosticReport::default();
476-
let diag_map = ConcurrentHashMap::default();
477-
diag_map.pin().insert(key.clone(), Some(vec![diag.clone()]));
478-
let tsgo_map = ConcurrentHashMap::default();
479-
tsgo_map.pin().insert(key.clone(), Some(vec![diag]));
480-
481-
let server_diag = super::ServerLinterDiagnostics {
482-
isolated_linter: std::sync::Arc::new(diag_map),
483-
tsgo_linter: std::sync::Arc::new(tsgo_map),
484-
};
485-
let result = server_diag.get_diagnostics(&key);
486-
assert!(result.is_some());
487-
assert_eq!(result.unwrap().len(), 2);
488-
489-
// Case 2: Entry present, but value is None
490-
let diag_map_none = ConcurrentHashMap::default();
491-
diag_map_none.pin().insert(key.clone(), None);
492-
let tsgo_map_none = ConcurrentHashMap::default();
493-
tsgo_map_none.pin().insert(key.clone(), None);
494-
495-
let server_diag_none = ServerLinterDiagnostics {
496-
isolated_linter: std::sync::Arc::new(diag_map_none),
497-
tsgo_linter: std::sync::Arc::new(tsgo_map_none),
498-
};
499-
let result_none = server_diag_none.get_diagnostics(&key);
500-
assert!(result_none.is_some());
501-
assert_eq!(result_none.unwrap().len(), 0);
502-
503-
// Case 3: No entry at all
504-
let server_diag_empty = ServerLinterDiagnostics::default();
505-
let result_empty = server_diag_empty.get_diagnostics(&key);
506-
assert!(result_empty.is_none());
507-
}
508-
509413
#[test]
510414
#[cfg(not(target_endian = "big"))]
511415
fn test_lint_on_run_on_type_on_type() {

0 commit comments

Comments
 (0)