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:
parent
672a1dd553
commit
ba59305510
20 changed files with 520 additions and 1071 deletions
|
@ -25,9 +25,9 @@ use std::{
|
|||
use task::TaskTemplate;
|
||||
use text::{BufferId, PointUtf16, ToPointUtf16};
|
||||
|
||||
pub enum LspExpandMacro {}
|
||||
pub enum LspExtExpandMacro {}
|
||||
|
||||
impl lsp::request::Request for LspExpandMacro {
|
||||
impl lsp::request::Request for LspExtExpandMacro {
|
||||
type Params = ExpandMacroParams;
|
||||
type Result = Option<ExpandedMacro>;
|
||||
const METHOD: &'static str = "rust-analyzer/expandMacro";
|
||||
|
@ -60,7 +60,7 @@ pub struct ExpandMacro {
|
|||
#[async_trait(?Send)]
|
||||
impl LspCommand for ExpandMacro {
|
||||
type Response = ExpandedMacro;
|
||||
type LspRequest = LspExpandMacro;
|
||||
type LspRequest = LspExtExpandMacro;
|
||||
type ProtoRequest = proto::LspExtExpandMacro;
|
||||
|
||||
fn display_name(&self) -> &str {
|
||||
|
@ -753,3 +753,33 @@ impl LspCommand for GetLspRunnables {
|
|||
BufferId::new(message.buffer_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LspExtCancelFlycheck {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LspExtRunFlycheck {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LspExtClearFlycheck {}
|
||||
|
||||
impl lsp::notification::Notification for LspExtCancelFlycheck {
|
||||
type Params = ();
|
||||
const METHOD: &'static str = "rust-analyzer/cancelFlycheck";
|
||||
}
|
||||
|
||||
impl lsp::notification::Notification for LspExtRunFlycheck {
|
||||
type Params = RunFlycheckParams;
|
||||
const METHOD: &'static str = "rust-analyzer/runFlycheck";
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RunFlycheckParams {
|
||||
pub text_document: Option<lsp::TextDocumentIdentifier>,
|
||||
}
|
||||
|
||||
impl lsp::notification::Notification for LspExtClearFlycheck {
|
||||
type Params = ();
|
||||
const METHOD: &'static str = "rust-analyzer/clearFlycheck";
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
use ::serde::{Deserialize, Serialize};
|
||||
use gpui::{PromptLevel, WeakEntity};
|
||||
use anyhow::Context as _;
|
||||
use gpui::{App, Entity, PromptLevel, Task, WeakEntity};
|
||||
use lsp::LanguageServer;
|
||||
use rpc::proto;
|
||||
|
||||
use crate::{LanguageServerPromptRequest, LspStore, LspStoreEvent};
|
||||
use crate::{
|
||||
LanguageServerPromptRequest, LspStore, LspStoreEvent, Project, ProjectPath, lsp_store,
|
||||
};
|
||||
|
||||
pub const RUST_ANALYZER_NAME: &str = "rust-analyzer";
|
||||
pub const CARGO_DIAGNOSTICS_SOURCE_NAME: &str = "rustc";
|
||||
|
@ -79,3 +83,161 @@ pub fn register_notifications(lsp_store: WeakEntity<LspStore>, language_server:
|
|||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn cancel_flycheck(
|
||||
project: Entity<Project>,
|
||||
buffer_path: ProjectPath,
|
||||
cx: &mut App,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
let upstream_client = project.read(cx).lsp_store().read(cx).upstream_client();
|
||||
let lsp_store = project.read(cx).lsp_store();
|
||||
let buffer = project.update(cx, |project, cx| {
|
||||
project.buffer_store().update(cx, |buffer_store, cx| {
|
||||
buffer_store.open_buffer(buffer_path, cx)
|
||||
})
|
||||
});
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
let buffer = buffer.await?;
|
||||
let Some(rust_analyzer_server) = project
|
||||
.update(cx, |project, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
project.language_server_id_for_name(buffer, RUST_ANALYZER_NAME, cx)
|
||||
})
|
||||
})?
|
||||
.await
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
let buffer_id = buffer.update(cx, |buffer, _| buffer.remote_id().to_proto())?;
|
||||
|
||||
if let Some((client, project_id)) = upstream_client {
|
||||
let request = proto::LspExtCancelFlycheck {
|
||||
project_id,
|
||||
buffer_id,
|
||||
language_server_id: rust_analyzer_server.to_proto(),
|
||||
};
|
||||
client
|
||||
.request(request)
|
||||
.await
|
||||
.context("lsp ext cancel flycheck proto request")?;
|
||||
} else {
|
||||
lsp_store
|
||||
.update(cx, |lsp_store, _| {
|
||||
if let Some(server) = lsp_store.language_server_for_id(rust_analyzer_server) {
|
||||
server.notify::<lsp_store::lsp_ext_command::LspExtCancelFlycheck>(&())?;
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})?
|
||||
.context("lsp ext cancel flycheck")?;
|
||||
};
|
||||
anyhow::Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run_flycheck(
|
||||
project: Entity<Project>,
|
||||
buffer_path: ProjectPath,
|
||||
cx: &mut App,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
let upstream_client = project.read(cx).lsp_store().read(cx).upstream_client();
|
||||
let lsp_store = project.read(cx).lsp_store();
|
||||
let buffer = project.update(cx, |project, cx| {
|
||||
project.buffer_store().update(cx, |buffer_store, cx| {
|
||||
buffer_store.open_buffer(buffer_path, cx)
|
||||
})
|
||||
});
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
let buffer = buffer.await?;
|
||||
let Some(rust_analyzer_server) = project
|
||||
.update(cx, |project, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
project.language_server_id_for_name(buffer, RUST_ANALYZER_NAME, cx)
|
||||
})
|
||||
})?
|
||||
.await
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
let buffer_id = buffer.update(cx, |buffer, _| buffer.remote_id().to_proto())?;
|
||||
|
||||
if let Some((client, project_id)) = upstream_client {
|
||||
let request = proto::LspExtRunFlycheck {
|
||||
project_id,
|
||||
buffer_id,
|
||||
language_server_id: rust_analyzer_server.to_proto(),
|
||||
current_file_only: false,
|
||||
};
|
||||
client
|
||||
.request(request)
|
||||
.await
|
||||
.context("lsp ext run flycheck proto request")?;
|
||||
} else {
|
||||
lsp_store
|
||||
.update(cx, |lsp_store, _| {
|
||||
if let Some(server) = lsp_store.language_server_for_id(rust_analyzer_server) {
|
||||
server.notify::<lsp_store::lsp_ext_command::LspExtRunFlycheck>(
|
||||
&lsp_store::lsp_ext_command::RunFlycheckParams {
|
||||
text_document: None,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})?
|
||||
.context("lsp ext run flycheck")?;
|
||||
};
|
||||
anyhow::Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn clear_flycheck(
|
||||
project: Entity<Project>,
|
||||
buffer_path: ProjectPath,
|
||||
cx: &mut App,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
let upstream_client = project.read(cx).lsp_store().read(cx).upstream_client();
|
||||
let lsp_store = project.read(cx).lsp_store();
|
||||
let buffer = project.update(cx, |project, cx| {
|
||||
project.buffer_store().update(cx, |buffer_store, cx| {
|
||||
buffer_store.open_buffer(buffer_path, cx)
|
||||
})
|
||||
});
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
let buffer = buffer.await?;
|
||||
let Some(rust_analyzer_server) = project
|
||||
.update(cx, |project, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
project.language_server_id_for_name(buffer, RUST_ANALYZER_NAME, cx)
|
||||
})
|
||||
})?
|
||||
.await
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
let buffer_id = buffer.update(cx, |buffer, _| buffer.remote_id().to_proto())?;
|
||||
|
||||
if let Some((client, project_id)) = upstream_client {
|
||||
let request = proto::LspExtClearFlycheck {
|
||||
project_id,
|
||||
buffer_id,
|
||||
language_server_id: rust_analyzer_server.to_proto(),
|
||||
};
|
||||
client
|
||||
.request(request)
|
||||
.await
|
||||
.context("lsp ext clear flycheck proto request")?;
|
||||
} else {
|
||||
lsp_store
|
||||
.update(cx, |lsp_store, _| {
|
||||
if let Some(server) = lsp_store.language_server_for_id(rust_analyzer_server) {
|
||||
server.notify::<lsp_store::lsp_ext_command::LspExtClearFlycheck>(&())?;
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})?
|
||||
.context("lsp ext clear flycheck")?;
|
||||
};
|
||||
anyhow::Ok(())
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue