ruff server: Introduce the ruff.printDebugInformation command (#11831)

## Summary

Closes #11715.

Introduces a new command, `ruff.printDebugInformation`. This will print
useful information about the status of the server to `stderr`.

Right now, the information shown by this command includes:
* The path to the server executable
* The version of the executable
* The text encoding being used
* The number of open documents and workspaces
* A list of registered configuration files
* The capabilities of the client

## Test Plan

First, checkout and use [the corresponding `ruff-vscode`
PR](https://github.com/astral-sh/ruff-vscode/pull/495).

Running the `Print debug information` command in VS Code should show
something like the following in the Output channel:

<img width="991" alt="Screenshot 2024-06-11 at 11 41 46 AM"
src="ab93c009-bb7b-4291-b057-d44fdc6f9f86">
This commit is contained in:
Jane Lewis 2024-06-11 11:42:46 -07:00 committed by GitHub
parent 507f5c1137
commit 4e9d771aa0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 103 additions and 4 deletions

View file

@ -11,8 +11,9 @@ use lsp_server::ErrorCode;
use lsp_types::{self as types, request as req};
use serde::Deserialize;
#[derive(Debug)]
#[derive(Debug, PartialEq)]
enum Command {
Debug,
Format,
FixAll,
OrganizeImports,
@ -33,13 +34,24 @@ impl super::RequestHandler for ExecuteCommand {
impl super::SyncRequestHandler for ExecuteCommand {
fn run(
session: &mut Session,
_notifier: client::Notifier,
notifier: client::Notifier,
requester: &mut client::Requester,
params: types::ExecuteCommandParams,
) -> server::Result<Option<serde_json::Value>> {
let command =
Command::from_str(&params.command).with_failure_code(ErrorCode::InvalidParams)?;
if command == Command::Debug {
let output = debug_information(session);
notifier
.notify::<types::notification::LogMessage>(types::LogMessageParams {
message: output,
typ: types::MessageType::INFO,
})
.with_failure_code(ErrorCode::InternalError)?;
return Ok(None);
}
// check if we can apply a workspace edit
if !session.resolved_client_capabilities().apply_edit {
return Err(anyhow::anyhow!("Cannot execute the '{}' command: the client does not support `workspace/applyEdit`", command.label())).with_failure_code(ErrorCode::InternalError);
@ -87,6 +99,9 @@ impl super::SyncRequestHandler for ExecuteCommand {
.set_fixes_for_document(fixes, snapshot.query().version())
.with_failure_code(ErrorCode::InternalError)?;
}
Command::Debug => {
unreachable!("The debug command should have already been handled")
}
}
}
@ -109,6 +124,7 @@ impl Command {
Self::FixAll => "Fix all auto-fixable problems",
Self::Format => "Format document",
Self::OrganizeImports => "Format imports",
Self::Debug => "Print debug information",
}
}
}
@ -121,6 +137,7 @@ impl FromStr for Command {
"ruff.applyAutofix" => Self::FixAll,
"ruff.applyFormat" => Self::Format,
"ruff.applyOrganizeImports" => Self::OrganizeImports,
"ruff.printDebugInformation" => Self::Debug,
_ => return Err(anyhow::anyhow!("Invalid command `{name}`")),
})
}
@ -148,3 +165,25 @@ fn apply_edit(
},
)
}
fn debug_information(session: &Session) -> String {
let executable = std::env::current_exe()
.map(|path| format!("{}", path.display()))
.unwrap_or_else(|_| "<unavailable>".to_string());
format!(
r#"executable = {executable}
version = {version}
encoding = {encoding:?}
open_document_count = {doc_count}
active_workspace_count = {workspace_count}
configuration_files = {config_files:?}
{client_capabilities}
"#,
version = crate::version(),
encoding = session.encoding(),
client_capabilities = session.resolved_client_capabilities(),
doc_count = session.num_documents(),
workspace_count = session.num_workspaces(),
config_files = session.list_config_files()
)
}