helix
helix copied to clipboard
lsp: Check server provider capabilities
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 document notifications and signature-help. This change covers manually invoked LSP commands like hover, documentHighlight, codeActions, etc.
Signature help and some other requests in the LSP client module have a nice convention for this: return an Option over the future.
https://github.com/helix-editor/helix/blob/2d958d6c50b10318e29f6dacc291d8fcafd66de9/helix-lsp/src/client.rs#L657-L666
Having Err::Unsupported is tricky because the return type is currently impl Future<Output = Result<_>>, so if the method is unsupported, we need to wrap that error variant in a future instead of returning it immediately, or wrap the future in a Result itself which feels to me like too much. I'll refactor this to try out the Option<impl Future> pattern.
I refactored the LSP method functions to all return Option<impl Future>s instead of use async fns and checked the server capabilities within those functions.
I think there's a cleaner way where we could check within Client::call and have Client::call return an Option<impl Future> but in order to make it really nice we would want to add a member to the Request trait in the lsp_types crate:
pub trait Request {
// ...
fn is_supported(&self, server_capabilties: &ServerCapabilities) -> bool;
}
~We might also want to make modifications for https://github.com/helix-editor/helix/issues/2052 (adding a resolved: bool field to CompletionItem) so maybe we should vendor lsp_types? OTOH it's a 5k SLOC library which is pretty big.~