Skip to content

Commit 3e4632d

Browse files
committed
Offload diagnostics serialization to the task pool
1 parent e7086a3 commit 3e4632d

File tree

2 files changed

+48
-32
lines changed

2 files changed

+48
-32
lines changed

src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs

+43
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,49 @@ impl GlobalState {
560560
fn send(&self, message: lsp_server::Message) {
561561
self.sender.send(message).unwrap()
562562
}
563+
564+
pub(crate) fn publish_diagnostics(
565+
&mut self,
566+
uri: Url,
567+
version: Option<i32>,
568+
mut diagnostics: Vec<lsp_types::Diagnostic>,
569+
) {
570+
// We put this on a separate thread to avoid blocking the main thread with serialization work
571+
self.task_pool.handle.spawn_with_sender(stdx::thread::ThreadIntent::Worker, {
572+
let sender = self.sender.clone();
573+
move |_| {
574+
// VSCode assumes diagnostic messages to be non-empty strings, so we need to patch
575+
// empty diagnostics. Neither the docs of VSCode nor the LSP spec say whether
576+
// diagnostic messages are actually allowed to be empty or not and patching this
577+
// in the VSCode client does not work as the assertion happens in the protocol
578+
// conversion. So this hack is here to stay, and will be considered a hack
579+
// until the LSP decides to state that empty messages are allowed.
580+
581+
// See https://github.com/rust-lang/rust-analyzer/issues/11404
582+
// See https://github.com/rust-lang/rust-analyzer/issues/13130
583+
let patch_empty = |message: &mut String| {
584+
if message.is_empty() {
585+
" ".clone_into(message);
586+
}
587+
};
588+
589+
for d in &mut diagnostics {
590+
patch_empty(&mut d.message);
591+
if let Some(dri) = &mut d.related_information {
592+
for dri in dri {
593+
patch_empty(&mut dri.message);
594+
}
595+
}
596+
}
597+
598+
let not = lsp_server::Notification::new(
599+
<lsp_types::notification::PublishDiagnostics as lsp_types::notification::Notification>::METHOD.to_owned(),
600+
lsp_types::PublishDiagnosticsParams { uri, diagnostics, version },
601+
);
602+
_ = sender.send(not.into());
603+
}
604+
});
605+
}
563606
}
564607

565608
impl Drop for GlobalState {

src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs

+5-32
Original file line numberDiff line numberDiff line change
@@ -440,40 +440,13 @@ impl GlobalState {
440440
if let Some(diagnostic_changes) = self.diagnostics.take_changes() {
441441
for file_id in diagnostic_changes {
442442
let uri = file_id_to_url(&self.vfs.read().0, file_id);
443-
let mut diagnostics =
444-
self.diagnostics.diagnostics_for(file_id).cloned().collect::<Vec<_>>();
445-
446-
// VSCode assumes diagnostic messages to be non-empty strings, so we need to patch
447-
// empty diagnostics. Neither the docs of VSCode nor the LSP spec say whether
448-
// diagnostic messages are actually allowed to be empty or not and patching this
449-
// in the VSCode client does not work as the assertion happens in the protocol
450-
// conversion. So this hack is here to stay, and will be considered a hack
451-
// until the LSP decides to state that empty messages are allowed.
452-
453-
// See https://github.com/rust-lang/rust-analyzer/issues/11404
454-
// See https://github.com/rust-lang/rust-analyzer/issues/13130
455-
let patch_empty = |message: &mut String| {
456-
if message.is_empty() {
457-
" ".clone_into(message);
458-
}
459-
};
460-
461-
for d in &mut diagnostics {
462-
patch_empty(&mut d.message);
463-
if let Some(dri) = &mut d.related_information {
464-
for dri in dri {
465-
patch_empty(&mut dri.message);
466-
}
467-
}
468-
}
469-
470443
let version = from_proto::vfs_path(&uri)
471-
.map(|path| self.mem_docs.get(&path).map(|it| it.version))
472-
.unwrap_or_default();
444+
.ok()
445+
.and_then(|path| self.mem_docs.get(&path).map(|it| it.version));
473446

474-
self.send_notification::<lsp_types::notification::PublishDiagnostics>(
475-
lsp_types::PublishDiagnosticsParams { uri, diagnostics, version },
476-
);
447+
let diagnostics =
448+
self.diagnostics.diagnostics_for(file_id).cloned().collect::<Vec<_>>();
449+
self.publish_diagnostics(uri, version, diagnostics);
477450
}
478451
}
479452

0 commit comments

Comments
 (0)