From 6fcd57ac53cd73adb717532c1f76b132a998e8c8 Mon Sep 17 00:00:00 2001 From: Zephaniah Ong <33389011+zephaniahong@users.noreply.github.com> Date: Sat, 2 Mar 2024 16:07:25 +0800 Subject: [PATCH] Expose more errors from rust-analyzer on invalid Cargo.toml contents (#8356) Release Notes: - Fixed ([#7574](https://github.com/zed-industries/zed/issues/7574)). --- crates/lsp/src/lsp.rs | 28 ++++++++++++++++ crates/project/src/project.rs | 46 ++++++++++++++++++++++++++- crates/workspace/src/notifications.rs | 1 + 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 03823e223bb570ee0f68914d583837e0b8a2bf2b..638ed9286fe2affeac841c41999da95efdf06f68 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -164,6 +164,34 @@ struct Error { message: String, } +/// Experimental: Informs the end user about the state of the server +/// +/// [Rust Analyzer Specification](https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/lsp-extensions.md#server-status) +#[derive(Debug)] +pub enum ServerStatus {} + +/// Other(String) variant to handle unknown values due to this still being experimental +#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub enum ServerHealthStatus { + Ok, + Warning, + Error, + Other(String), +} + +#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct ServerStatusParams { + pub health: ServerHealthStatus, + pub message: Option, +} + +impl lsp_types::notification::Notification for ServerStatus { + type Params = ServerStatusParams; + const METHOD: &'static str = "experimental/serverStatus"; +} + impl LanguageServer { /// Starts a language server process. pub fn new( diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index f3989390ce9b6dbea5d2cff256b5e0a8d652bbb8..45aca64a5a3620e8f8a1b4d7c3268bf505be8d2f 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -46,7 +46,7 @@ use log::error; use lsp::{ DiagnosticSeverity, DiagnosticTag, DidChangeWatchedFilesRegistrationOptions, DocumentHighlightKind, LanguageServer, LanguageServerBinary, LanguageServerId, - MessageActionItem, OneOf, + MessageActionItem, OneOf, ServerHealthStatus, ServerStatus, }; use lsp_command::*; use node_runtime::NodeRuntime; @@ -3141,6 +3141,50 @@ impl Project { let disk_based_diagnostics_progress_token = adapter.disk_based_diagnostics_progress_token.clone(); + language_server + .on_notification::({ + let this = this.clone(); + let name = name.to_string(); + move |params, mut cx| { + let this = this.clone(); + let name = name.to_string(); + if let Some(ref message) = params.message { + let message = message.trim(); + if !message.is_empty() { + let formatted_message = format!( + "Language server {name} (id {server_id}) status update: {message}" + ); + match params.health { + ServerHealthStatus::Ok => log::info!("{}", formatted_message), + ServerHealthStatus::Warning => log::warn!("{}", formatted_message), + ServerHealthStatus::Error => { + log::error!("{}", formatted_message); + let (tx, _rx) = smol::channel::bounded(1); + let request = LanguageServerPromptRequest { + level: PromptLevel::Critical, + message: params.message.unwrap_or_default(), + actions: Vec::new(), + response_channel: tx, + lsp_name: name.clone(), + }; + let _ = this + .update(&mut cx, |_, cx| { + cx.emit(Event::LanguageServerPrompt(request)); + }) + .ok(); + } + ServerHealthStatus::Other(status) => { + log::info!( + "Unknown server health: {status}\n{formatted_message}" + ) + } + } + } + } + } + }) + .detach(); + language_server .on_notification::(move |params, mut cx| { if let Some(this) = this.upgrade() { diff --git a/crates/workspace/src/notifications.rs b/crates/workspace/src/notifications.rs index 94fb597c83cbc6bb6d05e92c80e5b2d937c13802..521ea6a2bbbb19e0363995de054ef6067ca78c57 100644 --- a/crates/workspace/src/notifications.rs +++ b/crates/workspace/src/notifications.rs @@ -213,6 +213,7 @@ impl Render for LanguageServerPrompt { .id("language_server_prompt_notification") .elevation_3(cx) .items_start() + .justify_between() .p_2() .gap_2() .w_full()