Skip to content

Commit

Permalink
lsp: Check server provider capabilities
Browse files Browse the repository at this point in the history
Language Servers may signal that they do not support a method in
the initialization result (server capabilities). We can check these
when making LSP requests and hint in the status line when a method
is not supported by the server. This can also prevent crashes in
servers which assume that clients do not send requests for methods
which are disabled in the server capabilities.

We already check server capabilities for automatic auto-complete
and signature-help. This change covers manually invoked LSP commands
like hover, documentHighlight, codeActions, etc.
  • Loading branch information
the-mikedavis committed Aug 26, 2022
1 parent 86a8ea5 commit e7eedb5
Showing 1 changed file with 101 additions and 0 deletions.
101 changes: 101 additions & 0 deletions helix-term/src/commands/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,16 @@ pub fn symbol_picker(cx: &mut Context) {
let doc = doc!(cx.editor);

let language_server = language_server!(cx.editor, doc);

if matches!(
language_server.capabilities().workspace_symbol_provider,
None | Some(lsp::OneOf::Left(false))
) {
cx.editor
.set_status("Document symbols are not enabled by the Language Server");
return;
}

let current_url = doc.url();
let offset_encoding = language_server.offset_encoding();

Expand Down Expand Up @@ -359,6 +369,16 @@ pub fn workspace_symbol_picker(cx: &mut Context) {
let doc = doc!(cx.editor);
let current_url = doc.url();
let language_server = language_server!(cx.editor, doc);

if matches!(
language_server.capabilities().workspace_symbol_provider,
None | Some(lsp::OneOf::Left(false))
) {
cx.editor
.set_status("Workspace symbols are not enabled by the Language Server");
return;
}

let offset_encoding = language_server.offset_encoding();
let future = language_server.workspace_symbols("".to_string());

Expand Down Expand Up @@ -426,6 +446,15 @@ pub fn code_action(cx: &mut Context) {

let language_server = language_server!(cx.editor, doc);

if matches!(
language_server.capabilities().code_action_provider,
None | Some(lsp::CodeActionProviderCapability::Simple(false))
) {
cx.editor
.set_status("Code actions are not enabled by the Language Server");
return;
}

let selection_range = doc.selection(view.id).primary();
let offset_encoding = language_server.offset_encoding();

Expand Down Expand Up @@ -737,6 +766,16 @@ fn to_locations(definitions: Option<lsp::GotoDefinitionResponse>) -> Vec<lsp::Lo
pub fn goto_definition(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
let language_server = language_server!(cx.editor, doc);

if matches!(
language_server.capabilities().definition_provider,
None | Some(lsp::OneOf::Left(false))
) {
cx.editor
.set_status("Find definition is not enabled by the Language Server");
return;
}

let offset_encoding = language_server.offset_encoding();

let pos = doc.position(view.id, offset_encoding);
Expand All @@ -755,6 +794,16 @@ pub fn goto_definition(cx: &mut Context) {
pub fn goto_type_definition(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
let language_server = language_server!(cx.editor, doc);

if matches!(
language_server.capabilities().type_definition_provider,
None | Some(lsp::TypeDefinitionProviderCapability::Simple(false))
) {
cx.editor
.set_status("Find type definition is not enabled by the Language Server");
return;
}

let offset_encoding = language_server.offset_encoding();

let pos = doc.position(view.id, offset_encoding);
Expand All @@ -773,6 +822,16 @@ pub fn goto_type_definition(cx: &mut Context) {
pub fn goto_implementation(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
let language_server = language_server!(cx.editor, doc);

if matches!(
language_server.capabilities().implementation_provider,
None | Some(lsp::ImplementationProviderCapability::Simple(false))
) {
cx.editor
.set_status("Find implementation is not enabled by the Language Server");
return;
}

let offset_encoding = language_server.offset_encoding();

let pos = doc.position(view.id, offset_encoding);
Expand All @@ -791,6 +850,16 @@ pub fn goto_implementation(cx: &mut Context) {
pub fn goto_reference(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
let language_server = language_server!(cx.editor, doc);

if matches!(
language_server.capabilities().references_provider,
None | Some(lsp::OneOf::Left(false))
) {
cx.editor
.set_status("Find references is not enabled by the Language Server");
return;
}

let offset_encoding = language_server.offset_encoding();

let pos = doc.position(view.id, offset_encoding);
Expand Down Expand Up @@ -832,6 +901,18 @@ pub fn signature_help_impl(cx: &mut Context, invoked: SignatureHelpInvoked) {
return;
}
};

if was_manually_invoked
&& language_server
.capabilities()
.signature_help_provider
.is_none()
{
cx.editor
.set_status("Signature help is not enabled by the Language Server");
return;
}

let offset_encoding = language_server.offset_encoding();

let pos = doc.position(view.id, offset_encoding);
Expand Down Expand Up @@ -928,6 +1009,16 @@ pub fn signature_help_impl(cx: &mut Context, invoked: SignatureHelpInvoked) {
pub fn hover(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
let language_server = language_server!(cx.editor, doc);

if matches!(
language_server.capabilities().hover_provider,
None | Some(lsp::HoverProviderCapability::Simple(false))
) {
cx.editor
.set_status("Hover is not enabled by the Language Server");
return;
}

let offset_encoding = language_server.offset_encoding();

// TODO: factor out a doc.position_identifier() that returns lsp::TextDocumentPositionIdentifier
Expand Down Expand Up @@ -1016,6 +1107,16 @@ pub fn rename_symbol(cx: &mut Context) {
pub fn select_references_to_symbol_under_cursor(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
let language_server = language_server!(cx.editor, doc);

if matches!(
language_server.capabilities().document_highlight_provider,
None | Some(lsp::OneOf::Left(false))
) {
cx.editor
.set_status("Document highlight is not enabled by the Language Server");
return;
}

let offset_encoding = language_server.offset_encoding();

let pos = doc.position(view.id, offset_encoding);
Expand Down

0 comments on commit e7eedb5

Please sign in to comment.