about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-01-23 12:25:04 +0000
committerbors <bors@rust-lang.org>2023-01-23 12:25:04 +0000
commited88fd4ec404e6675bb9e0b538bed2d1e5436f18 (patch)
tree88b5937a91eeaea0eb80c66aa881412bcf3f55cf
parente1d7a71bcc42c10c1c7a77197c19bd4f1acfbcd8 (diff)
parentb9fe5afb30d00e14aaf5d02ff12a74efb774d4f1 (diff)
downloadrust-ed88fd4ec404e6675bb9e0b538bed2d1e5436f18.tar.gz
rust-ed88fd4ec404e6675bb9e0b538bed2d1e5436f18.zip
Auto merge of #14007 - Veykril:open-server-logs, r=Veykril
Add a 'open server logs' button to the error notification

Closes https://github.com/rust-lang/rust-analyzer/issues/13995#issuecomment-1399669561
![Code_pUQurJ9BRn](https://user-images.githubusercontent.com/3757771/214038673-658f3b43-5310-47b0-99da-d3222d173b0c.gif)
-rw-r--r--crates/rust-analyzer/src/config.rs4
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs7
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs50
-rw-r--r--docs/dev/lsp-extensions.md2
-rw-r--r--editors/code/src/client.ts1
-rw-r--r--editors/code/src/ctx.ts5
-rw-r--r--editors/code/src/lsp_ext.ts1
7 files changed, 58 insertions, 12 deletions
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index c4d9ad7dff5..8ea161dbdc4 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -989,6 +989,10 @@ impl Config {
         self.experimental("codeActionGroup")
     }
 
+    pub fn open_server_logs(&self) -> bool {
+        self.experimental("openServerLogs")
+    }
+
     pub fn server_status_notification(&self) -> bool {
         self.experimental("serverStatusNotification")
     }
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index b117acd1b0f..08b2c837de3 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -151,6 +151,13 @@ impl Notification for ClearFlycheck {
     const METHOD: &'static str = "rust-analyzer/clearFlycheck";
 }
 
+pub enum OpenServerLogs {}
+
+impl Notification for OpenServerLogs {
+    type Params = ();
+    const METHOD: &'static str = "rust-analyzer/openServerLogs";
+}
+
 #[derive(Deserialize, Serialize, Debug)]
 #[serde(rename_all = "camelCase")]
 pub struct RunFlycheckParams {
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs
index dcaee92857a..baa77a005e2 100644
--- a/crates/rust-analyzer/src/lsp_utils.rs
+++ b/crates/rust-analyzer/src/lsp_utils.rs
@@ -2,12 +2,13 @@
 use std::{mem, ops::Range, sync::Arc};
 
 use lsp_server::Notification;
+use lsp_types::request::Request;
 
 use crate::{
     from_proto,
     global_state::GlobalState,
     line_index::{LineEndings, LineIndex, PositionEncoding},
-    LspError,
+    lsp_ext, LspError,
 };
 
 pub(crate) fn invalid_params_error(message: String) -> LspError {
@@ -46,20 +47,47 @@ impl GlobalState {
     /// If `additional_info` is [`Some`], appends a note to the notification telling to check the logs.
     /// This will always log `message` + `additional_info` to the server's error log.
     pub(crate) fn show_and_log_error(&mut self, message: String, additional_info: Option<String>) {
-        let mut message = message;
         match additional_info {
             Some(additional_info) => {
-                tracing::error!("{}\n\n{}", &message, &additional_info);
-                if tracing::enabled!(tracing::Level::ERROR) {
-                    message.push_str("\n\nCheck the server logs for additional info.");
+                tracing::error!("{}:\n{}", &message, &additional_info);
+                match self.config.open_server_logs() && tracing::enabled!(tracing::Level::ERROR) {
+                    true => self.send_request::<lsp_types::request::ShowMessageRequest>(
+                        lsp_types::ShowMessageRequestParams {
+                            typ: lsp_types::MessageType::ERROR,
+                            message,
+                            actions: Some(vec![lsp_types::MessageActionItem {
+                                title: "Open server logs".to_owned(),
+                                properties: Default::default(),
+                            }]),
+                        },
+                        |this, resp| {
+                            let lsp_server::Response { error: None, result: Some(result), .. } = resp
+                            else { return };
+                            if let Ok(Some(_item)) = crate::from_json::<
+                                <lsp_types::request::ShowMessageRequest as lsp_types::request::Request>::Result,
+                            >(
+                                lsp_types::request::ShowMessageRequest::METHOD, &result
+                            ) {
+                                this.send_notification::<lsp_ext::OpenServerLogs>(());
+                            }
+                        },
+                    ),
+                    false => self.send_notification::<lsp_types::notification::ShowMessage>(
+                        lsp_types::ShowMessageParams {
+                            typ: lsp_types::MessageType::ERROR,
+                            message,
+                        },
+                    ),
                 }
             }
-            None => tracing::error!("{}", &message),
-        }
+            None => {
+                tracing::error!("{}", &message);
 
-        self.send_notification::<lsp_types::notification::ShowMessage>(
-            lsp_types::ShowMessageParams { typ: lsp_types::MessageType::ERROR, message },
-        )
+                self.send_notification::<lsp_types::notification::ShowMessage>(
+                    lsp_types::ShowMessageParams { typ: lsp_types::MessageType::ERROR, message },
+                );
+            }
+        }
     }
 
     /// rust-analyzer is resilient -- if it fails, this doesn't usually affect
@@ -77,7 +105,7 @@ impl GlobalState {
         let from_source_build = option_env!("POKE_RA_DEVS").is_some();
         let profiling_enabled = std::env::var("RA_PROFILE").is_ok();
         if from_source_build || profiling_enabled {
-            self.show_message(lsp_types::MessageType::ERROR, message)
+            self.show_and_log_error(message, None);
         }
     }
 
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 0f24ddbbc00..a794e866181 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: d296ce1226e3568d
+lsp_ext.rs hash: ec29403e67dfd15b
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index 1fbe9d4ea03..9335e9abb30 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -316,6 +316,7 @@ class ExperimentalFeatures implements lc.StaticFeature {
         caps.hoverActions = true;
         caps.serverStatusNotification = true;
         caps.colorDiagnosticOutput = true;
+        caps.openServerLogs = true;
         caps.commands = {
             commands: [
                 "rust-analyzer.runSingle",
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts
index d6cee5c8fc6..1860924c6de 100644
--- a/editors/code/src/ctx.ts
+++ b/editors/code/src/ctx.ts
@@ -187,6 +187,11 @@ export class Ctx {
                     this.setServerStatus(params)
                 )
             );
+            this.pushClientCleanup(
+                this._client.onNotification(ra.openServerLogs, () => {
+                    this.outputChannel!.show();
+                })
+            );
         }
         return this._client;
     }
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 29349cc20f5..6ddf83799c0 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -21,6 +21,7 @@ export interface ServerStatusParams {
 export const serverStatus = new lc.NotificationType<ServerStatusParams>(
     "experimental/serverStatus"
 );
+export const openServerLogs = new lc.NotificationType0("rust-analyzer/openServerLogs");
 
 export const reloadWorkspace = new lc.RequestType0<null, void>("rust-analyzer/reloadWorkspace");