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)
This commit is contained in:
bors 2023-01-23 12:25:04 +00:00
commit ed88fd4ec4
7 changed files with 58 additions and 12 deletions

View file

@ -989,6 +989,10 @@ impl Config {
self.experimental("codeActionGroup") self.experimental("codeActionGroup")
} }
pub fn open_server_logs(&self) -> bool {
self.experimental("openServerLogs")
}
pub fn server_status_notification(&self) -> bool { pub fn server_status_notification(&self) -> bool {
self.experimental("serverStatusNotification") self.experimental("serverStatusNotification")
} }

View file

@ -151,6 +151,13 @@ impl Notification for ClearFlycheck {
const METHOD: &'static str = "rust-analyzer/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)] #[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RunFlycheckParams { pub struct RunFlycheckParams {

View file

@ -2,12 +2,13 @@
use std::{mem, ops::Range, sync::Arc}; use std::{mem, ops::Range, sync::Arc};
use lsp_server::Notification; use lsp_server::Notification;
use lsp_types::request::Request;
use crate::{ use crate::{
from_proto, from_proto,
global_state::GlobalState, global_state::GlobalState,
line_index::{LineEndings, LineIndex, PositionEncoding}, line_index::{LineEndings, LineIndex, PositionEncoding},
LspError, lsp_ext, LspError,
}; };
pub(crate) fn invalid_params_error(message: String) -> 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. /// 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. /// 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>) { pub(crate) fn show_and_log_error(&mut self, message: String, additional_info: Option<String>) {
let mut message = message;
match additional_info { match additional_info {
Some(additional_info) => { Some(additional_info) => {
tracing::error!("{}\n\n{}", &message, &additional_info); tracing::error!("{}:\n{}", &message, &additional_info);
if tracing::enabled!(tracing::Level::ERROR) { match self.config.open_server_logs() && tracing::enabled!(tracing::Level::ERROR) {
message.push_str("\n\nCheck the server logs for additional info."); 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>( self.send_notification::<lsp_types::notification::ShowMessage>(
lsp_types::ShowMessageParams { typ: lsp_types::MessageType::ERROR, message }, lsp_types::ShowMessageParams { typ: lsp_types::MessageType::ERROR, message },
) );
}
}
} }
/// rust-analyzer is resilient -- if it fails, this doesn't usually affect /// 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 from_source_build = option_env!("POKE_RA_DEVS").is_some();
let profiling_enabled = std::env::var("RA_PROFILE").is_ok(); let profiling_enabled = std::env::var("RA_PROFILE").is_ok();
if from_source_build || profiling_enabled { if from_source_build || profiling_enabled {
self.show_message(lsp_types::MessageType::ERROR, message) self.show_and_log_error(message, None);
} }
} }

View file

@ -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 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: need to adjust this doc as well and ping this issue:

View file

@ -316,6 +316,7 @@ class ExperimentalFeatures implements lc.StaticFeature {
caps.hoverActions = true; caps.hoverActions = true;
caps.serverStatusNotification = true; caps.serverStatusNotification = true;
caps.colorDiagnosticOutput = true; caps.colorDiagnosticOutput = true;
caps.openServerLogs = true;
caps.commands = { caps.commands = {
commands: [ commands: [
"rust-analyzer.runSingle", "rust-analyzer.runSingle",

View file

@ -187,6 +187,11 @@ export class Ctx {
this.setServerStatus(params) this.setServerStatus(params)
) )
); );
this.pushClientCleanup(
this._client.onNotification(ra.openServerLogs, () => {
this.outputChannel!.show();
})
);
} }
return this._client; return this._client;
} }

View file

@ -21,6 +21,7 @@ export interface ServerStatusParams {
export const serverStatus = new lc.NotificationType<ServerStatusParams>( export const serverStatus = new lc.NotificationType<ServerStatusParams>(
"experimental/serverStatus" "experimental/serverStatus"
); );
export const openServerLogs = new lc.NotificationType0("rust-analyzer/openServerLogs");
export const reloadWorkspace = new lc.RequestType0<null, void>("rust-analyzer/reloadWorkspace"); export const reloadWorkspace = new lc.RequestType0<null, void>("rust-analyzer/reloadWorkspace");