mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 14:52:01 +00:00
Add supported commands in server capabilities (#11850)
## Summary This PR updates the server capabilities to include the commands that Ruff supports. This is similar to how there's a list of possible code actions supported by the server. I noticed this when I was trying to find whether Helix supported workspace commands or not based on Jane's comment (https://github.com/astral-sh/ruff/pull/11831#discussion_r1634984921) and I found the `:lsp-workspace-command` in the editor but it didn't show up anything in the picker. So, I looked at the implementation in Helix (9c479e6d2d/helix-term/src/commands/typed.rs (L1372-L1384)
) which made me realize that Ruff doesn't provide this in its capabilities. Currently, this does require `ruff` to be first in the list of language servers in the user config but that should be resolved by https://github.com/helix-editor/helix/pull/10176. So, the following config should work: ```toml [[language]] name = "python" # Ruff should come first until https://github.com/helix-editor/helix/pull/10176 is released language-servers = ["ruff", "pyright"] ``` ## Test Plan 1. Neovim's server capabilities output should include the supported commands: ``` executeCommandProvider = { commands = { "ruff.applyFormat", "ruff.applyAutofix", "ruff.applyOrganizeImports", "ruff.printDebugInformation" }, workDoneProgress = false }, ``` 2. Helix should now display the commands to pick from when `:lsp-workspace-command` is invoked: <img width="832" alt="Screenshot 2024-06-13 at 08 47 14" src="09048ecd
-c974-4e09-ab56-9482ff3d780b">
This commit is contained in:
parent
bcbddac21c
commit
9dc226be97
2 changed files with 70 additions and 41 deletions
|
@ -1,6 +1,7 @@
|
|||
//! Scheduling, I/O, and API endpoints.
|
||||
|
||||
use std::num::NonZeroUsize;
|
||||
use std::str::FromStr;
|
||||
|
||||
use lsp_server as lsp;
|
||||
use lsp_types as types;
|
||||
|
@ -276,6 +277,14 @@ impl Server {
|
|||
},
|
||||
},
|
||||
)),
|
||||
execute_command_provider: Some(types::ExecuteCommandOptions {
|
||||
commands: SupportedCommand::all()
|
||||
.map(|command| command.identifier().to_string())
|
||||
.to_vec(),
|
||||
work_done_progress_options: WorkDoneProgressOptions {
|
||||
work_done_progress: Some(false),
|
||||
},
|
||||
}),
|
||||
hover_provider: Some(types::HoverProviderCapability::Simple(true)),
|
||||
notebook_document_sync: Some(types::OneOf::Left(NotebookDocumentSyncOptions {
|
||||
save: Some(false),
|
||||
|
@ -354,3 +363,56 @@ impl SupportedCodeAction {
|
|||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub(crate) enum SupportedCommand {
|
||||
Debug,
|
||||
Format,
|
||||
FixAll,
|
||||
OrganizeImports,
|
||||
}
|
||||
|
||||
impl SupportedCommand {
|
||||
const fn label(self) -> &'static str {
|
||||
match self {
|
||||
Self::FixAll => "Fix all auto-fixable problems",
|
||||
Self::Format => "Format document",
|
||||
Self::OrganizeImports => "Format imports",
|
||||
Self::Debug => "Print debug information",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the identifier of the command.
|
||||
const fn identifier(self) -> &'static str {
|
||||
match self {
|
||||
SupportedCommand::Format => "ruff.applyFormat",
|
||||
SupportedCommand::FixAll => "ruff.applyAutofix",
|
||||
SupportedCommand::OrganizeImports => "ruff.applyOrganizeImports",
|
||||
SupportedCommand::Debug => "ruff.printDebugInformation",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns all the commands that the server currently supports.
|
||||
const fn all() -> [SupportedCommand; 4] {
|
||||
[
|
||||
SupportedCommand::Format,
|
||||
SupportedCommand::FixAll,
|
||||
SupportedCommand::OrganizeImports,
|
||||
SupportedCommand::Debug,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for SupportedCommand {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(name: &str) -> anyhow::Result<Self, Self::Err> {
|
||||
Ok(match name {
|
||||
"ruff.applyAutofix" => Self::FixAll,
|
||||
"ruff.applyFormat" => Self::Format,
|
||||
"ruff.applyOrganizeImports" => Self::OrganizeImports,
|
||||
"ruff.printDebugInformation" => Self::Debug,
|
||||
_ => return Err(anyhow::anyhow!("Invalid command `{name}`")),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ use std::str::FromStr;
|
|||
|
||||
use crate::edit::WorkspaceEditTracker;
|
||||
use crate::server::api::LSPResult;
|
||||
use crate::server::client;
|
||||
use crate::server::schedule::Task;
|
||||
use crate::server::{client, SupportedCommand};
|
||||
use crate::session::Session;
|
||||
use crate::DIAGNOSTIC_NAME;
|
||||
use crate::{edit::DocumentVersion, server};
|
||||
|
@ -11,14 +11,6 @@ use lsp_server::ErrorCode;
|
|||
use lsp_types::{self as types, request as req};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum Command {
|
||||
Debug,
|
||||
Format,
|
||||
FixAll,
|
||||
OrganizeImports,
|
||||
}
|
||||
|
||||
pub(crate) struct ExecuteCommand;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -38,10 +30,10 @@ impl super::SyncRequestHandler for ExecuteCommand {
|
|||
requester: &mut client::Requester,
|
||||
params: types::ExecuteCommandParams,
|
||||
) -> server::Result<Option<serde_json::Value>> {
|
||||
let command =
|
||||
Command::from_str(¶ms.command).with_failure_code(ErrorCode::InvalidParams)?;
|
||||
let command = SupportedCommand::from_str(¶ms.command)
|
||||
.with_failure_code(ErrorCode::InvalidParams)?;
|
||||
|
||||
if command == Command::Debug {
|
||||
if command == SupportedCommand::Debug {
|
||||
let output = debug_information(session);
|
||||
notifier
|
||||
.notify::<types::notification::LogMessage>(types::LogMessageParams {
|
||||
|
@ -74,7 +66,7 @@ impl super::SyncRequestHandler for ExecuteCommand {
|
|||
return Ok(None);
|
||||
};
|
||||
match command {
|
||||
Command::FixAll => {
|
||||
SupportedCommand::FixAll => {
|
||||
let fixes = super::code_action_resolve::fix_all_edit(
|
||||
snapshot.query(),
|
||||
snapshot.encoding(),
|
||||
|
@ -84,13 +76,13 @@ impl super::SyncRequestHandler for ExecuteCommand {
|
|||
.set_fixes_for_document(fixes, snapshot.query().version())
|
||||
.with_failure_code(ErrorCode::InternalError)?;
|
||||
}
|
||||
Command::Format => {
|
||||
SupportedCommand::Format => {
|
||||
let fixes = super::format::format_full_document(&snapshot)?;
|
||||
edit_tracker
|
||||
.set_fixes_for_document(fixes, version)
|
||||
.with_failure_code(ErrorCode::InternalError)?;
|
||||
}
|
||||
Command::OrganizeImports => {
|
||||
SupportedCommand::OrganizeImports => {
|
||||
let fixes = super::code_action_resolve::organize_imports_edit(
|
||||
snapshot.query(),
|
||||
snapshot.encoding(),
|
||||
|
@ -100,7 +92,7 @@ impl super::SyncRequestHandler for ExecuteCommand {
|
|||
.set_fixes_for_document(fixes, snapshot.query().version())
|
||||
.with_failure_code(ErrorCode::InternalError)?;
|
||||
}
|
||||
Command::Debug => {
|
||||
SupportedCommand::Debug => {
|
||||
unreachable!("The debug command should have already been handled")
|
||||
}
|
||||
}
|
||||
|
@ -119,31 +111,6 @@ impl super::SyncRequestHandler for ExecuteCommand {
|
|||
}
|
||||
}
|
||||
|
||||
impl Command {
|
||||
fn label(&self) -> &str {
|
||||
match self {
|
||||
Self::FixAll => "Fix all auto-fixable problems",
|
||||
Self::Format => "Format document",
|
||||
Self::OrganizeImports => "Format imports",
|
||||
Self::Debug => "Print debug information",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Command {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(name: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match name {
|
||||
"ruff.applyAutofix" => Self::FixAll,
|
||||
"ruff.applyFormat" => Self::Format,
|
||||
"ruff.applyOrganizeImports" => Self::OrganizeImports,
|
||||
"ruff.printDebugInformation" => Self::Debug,
|
||||
_ => return Err(anyhow::anyhow!("Invalid command `{name}`")),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_edit(
|
||||
requester: &mut client::Requester,
|
||||
label: &str,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue