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:
parent
8f1023360d
commit
d9dcc59334
6 changed files with 164 additions and 23 deletions
|
@ -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(())
|
||||
|
|
|
@ -2,13 +2,14 @@ use std::sync::Arc;
|
|||
|
||||
use ::serde::{Deserialize, Serialize};
|
||||
use gpui::WeakEntity;
|
||||
use language::CachedLspAdapter;
|
||||
use language::{CachedLspAdapter, Diagnostic};
|
||||
use lsp::LanguageServer;
|
||||
use util::ResultExt as _;
|
||||
|
||||
use crate::LspStore;
|
||||
|
||||
pub const CLANGD_SERVER_NAME: &str = "clangd";
|
||||
const INACTIVE_REGION_MESSAGE: &str = "inactive region";
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
@ -25,6 +26,16 @@ impl lsp::notification::Notification for InactiveRegions {
|
|||
const METHOD: &'static str = "textDocument/inactiveRegions";
|
||||
}
|
||||
|
||||
pub fn is_inactive_region(diag: &Diagnostic) -> bool {
|
||||
diag.is_unnecessary
|
||||
&& diag.severity == lsp::DiagnosticSeverity::INFORMATION
|
||||
&& diag.message == INACTIVE_REGION_MESSAGE
|
||||
&& diag
|
||||
.source
|
||||
.as_ref()
|
||||
.is_some_and(|v| v == CLANGD_SERVER_NAME)
|
||||
}
|
||||
|
||||
pub fn register_notifications(
|
||||
lsp_store: WeakEntity<LspStore>,
|
||||
language_server: &LanguageServer,
|
||||
|
@ -35,10 +46,6 @@ pub fn register_notifications(
|
|||
}
|
||||
let server_id = language_server.server_id();
|
||||
|
||||
// TODO: inactiveRegions support needs do add diagnostics, not replace them as `this.update_diagnostics` call below does
|
||||
if true {
|
||||
return;
|
||||
}
|
||||
language_server
|
||||
.on_notification::<InactiveRegions, _>({
|
||||
let adapter = adapter.clone();
|
||||
|
@ -54,7 +61,7 @@ pub fn register_notifications(
|
|||
range,
|
||||
severity: Some(lsp::DiagnosticSeverity::INFORMATION),
|
||||
source: Some(CLANGD_SERVER_NAME.to_string()),
|
||||
message: "inactive region".to_string(),
|
||||
message: INACTIVE_REGION_MESSAGE.to_string(),
|
||||
tags: Some(vec![lsp::DiagnosticTag::UNNECESSARY]),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -64,10 +71,11 @@ pub fn register_notifications(
|
|||
version: params.text_document.version,
|
||||
diagnostics,
|
||||
};
|
||||
this.update_diagnostics(
|
||||
this.merge_diagnostics(
|
||||
server_id,
|
||||
mapped_diagnostics,
|
||||
&adapter.disk_based_diagnostic_sources,
|
||||
|diag| !is_inactive_region(diag),
|
||||
cx,
|
||||
)
|
||||
.log_err();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue