Merge clangd's inactiveRegions with existing diagnostics (#26737)

Closes: https://github.com/zed-industries/zed/issues/13089

This PR attempts to resolve the issues discussed in my previous PR
#26146.

Release Notes:

- Fixed: `inactiveRegions` doesn't replace existing diagnostics anymore
This commit is contained in:
Naim A. 2025-03-25 15:13:53 +02:00 committed by GitHub
parent 8f1023360d
commit d9dcc59334
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 164 additions and 23 deletions

View file

@ -77,7 +77,6 @@ use std::{
ops::{ControlFlow, Range},
path::{self, Path, PathBuf},
rc::Rc,
str,
sync::Arc,
time::{Duration, Instant},
};
@ -452,8 +451,17 @@ impl LocalLspStore {
move |mut params, cx| {
let adapter = adapter.clone();
if let Some(this) = this.upgrade() {
adapter.process_diagnostics(&mut params);
this.update(cx, |this, cx| {
{
let buffer = params
.uri
.to_file_path()
.map(|file_path| this.get_buffer(&file_path, cx))
.ok()
.flatten();
adapter.process_diagnostics(&mut params, server_id, buffer);
}
this.update_diagnostics(
server_id,
params,
@ -2162,7 +2170,7 @@ impl LocalLspStore {
Patch::new(snapshot.edits_since::<PointUtf16>(saved_version).collect())
});
let mut sanitized_diagnostics = Vec::new();
let mut sanitized_diagnostics = Vec::with_capacity(diagnostics.len());
for entry in diagnostics {
let start;
@ -6331,6 +6339,18 @@ impl LspStore {
version: Option<i32>,
diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
cx: &mut Context<Self>,
) -> anyhow::Result<()> {
self.merge_diagnostic_entries(server_id, abs_path, version, diagnostics, |_| false, cx)
}
pub fn merge_diagnostic_entries<F: Fn(&Diagnostic) -> bool + Clone>(
&mut self,
server_id: LanguageServerId,
abs_path: PathBuf,
version: Option<i32>,
mut diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
filter: F,
cx: &mut Context<Self>,
) -> Result<(), anyhow::Error> {
let Some((worktree, relative_path)) =
self.worktree_store.read(cx).find_worktree(&abs_path, cx)
@ -6345,6 +6365,28 @@ impl LspStore {
};
if let Some(buffer) = self.buffer_store.read(cx).get_by_path(&project_path, cx) {
let snapshot = self
.as_local_mut()
.unwrap()
.buffer_snapshot_for_lsp_version(&buffer, server_id, version, cx)?;
diagnostics.extend(
buffer
.read(cx)
.get_diagnostics(server_id)
.into_iter()
.flat_map(|diag| {
diag.iter().filter(|v| filter(&v.diagnostic)).map(|v| {
let start = Unclipped(v.range.start.to_point_utf16(&snapshot));
let end = Unclipped(v.range.end.to_point_utf16(&snapshot));
DiagnosticEntry {
range: start..end,
diagnostic: v.diagnostic.clone(),
}
})
}),
);
self.as_local_mut().unwrap().update_buffer_diagnostics(
&buffer,
server_id,
@ -8369,11 +8411,45 @@ impl LspStore {
}
}
fn get_buffer<'a>(&self, abs_path: &Path, cx: &'a App) -> Option<&'a Buffer> {
let (worktree, relative_path) =
self.worktree_store.read(cx).find_worktree(&abs_path, cx)?;
let project_path = ProjectPath {
worktree_id: worktree.read(cx).id(),
path: relative_path.into(),
};
Some(
self.buffer_store()
.read(cx)
.get_by_path(&project_path, cx)?
.read(cx),
)
}
pub fn update_diagnostics(
&mut self,
language_server_id: LanguageServerId,
params: lsp::PublishDiagnosticsParams,
disk_based_sources: &[String],
cx: &mut Context<Self>,
) -> Result<()> {
self.merge_diagnostics(
language_server_id,
params,
disk_based_sources,
|_| false,
cx,
)
}
pub fn merge_diagnostics<F: Fn(&Diagnostic) -> bool + Clone>(
&mut self,
language_server_id: LanguageServerId,
mut params: lsp::PublishDiagnosticsParams,
disk_based_sources: &[String],
filter: F,
cx: &mut Context<Self>,
) -> Result<()> {
if !self.mode.is_local() {
@ -8480,11 +8556,12 @@ impl LspStore {
}
}
self.update_diagnostic_entries(
self.merge_diagnostic_entries(
language_server_id,
abs_path,
params.version,
diagnostics,
filter,
cx,
)?;
Ok(())