From e71a6a9fbe0beaba5959a5dc1e91219abb196983 Mon Sep 17 00:00:00 2001 From: Sysix <3897725+Sysix@users.noreply.github.com> Date: Wed, 12 Nov 2025 21:43:04 +0000 Subject: [PATCH] refactor(language_server): `provided_commands` and `provided_code_action_kinds` for `ToolBuilder` (#15610) --- crates/oxc_language_server/src/backend.rs | 2 +- .../oxc_language_server/src/capabilities.rs | 28 +++++++++---------- crates/oxc_language_server/src/linter/mod.rs | 2 -- .../src/linter/server_linter.rs | 13 +++++++-- crates/oxc_language_server/src/tool.rs | 13 +++++++++ 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/crates/oxc_language_server/src/backend.rs b/crates/oxc_language_server/src/backend.rs index 33d1c392dc857..6c24e62e71f0f 100644 --- a/crates/oxc_language_server/src/backend.rs +++ b/crates/oxc_language_server/src/backend.rs @@ -150,7 +150,7 @@ impl LanguageServer for Backend { version: Some(server_version.to_string()), }), offset_encoding: None, - capabilities: capabilities.into(), + capabilities: capabilities.server_capabilities(&self.tool_builders), }) } diff --git a/crates/oxc_language_server/src/capabilities.rs b/crates/oxc_language_server/src/capabilities.rs index ea4fa8c29fd9d..0503b1016173d 100644 --- a/crates/oxc_language_server/src/capabilities.rs +++ b/crates/oxc_language_server/src/capabilities.rs @@ -5,7 +5,7 @@ use tower_lsp_server::lsp_types::{ WorkDoneProgressOptions, WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, }; -use crate::linter::{CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC, FIX_ALL_COMMAND_ID}; +use crate::ToolBuilder; #[derive(Clone, Default)] pub struct Capabilities { @@ -57,9 +57,15 @@ impl From for Capabilities { } } -impl From for ServerCapabilities { - fn from(value: Capabilities) -> Self { - Self { +impl Capabilities { + pub fn server_capabilities(&self, tools: &[Box]) -> ServerCapabilities { + let code_action_kinds: Vec = + tools.iter().flat_map(|tool| tool.provided_code_action_kinds()).collect(); + + let commands: Vec = + tools.iter().flat_map(|tool| tool.provided_commands()).collect(); + + ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Options( TextDocumentSyncOptions { change: Some(TextDocumentSyncKind::FULL), @@ -77,12 +83,9 @@ impl From for ServerCapabilities { }), file_operations: None, }), - code_action_provider: if value.code_action_provider { + code_action_provider: if self.code_action_provider && !code_action_kinds.is_empty() { Some(CodeActionProviderCapability::Options(CodeActionOptions { - code_action_kinds: Some(vec![ - CodeActionKind::QUICKFIX, - CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC, - ]), + code_action_kinds: Some(code_action_kinds), work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None, }, @@ -91,11 +94,8 @@ impl From for ServerCapabilities { } else { None }, - execute_command_provider: if value.workspace_execute_command { - Some(ExecuteCommandOptions { - commands: vec![FIX_ALL_COMMAND_ID.to_string()], - ..Default::default() - }) + execute_command_provider: if self.workspace_execute_command && !commands.is_empty() { + Some(ExecuteCommandOptions { commands, ..Default::default() }) } else { None }, diff --git a/crates/oxc_language_server/src/linter/mod.rs b/crates/oxc_language_server/src/linter/mod.rs index 9d787eb3019f5..c8c05c4ea6587 100644 --- a/crates/oxc_language_server/src/linter/mod.rs +++ b/crates/oxc_language_server/src/linter/mod.rs @@ -8,8 +8,6 @@ mod server_linter; #[cfg(test)] mod tester; -pub use code_actions::CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC; -pub use commands::FIX_ALL_COMMAND_ID; pub use server_linter::ServerLinterBuilder; const LINT_CONFIG_FILE: &str = ".oxlintrc.json"; diff --git a/crates/oxc_language_server/src/linter/server_linter.rs b/crates/oxc_language_server/src/linter/server_linter.rs index d7493d5292c02..b1b0ea6703401 100644 --- a/crates/oxc_language_server/src/linter/server_linter.rs +++ b/crates/oxc_language_server/src/linter/server_linter.rs @@ -21,8 +21,11 @@ use oxc_linter::{ use crate::{ ConcurrentHashMap, linter::{ - CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC, LINT_CONFIG_FILE, - code_actions::{apply_all_fix_code_action, apply_fix_code_actions, fix_all_text_edit}, + LINT_CONFIG_FILE, + code_actions::{ + CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC, apply_all_fix_code_action, apply_fix_code_actions, + fix_all_text_edit, + }, commands::{FIX_ALL_COMMAND_ID, FixAllCommandArgs}, config_walker::ConfigWalker, error_with_position::DiagnosticReport, @@ -140,6 +143,12 @@ impl ServerLinterBuilder { } impl ToolBuilder for ServerLinterBuilder { + fn provided_code_action_kinds(&self) -> Vec { + vec![CodeActionKind::QUICKFIX, CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC] + } + fn provided_commands(&self) -> Vec { + vec![FIX_ALL_COMMAND_ID.to_string()] + } fn build_boxed(&self, root_uri: &Uri, options: serde_json::Value) -> Box { Box::new(ServerLinterBuilder::build(root_uri, options)) } diff --git a/crates/oxc_language_server/src/tool.rs b/crates/oxc_language_server/src/tool.rs index 5b9fb1455202e..4026f21d27c03 100644 --- a/crates/oxc_language_server/src/tool.rs +++ b/crates/oxc_language_server/src/tool.rs @@ -7,6 +7,19 @@ use tower_lsp_server::{ }; pub trait ToolBuilder: Send + Sync { + /// Get the commands provided by this tool. + /// This will be used to register the commands with the LSP Client. + fn provided_commands(&self) -> Vec { + Vec::new() + } + + /// Get the code action kinds provided by this tool. + /// This will be used to register the code action kinds with the LSP Client. + fn provided_code_action_kinds(&self) -> Vec { + Vec::new() + } + + /// Build a boxed instance of the tool for the given root URI and options. fn build_boxed(&self, root_uri: &Uri, options: serde_json::Value) -> Box; }