Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/rust-analyzer/src/global_state.rs43
-rw-r--r--crates/rust-analyzer/src/main_loop.rs37
2 files changed, 48 insertions, 32 deletions
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 12146c8ce0..9d064ed122 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -560,6 +560,49 @@ impl GlobalState {
fn send(&self, message: lsp_server::Message) {
self.sender.send(message).unwrap()
}
+
+ pub(crate) fn publish_diagnostics(
+ &mut self,
+ uri: Url,
+ version: Option<i32>,
+ mut diagnostics: Vec<lsp_types::Diagnostic>,
+ ) {
+ // We put this on a separate thread to avoid blocking the main thread with serialization work
+ self.task_pool.handle.spawn_with_sender(stdx::thread::ThreadIntent::Worker, {
+ let sender = self.sender.clone();
+ move |_| {
+ // VSCode assumes diagnostic messages to be non-empty strings, so we need to patch
+ // empty diagnostics. Neither the docs of VSCode nor the LSP spec say whether
+ // diagnostic messages are actually allowed to be empty or not and patching this
+ // in the VSCode client does not work as the assertion happens in the protocol
+ // conversion. So this hack is here to stay, and will be considered a hack
+ // until the LSP decides to state that empty messages are allowed.
+
+ // See https://github.com/rust-lang/rust-analyzer/issues/11404
+ // See https://github.com/rust-lang/rust-analyzer/issues/13130
+ let patch_empty = |message: &mut String| {
+ if message.is_empty() {
+ " ".clone_into(message);
+ }
+ };
+
+ for d in &mut diagnostics {
+ patch_empty(&mut d.message);
+ if let Some(dri) = &mut d.related_information {
+ for dri in dri {
+ patch_empty(&mut dri.message);
+ }
+ }
+ }
+
+ let not = lsp_server::Notification::new(
+ <lsp_types::notification::PublishDiagnostics as lsp_types::notification::Notification>::METHOD.to_owned(),
+ lsp_types::PublishDiagnosticsParams { uri, diagnostics, version },
+ );
+ _ = sender.send(not.into());
+ }
+ });
+ }
}
impl Drop for GlobalState {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 75635d1c28..54f718479f 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -440,40 +440,13 @@ impl GlobalState {
if let Some(diagnostic_changes) = self.diagnostics.take_changes() {
for file_id in diagnostic_changes {
let uri = file_id_to_url(&self.vfs.read().0, file_id);
- let mut diagnostics =
- self.diagnostics.diagnostics_for(file_id).cloned().collect::<Vec<_>>();
-
- // VSCode assumes diagnostic messages to be non-empty strings, so we need to patch
- // empty diagnostics. Neither the docs of VSCode nor the LSP spec say whether
- // diagnostic messages are actually allowed to be empty or not and patching this
- // in the VSCode client does not work as the assertion happens in the protocol
- // conversion. So this hack is here to stay, and will be considered a hack
- // until the LSP decides to state that empty messages are allowed.
-
- // See https://github.com/rust-lang/rust-analyzer/issues/11404
- // See https://github.com/rust-lang/rust-analyzer/issues/13130
- let patch_empty = |message: &mut String| {
- if message.is_empty() {
- " ".clone_into(message);
- }
- };
-
- for d in &mut diagnostics {
- patch_empty(&mut d.message);
- if let Some(dri) = &mut d.related_information {
- for dri in dri {
- patch_empty(&mut dri.message);
- }
- }
- }
-
let version = from_proto::vfs_path(&uri)
- .map(|path| self.mem_docs.get(&path).map(|it| it.version))
- .unwrap_or_default();
+ .ok()
+ .and_then(|path| self.mem_docs.get(&path).map(|it| it.version));
- self.send_notification::<lsp_types::notification::PublishDiagnostics>(
- lsp_types::PublishDiagnosticsParams { uri, diagnostics, version },
- );
+ let diagnostics =
+ self.diagnostics.diagnostics_for(file_id).cloned().collect::<Vec<_>>();
+ self.publish_diagnostics(uri, version, diagnostics);
}
}