Skip to content

Commit bd2ef7d

Browse files
committed
refactor(language_server): use Arc for diagnostic_report_map (#10940)
`papaya::HasMap` is already thread safe. And the diagnostics map are not that important to be locked.
1 parent 2b76ab5 commit bd2ef7d

File tree

2 files changed

+19
-25
lines changed

2 files changed

+19
-25
lines changed

crates/oxc_language_server/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ impl LanguageServer for Backend {
349349
let Some(worker) = workers.iter().find(|worker| worker.is_responsible_for_uri(uri)) else {
350350
return;
351351
};
352-
worker.remove_diagnostics(&params.text_document.uri).await;
352+
worker.remove_diagnostics(&params.text_document.uri);
353353
}
354354

355355
async fn code_action(&self, params: CodeActionParams) -> Result<Option<CodeActionResponse>> {
@@ -448,7 +448,7 @@ impl Backend {
448448
async fn clear_all_diagnostics(&self) {
449449
let mut cleared_diagnostics = vec![];
450450
for worker in self.workspace_workers.lock().await.iter() {
451-
cleared_diagnostics.extend(worker.get_clear_diagnostics().await);
451+
cleared_diagnostics.extend(worker.get_clear_diagnostics());
452452
}
453453
self.publish_all_diagnostics(&cleared_diagnostics).await;
454454
}

crates/oxc_language_server/src/worker.rs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{str::FromStr, vec};
1+
use std::{str::FromStr, sync::Arc, vec};
22

33
use log::debug;
44
use rustc_hash::FxBuildHasher;
@@ -20,7 +20,7 @@ use crate::{
2020
pub struct WorkspaceWorker {
2121
root_uri: Uri,
2222
server_linter: RwLock<Option<ServerLinter>>,
23-
diagnostics_report_map: RwLock<ConcurrentHashMap<String, Vec<DiagnosticReport>>>,
23+
diagnostics_report_map: Arc<ConcurrentHashMap<String, Vec<DiagnosticReport>>>,
2424
options: Mutex<Options>,
2525
}
2626

@@ -29,7 +29,7 @@ impl WorkspaceWorker {
2929
Self {
3030
root_uri,
3131
server_linter: RwLock::new(None),
32-
diagnostics_report_map: RwLock::new(ConcurrentHashMap::default()),
32+
diagnostics_report_map: Arc::new(ConcurrentHashMap::default()),
3333
options: Mutex::new(Options::default()),
3434
}
3535
}
@@ -54,8 +54,8 @@ impl WorkspaceWorker {
5454
self.server_linter.read().await.is_none()
5555
}
5656

57-
pub async fn remove_diagnostics(&self, uri: &Uri) {
58-
self.diagnostics_report_map.read().await.pin().remove(&uri.to_string());
57+
pub fn remove_diagnostics(&self, uri: &Uri) {
58+
self.diagnostics_report_map.pin().remove(&uri.to_string());
5959
}
6060

6161
async fn refresh_server_linter(&self) {
@@ -85,7 +85,7 @@ impl WorkspaceWorker {
8585
let diagnostics = self.lint_file_internal(uri, content).await;
8686

8787
if let Some(diagnostics) = &diagnostics {
88-
self.update_diagnostics(uri, diagnostics).await;
88+
self.update_diagnostics(uri, diagnostics);
8989
}
9090

9191
diagnostics
@@ -103,40 +103,36 @@ impl WorkspaceWorker {
103103
server_linter.run_single(uri, content)
104104
}
105105

106-
async fn update_diagnostics(&self, uri: &Uri, diagnostics: &[DiagnosticReport]) {
107-
self.diagnostics_report_map
108-
.read()
109-
.await
110-
.pin()
111-
.insert(uri.to_string(), diagnostics.to_owned());
106+
fn update_diagnostics(&self, uri: &Uri, diagnostics: &[DiagnosticReport]) {
107+
self.diagnostics_report_map.pin().insert(uri.to_string(), diagnostics.to_owned());
112108
}
113109

114110
async fn revalidate_diagnostics(&self) -> ConcurrentHashMap<String, Vec<DiagnosticReport>> {
115111
let diagnostics_map = ConcurrentHashMap::with_capacity_and_hasher(
116-
self.diagnostics_report_map.read().await.len(),
112+
self.diagnostics_report_map.len(),
117113
FxBuildHasher,
118114
);
119115
let server_linter = self.server_linter.read().await;
120116
let Some(server_linter) = &*server_linter else {
121117
debug!("no server_linter initialized in the worker");
122118
return diagnostics_map;
123119
};
124-
for uri in self.diagnostics_report_map.read().await.pin().keys() {
120+
121+
for uri in self.diagnostics_report_map.pin_owned().keys() {
125122
if let Some(diagnostics) = server_linter.run_single(&Uri::from_str(uri).unwrap(), None)
126123
{
124+
self.diagnostics_report_map.pin().insert(uri.clone(), diagnostics.clone());
127125
diagnostics_map.pin().insert(uri.clone(), diagnostics);
126+
} else {
127+
self.diagnostics_report_map.pin().remove(uri);
128128
}
129129
}
130130

131-
*self.diagnostics_report_map.write().await = diagnostics_map.clone();
132-
133131
diagnostics_map
134132
}
135133

136-
pub async fn get_clear_diagnostics(&self) -> Vec<(String, Vec<Diagnostic>)> {
134+
pub fn get_clear_diagnostics(&self) -> Vec<(String, Vec<Diagnostic>)> {
137135
self.diagnostics_report_map
138-
.read()
139-
.await
140136
.pin()
141137
.keys()
142138
.map(|uri| (uri.clone(), vec![]))
@@ -149,8 +145,7 @@ impl WorkspaceWorker {
149145
range: &Range,
150146
is_source_fix_all_oxc: bool,
151147
) -> Vec<CodeActionOrCommand> {
152-
let report_map = self.diagnostics_report_map.read().await;
153-
let report_map_ref = report_map.pin_owned();
148+
let report_map_ref = self.diagnostics_report_map.pin_owned();
154149
let value = match report_map_ref.get(&uri.to_string()) {
155150
Some(value) => value,
156151
// code actions / commands can be requested without opening the file
@@ -190,8 +185,7 @@ impl WorkspaceWorker {
190185
}
191186

192187
pub async fn get_diagnostic_text_edits(&self, uri: &Uri) -> Vec<TextEdit> {
193-
let report_map = self.diagnostics_report_map.read().await;
194-
let report_map_ref = report_map.pin_owned();
188+
let report_map_ref = self.diagnostics_report_map.pin_owned();
195189
let value = match report_map_ref.get(&uri.to_string()) {
196190
Some(value) => value,
197191
// code actions / commands can be requested without opening the file

0 commit comments

Comments
 (0)