summaryrefslogtreecommitdiff
path: root/helix-lsp/src/client.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-lsp/src/client.rs')
-rw-r--r--helix-lsp/src/client.rs105
1 files changed, 92 insertions, 13 deletions
diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index 840e7382..a3711317 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,
@@ -44,6 +44,7 @@ fn workspace_for_uri(uri: lsp::Url) -> WorkspaceFolder {
#[derive(Debug)]
pub struct Client {
id: usize,
+ name: String,
_process: Child,
server_tx: UnboundedSender<Payload>,
request_counter: AtomicU64,
@@ -166,8 +167,7 @@ impl Client {
tokio::spawn(self.did_change_workspace(vec![workspace_for_uri(root_uri)], Vec::new()));
}
- #[allow(clippy::type_complexity)]
- #[allow(clippy::too_many_arguments)]
+ #[allow(clippy::type_complexity, clippy::too_many_arguments)]
pub fn start(
cmd: &str,
args: &[String],
@@ -176,6 +176,7 @@ impl Client {
root_markers: &[String],
manual_roots: &[PathBuf],
id: usize,
+ name: String,
req_timeout: u64,
doc_path: Option<&std::path::PathBuf>,
) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
@@ -200,7 +201,7 @@ impl Client {
let stderr = BufReader::new(process.stderr.take().expect("Failed to open stderr"));
let (server_rx, server_tx, initialize_notify) =
- Transport::start(reader, writer, stderr, id);
+ Transport::start(reader, writer, stderr, id, name.clone());
let (workspace, workspace_is_cwd) = find_workspace();
let workspace = path::get_normalized_path(&workspace);
let root = find_lsp_workspace(
@@ -225,6 +226,7 @@ impl Client {
let client = Self {
id,
+ name,
_process: process,
server_tx,
request_counter: AtomicU64::new(0),
@@ -240,6 +242,10 @@ impl Client {
Ok((client, server_rx, initialize_notify))
}
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
pub fn id(&self) -> usize {
self.id
}
@@ -270,6 +276,87 @@ impl Client {
.expect("language server not yet initialized!")
}
+ /// Client has to be initialized otherwise this function panics
+ #[inline]
+ pub fn supports_feature(&self, feature: LanguageServerFeature) -> bool {
+ let capabilities = self.capabilities();
+
+ use lsp::*;
+ match feature {
+ LanguageServerFeature::Format => matches!(
+ capabilities.document_formatting_provider,
+ Some(OneOf::Left(true) | OneOf::Right(_))
+ ),
+ LanguageServerFeature::GotoDeclaration => matches!(
+ capabilities.declaration_provider,
+ Some(
+ DeclarationCapability::Simple(true)
+ | DeclarationCapability::RegistrationOptions(_)
+ | DeclarationCapability::Options(_),
+ )
+ ),
+ LanguageServerFeature::GotoDefinition => matches!(
+ capabilities.definition_provider,
+ Some(OneOf::Left(true) | OneOf::Right(_))
+ ),
+ LanguageServerFeature::GotoTypeDefinition => matches!(
+ capabilities.type_definition_provider,
+ Some(
+ TypeDefinitionProviderCapability::Simple(true)
+ | TypeDefinitionProviderCapability::Options(_),
+ )
+ ),
+ LanguageServerFeature::GotoReference => matches!(
+ capabilities.references_provider,
+ Some(OneOf::Left(true) | OneOf::Right(_))
+ ),
+ LanguageServerFeature::GotoImplementation => matches!(
+ capabilities.implementation_provider,
+ Some(
+ ImplementationProviderCapability::Simple(true)
+ | ImplementationProviderCapability::Options(_),
+ )
+ ),
+ LanguageServerFeature::SignatureHelp => capabilities.signature_help_provider.is_some(),
+ LanguageServerFeature::Hover => matches!(
+ capabilities.hover_provider,
+ Some(HoverProviderCapability::Simple(true) | HoverProviderCapability::Options(_),)
+ ),
+ LanguageServerFeature::DocumentHighlight => matches!(
+ capabilities.document_highlight_provider,
+ Some(OneOf::Left(true) | OneOf::Right(_))
+ ),
+ LanguageServerFeature::Completion => capabilities.completion_provider.is_some(),
+ LanguageServerFeature::CodeAction => matches!(
+ capabilities.code_action_provider,
+ Some(
+ CodeActionProviderCapability::Simple(true)
+ | CodeActionProviderCapability::Options(_),
+ )
+ ),
+ LanguageServerFeature::WorkspaceCommand => {
+ capabilities.execute_command_provider.is_some()
+ }
+ LanguageServerFeature::DocumentSymbols => matches!(
+ capabilities.document_symbol_provider,
+ Some(OneOf::Left(true) | OneOf::Right(_))
+ ),
+ LanguageServerFeature::WorkspaceSymbols => matches!(
+ capabilities.workspace_symbol_provider,
+ Some(OneOf::Left(true) | OneOf::Right(_))
+ ),
+ LanguageServerFeature::Diagnostics => true, // there's no extra server capability
+ LanguageServerFeature::RenameSymbol => matches!(
+ capabilities.rename_provider,
+ Some(OneOf::Left(true)) | Some(OneOf::Right(_))
+ ),
+ LanguageServerFeature::InlayHints => matches!(
+ capabilities.inlay_hint_provider,
+ Some(OneOf::Left(true) | OneOf::Right(InlayHintServerCapabilities::Options(_)))
+ ),
+ }
+ }
+
pub fn offset_encoding(&self) -> OffsetEncoding {
self.capabilities()
.position_encoding
@@ -1295,21 +1382,13 @@ impl Client {
Some(self.call::<lsp::request::CodeActionRequest>(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<impl Future<Output = Result<lsp::WorkspaceEdit>>> {
- if !self.supports_rename() {
+ if !self.supports_feature(LanguageServerFeature::RenameSymbol) {
return None;
}