Fix pull diagnostics on the remote clients (#33028)
Also add a test. Release Notes: - Fixed pull diagnostics on the remote clients
This commit is contained in:
parent
e202981f0c
commit
c8d49408d3
4 changed files with 666 additions and 86 deletions
|
@ -3902,6 +3902,7 @@ impl GetDocumentDiagnostics {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WorkspaceLspPullDiagnostics {
|
||||
pub version: Option<i32>,
|
||||
pub diagnostics: LspPullDiagnostics,
|
||||
|
|
|
@ -491,7 +491,7 @@ impl LocalLspStore {
|
|||
None,
|
||||
DiagnosticSourceKind::Pushed,
|
||||
&adapter.disk_based_diagnostic_sources,
|
||||
|diagnostic, cx| match diagnostic.source_kind {
|
||||
|_, diagnostic, cx| match diagnostic.source_kind {
|
||||
DiagnosticSourceKind::Other | DiagnosticSourceKind::Pushed => {
|
||||
adapter.retain_old_diagnostic(diagnostic, cx)
|
||||
}
|
||||
|
@ -6008,10 +6008,15 @@ impl LspStore {
|
|||
buffer: Entity<Buffer>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
let buffer_id = buffer.read(cx).remote_id();
|
||||
let diagnostics = self.pull_diagnostics(buffer, cx);
|
||||
cx.spawn(async move |lsp_store, cx| {
|
||||
let diagnostics = diagnostics.await.context("pulling diagnostics")?;
|
||||
lsp_store.update(cx, |lsp_store, cx| {
|
||||
if lsp_store.as_local().is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
for diagnostics_set in diagnostics {
|
||||
let LspPullDiagnostics::Response {
|
||||
server_id,
|
||||
|
@ -6040,7 +6045,7 @@ impl LspStore {
|
|||
Some(result_id),
|
||||
DiagnosticSourceKind::Pulled,
|
||||
disk_based_sources,
|
||||
|_, _| true,
|
||||
|_, _, _| true,
|
||||
cx,
|
||||
)
|
||||
.log_err();
|
||||
|
@ -6060,8 +6065,10 @@ impl LspStore {
|
|||
result_id,
|
||||
DiagnosticSourceKind::Pulled,
|
||||
disk_based_sources,
|
||||
|old_diagnostic, _| match old_diagnostic.source_kind {
|
||||
DiagnosticSourceKind::Pulled => false,
|
||||
|buffer, old_diagnostic, _| match old_diagnostic.source_kind {
|
||||
DiagnosticSourceKind::Pulled => {
|
||||
buffer.remote_id() != buffer_id
|
||||
}
|
||||
DiagnosticSourceKind::Other
|
||||
| DiagnosticSourceKind::Pushed => true,
|
||||
},
|
||||
|
@ -7077,19 +7084,19 @@ impl LspStore {
|
|||
result_id,
|
||||
version,
|
||||
diagnostics,
|
||||
|_, _| false,
|
||||
|_, _, _| false,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn merge_diagnostic_entries<F: Fn(&Diagnostic, &App) -> bool + Clone>(
|
||||
pub fn merge_diagnostic_entries(
|
||||
&mut self,
|
||||
server_id: LanguageServerId,
|
||||
abs_path: PathBuf,
|
||||
result_id: Option<String>,
|
||||
version: Option<i32>,
|
||||
mut diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
|
||||
filter: F,
|
||||
filter: impl Fn(&Buffer, &Diagnostic, &App) -> bool + Clone,
|
||||
cx: &mut Context<Self>,
|
||||
) -> anyhow::Result<()> {
|
||||
let Some((worktree, relative_path)) =
|
||||
|
@ -7111,26 +7118,30 @@ impl LspStore {
|
|||
.get_diagnostics(server_id)
|
||||
.into_iter()
|
||||
.flat_map(|diag| {
|
||||
diag.iter().filter(|v| filter(&v.diagnostic, cx)).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(),
|
||||
}
|
||||
})
|
||||
diag.iter()
|
||||
.filter(|v| filter(buffer, &v.diagnostic, cx))
|
||||
.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(),
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
self.as_local_mut().unwrap().update_buffer_diagnostics(
|
||||
&buffer_handle,
|
||||
server_id,
|
||||
result_id,
|
||||
version,
|
||||
diagnostics.clone(),
|
||||
reused_diagnostics.clone(),
|
||||
cx,
|
||||
)?;
|
||||
self.as_local_mut()
|
||||
.context("cannot merge diagnostics on a remote LspStore")?
|
||||
.update_buffer_diagnostics(
|
||||
&buffer_handle,
|
||||
server_id,
|
||||
result_id,
|
||||
version,
|
||||
diagnostics.clone(),
|
||||
reused_diagnostics.clone(),
|
||||
cx,
|
||||
)?;
|
||||
|
||||
diagnostics.extend(reused_diagnostics);
|
||||
}
|
||||
|
@ -7678,55 +7689,15 @@ impl LspStore {
|
|||
buffer.wait_for_version(deserialize_version(&message.version))
|
||||
})?
|
||||
.await?;
|
||||
let pull_diagnostics = lsp_store.update(&mut cx, |lsp_store, cx| {
|
||||
let server_ids = buffer.update(cx, |buffer, cx| {
|
||||
lsp_store
|
||||
.language_servers_for_local_buffer(buffer, cx)
|
||||
.map(|(_, server)| server.server_id())
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
server_ids
|
||||
.into_iter()
|
||||
.map(|server_id| {
|
||||
let result_id = lsp_store.result_id(server_id, buffer_id, cx);
|
||||
let task = lsp_store.request_lsp(
|
||||
buffer.clone(),
|
||||
LanguageServerToQuery::Other(server_id),
|
||||
GetDocumentDiagnostics {
|
||||
previous_result_id: result_id,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
async move { (server_id, task.await) }
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})?;
|
||||
|
||||
let all_diagnostics_responses = join_all(pull_diagnostics).await;
|
||||
let mut all_diagnostics = Vec::new();
|
||||
for (server_id, response) in all_diagnostics_responses {
|
||||
all_diagnostics.push((server_id, response?));
|
||||
}
|
||||
|
||||
lsp_store.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
|
||||
responses: all_diagnostics
|
||||
.into_iter()
|
||||
.map(|(server_id, lsp_diagnostic)| proto::LspResponse {
|
||||
server_id: server_id.to_proto(),
|
||||
response: Some(
|
||||
proto::lsp_response::Response::GetDocumentDiagnosticsResponse(
|
||||
GetDocumentDiagnostics::response_to_proto(
|
||||
lsp_diagnostic,
|
||||
project,
|
||||
sender_id,
|
||||
&buffer_version,
|
||||
cx,
|
||||
),
|
||||
),
|
||||
),
|
||||
})
|
||||
.collect(),
|
||||
lsp_store
|
||||
.update(&mut cx, |lsp_store, cx| {
|
||||
lsp_store.pull_diagnostics_for_buffer(buffer, cx)
|
||||
})?
|
||||
.await?;
|
||||
// `pull_diagnostics_for_buffer` will merge in the new diagnostics and send them to the client.
|
||||
// The client cannot merge anything into its non-local LspStore, so we do not need to return anything.
|
||||
Ok(proto::MultiLspQueryResponse {
|
||||
responses: Vec::new(),
|
||||
})
|
||||
}
|
||||
Some(proto::multi_lsp_query::Request::GetDocumentColor(message)) => {
|
||||
|
@ -9510,24 +9481,22 @@ impl LspStore {
|
|||
result_id,
|
||||
source_kind,
|
||||
disk_based_sources,
|
||||
|_, _| false,
|
||||
|_, _, _| false,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn merge_diagnostics<F: Fn(&Diagnostic, &App) -> bool + Clone>(
|
||||
pub fn merge_diagnostics(
|
||||
&mut self,
|
||||
language_server_id: LanguageServerId,
|
||||
mut params: lsp::PublishDiagnosticsParams,
|
||||
result_id: Option<String>,
|
||||
source_kind: DiagnosticSourceKind,
|
||||
disk_based_sources: &[String],
|
||||
filter: F,
|
||||
filter: impl Fn(&Buffer, &Diagnostic, &App) -> bool + Clone,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Result<()> {
|
||||
if !self.mode.is_local() {
|
||||
anyhow::bail!("called update_diagnostics on remote");
|
||||
}
|
||||
anyhow::ensure!(self.mode.is_local(), "called update_diagnostics on remote");
|
||||
let abs_path = params
|
||||
.uri
|
||||
.to_file_path()
|
||||
|
@ -10470,7 +10439,7 @@ fn lsp_workspace_diagnostics_refresh(
|
|||
Some(result_id),
|
||||
DiagnosticSourceKind::Pulled,
|
||||
disk_based_sources,
|
||||
|_, _| true,
|
||||
|_, _, _| true,
|
||||
cx,
|
||||
)
|
||||
.log_err();
|
||||
|
@ -10490,8 +10459,12 @@ fn lsp_workspace_diagnostics_refresh(
|
|||
result_id,
|
||||
DiagnosticSourceKind::Pulled,
|
||||
disk_based_sources,
|
||||
|old_diagnostic, _| match old_diagnostic.source_kind {
|
||||
DiagnosticSourceKind::Pulled => false,
|
||||
|buffer, old_diagnostic, cx| match old_diagnostic.source_kind {
|
||||
DiagnosticSourceKind::Pulled => {
|
||||
let buffer_url = File::from_dyn(buffer.file()).map(|f| f.abs_path(cx))
|
||||
.and_then(|abs_path| file_path_to_lsp_url(&abs_path).ok());
|
||||
buffer_url.is_none_or(|buffer_url| buffer_url != uri)
|
||||
},
|
||||
DiagnosticSourceKind::Other
|
||||
| DiagnosticSourceKind::Pushed => true,
|
||||
},
|
||||
|
|
|
@ -87,7 +87,7 @@ pub fn register_notifications(
|
|||
None,
|
||||
DiagnosticSourceKind::Pushed,
|
||||
&adapter.disk_based_diagnostic_sources,
|
||||
|diag, _| !is_inactive_region(diag),
|
||||
|_, diag, _| !is_inactive_region(diag),
|
||||
cx,
|
||||
)
|
||||
.log_err();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue