From ff262084271492bba239dbc2e5788be3c4d5a4e5 Mon Sep 17 00:00:00 2001 From: Philipp Mildenberger Date: Mon, 20 Mar 2023 17:44:04 +0100 Subject: Filter language servers also by capabilities in `doc.language_servers_with_feature` * Add `helix_lsp::client::Client::supports_feature(&self, LanguageServerFeature)` * Extend `doc.language_servers_with_feature` to use this method as filter as well * Add macro `language_server_with_feature!` to reduce boilerplate for non-mergeable language server requests (like goto-definition) * Refactored most of the `find_map` code to use the either the macro or filter directly via `doc.language_servers_with_feature` --- helix-lsp/src/client.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 10 deletions(-) (limited to 'helix-lsp/src') diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs index 65c6954d..b1a73247 100644 --- a/helix-lsp/src/client.rs +++ b/helix-lsp/src/client.rs @@ -4,7 +4,7 @@ use crate::{ Call, Error, OffsetEncoding, Result, }; -use helix_core::{find_workspace, path, ChangeSet, Rope}; +use helix_core::{find_workspace, path, syntax::LanguageServerFeature, ChangeSet, Rope}; use helix_loader::{self, VERSION_AND_GIT_HASH}; use lsp::{ notification::DidChangeWorkspaceFolders, DidChangeWorkspaceFoldersParams, OneOf, @@ -276,6 +276,93 @@ impl Client { .expect("language server not yet initialized!") } + #[inline] // TODO inline? + pub fn supports_feature(&self, feature: LanguageServerFeature) -> bool { + let capabilities = match self.capabilities.get() { + Some(capabilities) => capabilities, + None => return false, // not initialized, TODO unwrap/expect instead? + }; + match feature { + LanguageServerFeature::Format => matches!( + capabilities.document_formatting_provider, + Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) + ), + LanguageServerFeature::GotoDeclaration => matches!( + capabilities.declaration_provider, + Some( + lsp::DeclarationCapability::Simple(true) + | lsp::DeclarationCapability::RegistrationOptions(_) + | lsp::DeclarationCapability::Options(_), + ) + ), + LanguageServerFeature::GotoDefinition => matches!( + capabilities.definition_provider, + Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) + ), + LanguageServerFeature::GotoTypeDefinition => matches!( + capabilities.type_definition_provider, + Some( + lsp::TypeDefinitionProviderCapability::Simple(true) + | lsp::TypeDefinitionProviderCapability::Options(_), + ) + ), + LanguageServerFeature::GotoReference => matches!( + capabilities.references_provider, + Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) + ), + LanguageServerFeature::GotoImplementation => matches!( + capabilities.implementation_provider, + Some( + lsp::ImplementationProviderCapability::Simple(true) + | lsp::ImplementationProviderCapability::Options(_), + ) + ), + LanguageServerFeature::SignatureHelp => capabilities.signature_help_provider.is_some(), + LanguageServerFeature::Hover => matches!( + capabilities.hover_provider, + Some( + lsp::HoverProviderCapability::Simple(true) + | lsp::HoverProviderCapability::Options(_), + ) + ), + LanguageServerFeature::DocumentHighlight => matches!( + capabilities.document_highlight_provider, + Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) + ), + LanguageServerFeature::Completion => capabilities.completion_provider.is_some(), + LanguageServerFeature::CodeAction => matches!( + capabilities.code_action_provider, + Some( + lsp::CodeActionProviderCapability::Simple(true) + | lsp::CodeActionProviderCapability::Options(_), + ) + ), + LanguageServerFeature::WorkspaceCommand => { + capabilities.execute_command_provider.is_some() + } + LanguageServerFeature::DocumentSymbols => matches!( + capabilities.document_symbol_provider, + Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) + ), + LanguageServerFeature::WorkspaceSymbols => matches!( + capabilities.workspace_symbol_provider, + Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) + ), + LanguageServerFeature::Diagnostics => true, // there's no extra server capability + LanguageServerFeature::RenameSymbol => matches!( + capabilities.rename_provider, + Some(lsp::OneOf::Left(true)) | Some(lsp::OneOf::Right(_)) + ), + LanguageServerFeature::InlayHints => matches!( + capabilities.inlay_hint_provider, + Some( + lsp::OneOf::Left(true) + | lsp::OneOf::Right(lsp::InlayHintServerCapabilities::Options(_)) + ) + ), + } + } + pub fn offset_encoding(&self) -> OffsetEncoding { self.capabilities() .position_encoding @@ -1301,21 +1388,13 @@ impl Client { Some(self.call::(params)) } - pub fn supports_rename(&self) -> bool { - let capabilities = self.capabilities.get().unwrap(); - matches!( - capabilities.rename_provider, - Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) - ) - } - pub fn rename_symbol( &self, text_document: lsp::TextDocumentIdentifier, position: lsp::Position, new_name: String, ) -> Option>> { - if !self.supports_rename() { + if !self.supports_feature(LanguageServerFeature::RenameSymbol) { return None; } -- cgit v1.2.3-70-g09d2