Use rust-analyzer's flycheck as source of cargo diagnostics (#29779)

Follow-up of https://github.com/zed-industries/zed/pull/29706

Instead of doing `cargo check` manually, use rust-analyzer's flycheck:
at the cost of more sophisticated check command configuration, we keep
much less code in Zed, and get a proper progress report.

User-facing UI does not change except `diagnostics_fetch_command` and
`env` settings removed from the diagnostics settings.

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2025-05-02 10:07:51 +03:00 committed by GitHub
parent 672a1dd553
commit ba59305510
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 520 additions and 1071 deletions

View file

@ -8,6 +8,7 @@ use crate::{
buffer_store::{BufferStore, BufferStoreEvent},
environment::ProjectEnvironment,
lsp_command::{self, *},
lsp_store,
manifest_tree::{AdapterQuery, LanguageServerTree, LaunchDisposition, ManifestTree},
prettier_store::{self, PrettierStore, PrettierStoreEvent},
project_settings::{LspSettings, ProjectSettings},
@ -3396,7 +3397,7 @@ pub struct LanguageServerStatus {
pub name: String,
pub pending_work: BTreeMap<String, LanguageServerProgress>,
pub has_pending_diagnostic_updates: bool,
pub progress_tokens: HashSet<String>,
progress_tokens: HashSet<String>,
}
#[derive(Clone, Debug)]
@ -3449,8 +3450,14 @@ impl LspStore {
client.add_entity_request_handler(Self::handle_lsp_command::<PerformRename>);
client.add_entity_request_handler(Self::handle_lsp_command::<LinkedEditingRange>);
client.add_entity_request_handler(Self::handle_lsp_ext_cancel_flycheck);
client.add_entity_request_handler(Self::handle_lsp_ext_run_flycheck);
client.add_entity_request_handler(Self::handle_lsp_ext_clear_flycheck);
client.add_entity_request_handler(Self::handle_lsp_command::<lsp_ext_command::ExpandMacro>);
client.add_entity_request_handler(Self::handle_lsp_command::<lsp_ext_command::OpenDocs>);
client.add_entity_request_handler(
Self::handle_lsp_command::<lsp_ext_command::GoToParentModule>,
);
client.add_entity_request_handler(
Self::handle_lsp_command::<lsp_ext_command::GetLspRunnables>,
);
@ -6236,13 +6243,6 @@ impl LspStore {
})
}
pub fn language_server_with_name(&self, name: &str, cx: &App) -> Option<LanguageServerId> {
self.as_local()?
.lsp_tree
.read(cx)
.server_id_for_name(&LanguageServerName::from(name))
}
pub fn language_servers_for_local_buffer<'a>(
&'a self,
buffer: &Buffer,
@ -7028,37 +7028,26 @@ impl LspStore {
mut cx: AsyncApp,
) -> Result<proto::LanguageServerIdForNameResponse> {
let name = &envelope.payload.name;
match envelope.payload.buffer_id {
Some(buffer_id) => {
let buffer_id = BufferId::new(buffer_id)?;
lsp_store
.update(&mut cx, |lsp_store, cx| {
let buffer = lsp_store.buffer_store.read(cx).get_existing(buffer_id)?;
let server_id = buffer.update(cx, |buffer, cx| {
lsp_store
.language_servers_for_local_buffer(buffer, cx)
.find_map(|(adapter, server)| {
if adapter.name.0.as_ref() == name {
Some(server.server_id())
} else {
None
}
})
});
Ok(server_id)
})?
.map(|server_id| proto::LanguageServerIdForNameResponse {
server_id: server_id.map(|id| id.to_proto()),
})
}
None => lsp_store.update(&mut cx, |lsp_store, cx| {
proto::LanguageServerIdForNameResponse {
server_id: lsp_store
.language_server_with_name(name, cx)
.map(|id| id.to_proto()),
}
}),
}
let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
lsp_store
.update(&mut cx, |lsp_store, cx| {
let buffer = lsp_store.buffer_store.read(cx).get_existing(buffer_id)?;
let server_id = buffer.update(cx, |buffer, cx| {
lsp_store
.language_servers_for_local_buffer(buffer, cx)
.find_map(|(adapter, server)| {
if adapter.name.0.as_ref() == name {
Some(server.server_id())
} else {
None
}
})
});
Ok(server_id)
})?
.map(|server_id| proto::LanguageServerIdForNameResponse {
server_id: server_id.map(|id| id.to_proto()),
})
}
async fn handle_rename_project_entry(
@ -7282,6 +7271,77 @@ impl LspStore {
})
}
async fn handle_lsp_ext_cancel_flycheck(
lsp_store: Entity<Self>,
envelope: TypedEnvelope<proto::LspExtCancelFlycheck>,
mut cx: AsyncApp,
) -> Result<proto::Ack> {
let server_id = LanguageServerId(envelope.payload.language_server_id as usize);
lsp_store.update(&mut cx, |lsp_store, _| {
if let Some(server) = lsp_store.language_server_for_id(server_id) {
server
.notify::<lsp_store::lsp_ext_command::LspExtCancelFlycheck>(&())
.context("handling lsp ext cancel flycheck")
} else {
anyhow::Ok(())
}
})??;
Ok(proto::Ack {})
}
async fn handle_lsp_ext_run_flycheck(
lsp_store: Entity<Self>,
envelope: TypedEnvelope<proto::LspExtRunFlycheck>,
mut cx: AsyncApp,
) -> Result<proto::Ack> {
let server_id = LanguageServerId(envelope.payload.language_server_id as usize);
lsp_store.update(&mut cx, |lsp_store, cx| {
if let Some(server) = lsp_store.language_server_for_id(server_id) {
let text_document = if envelope.payload.current_file_only {
let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
lsp_store
.buffer_store()
.read(cx)
.get(buffer_id)
.and_then(|buffer| Some(buffer.read(cx).file()?.as_local()?.abs_path(cx)))
.map(|path| make_text_document_identifier(&path))
.transpose()?
} else {
None
};
server
.notify::<lsp_store::lsp_ext_command::LspExtRunFlycheck>(
&lsp_store::lsp_ext_command::RunFlycheckParams { text_document },
)
.context("handling lsp ext run flycheck")
} else {
anyhow::Ok(())
}
})??;
Ok(proto::Ack {})
}
async fn handle_lsp_ext_clear_flycheck(
lsp_store: Entity<Self>,
envelope: TypedEnvelope<proto::LspExtClearFlycheck>,
mut cx: AsyncApp,
) -> Result<proto::Ack> {
let server_id = LanguageServerId(envelope.payload.language_server_id as usize);
lsp_store.update(&mut cx, |lsp_store, _| {
if let Some(server) = lsp_store.language_server_for_id(server_id) {
server
.notify::<lsp_store::lsp_ext_command::LspExtClearFlycheck>(&())
.context("handling lsp ext clear flycheck")
} else {
anyhow::Ok(())
}
})??;
Ok(proto::Ack {})
}
pub fn disk_based_diagnostics_started(
&mut self,
language_server_id: LanguageServerId,
@ -7534,7 +7594,7 @@ impl LspStore {
}
}
pub fn on_lsp_progress(
fn on_lsp_progress(
&mut self,
progress: lsp::ProgressParams,
language_server_id: LanguageServerId,