diff --git a/Cargo.lock b/Cargo.lock index c062366923d..5ce35c5b1dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -658,9 +658,9 @@ dependencies = [ [[package]] name = "lsp-server" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5383e043329615624bbf45e1ba27bd75c176762b2592855c659bc28ac580a06b" +checksum = "dccec31bfd027ac0dd288a78e19005fd89624d9099456e284b5241316a6c3072" dependencies = [ "crossbeam-channel", "log", diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 09908458dba..f5b4fee2bc7 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -74,12 +74,25 @@ fn run_server() -> Result<()> { log::info!("lifecycle: server started"); let (connection, io_threads) = Connection::stdio(); - let server_capabilities = serde_json::to_value(rust_analyzer::server_capabilities()).unwrap(); - let initialize_params = connection.initialize(server_capabilities)?; + let (initialize_id, initialize_params) = connection.initialize_start()?; let initialize_params = from_json::<lsp_types::InitializeParams>("InitializeParams", initialize_params)?; + let server_capabilities = rust_analyzer::server_capabilities(&initialize_params.capabilities); + + let initialize_result = lsp_types::InitializeResult { + capabilities: server_capabilities, + server_info: Some(lsp_types::ServerInfo { + name: String::from("rust-analyzer"), + version: None, + }), + }; + + let initialize_result = serde_json::to_value(initialize_result).unwrap(); + + connection.initialize_finish(initialize_id, initialize_result)?; + if let Some(client_info) = initialize_params.client_info { log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); } diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 110c9a44297..5ac98c65728 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs @@ -4,16 +4,47 @@ use std::env; use crate::semantic_tokens; use lsp_types::{ - CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability, - CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions, - FoldingRangeProviderCapability, ImplementationProviderCapability, RenameOptions, - RenameProviderCapability, SaveOptions, SelectionRangeProviderCapability, - SemanticTokensDocumentProvider, SemanticTokensLegend, SemanticTokensOptions, - ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, - TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, + CallHierarchyServerCapability, ClientCapabilities, CodeActionOptions, + CodeActionProviderCapability, CodeLensOptions, CompletionOptions, + DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, + ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions, + SelectionRangeProviderCapability, SemanticTokensDocumentProvider, SemanticTokensLegend, + SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, + TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability, + WorkDoneProgressOptions, }; -pub fn server_capabilities() -> ServerCapabilities { +pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabilities { + let mut code_action_provider = CodeActionProviderCapability::Simple(true); + + match client_caps.text_document.as_ref() { + Some(it) => { + match it.code_action.as_ref().and_then(|c| c.code_action_literal_support.as_ref()) { + Some(_literal_support) => { + code_action_provider = + CodeActionProviderCapability::Options(CodeActionOptions { + // Advertise support for all built-in CodeActionKinds. + // Ideally we would base this off of the client capabilities + // but the client is supposed to fall back gracefully for unknown values. + code_action_kinds: Some(vec![ + lsp_types::code_action_kind::EMPTY.to_string(), + lsp_types::code_action_kind::QUICKFIX.to_string(), + lsp_types::code_action_kind::REFACTOR.to_string(), + lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(), + lsp_types::code_action_kind::REFACTOR_INLINE.to_string(), + lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(), + lsp_types::code_action_kind::SOURCE.to_string(), + lsp_types::code_action_kind::SOURCE_ORGANIZE_IMPORTS.to_string(), + ]), + work_done_progress_options: Default::default(), + }); + } + None => {} + } + } + None => {} + }; + ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { open_close: Some(true), @@ -45,20 +76,7 @@ pub fn server_capabilities() -> ServerCapabilities { document_highlight_provider: Some(true), document_symbol_provider: Some(true), workspace_symbol_provider: Some(true), - code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions { - // Advertise support for all built-in CodeActionKinds - code_action_kinds: Some(vec![ - lsp_types::code_action_kind::EMPTY.to_string(), - lsp_types::code_action_kind::QUICKFIX.to_string(), - lsp_types::code_action_kind::REFACTOR.to_string(), - lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(), - lsp_types::code_action_kind::REFACTOR_INLINE.to_string(), - lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(), - lsp_types::code_action_kind::SOURCE.to_string(), - lsp_types::code_action_kind::SOURCE_ORGANIZE_IMPORTS.to_string(), - ]), - work_done_progress_options: Default::default(), - })), + code_action_provider: Some(code_action_provider), code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), document_formatting_provider: Some(true), document_range_formatting_provider: None,