From 6bf4fc27d923207df36d06da295d815d768f3a0b Mon Sep 17 00:00:00 2001 From: kjeremy Date: Tue, 19 May 2020 11:56:51 -0400 Subject: [PATCH 1/3] LSP: Two stage initialization Fills in server information. Derives CodeAction capabilities from the client. If code action literals are unsupported we fall back to the "simple support" which just sends back commands (this is already supported in our config). The difference being that we did not adjust our server capabilities so that if the client was checking for `CodeActionProvider: "true"` in the response that would have failed. --- Cargo.lock | 4 +- crates/rust-analyzer/src/bin/main.rs | 17 +++++++- crates/rust-analyzer/src/caps.rs | 62 ++++++++++++++++++---------- 3 files changed, 57 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c062366923dd..5ce35c5b1dc7 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 09908458dba7..f5b4fee2bc7a 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::("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 110c9a442975..5ac98c65728b 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, From e3ae298e7869e8b403c91426d7c88c98558767ea Mon Sep 17 00:00:00 2001 From: kjeremy Date: Tue, 19 May 2020 17:22:38 -0400 Subject: [PATCH 2/3] Fill code action capabilities with a function --- crates/rust-analyzer/src/caps.rs | 56 +++++++++++++++----------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 5ac98c65728b..4effc82ca118 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs @@ -15,35 +15,7 @@ use lsp_types::{ }; 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 => {} - }; + let code_action_provider = code_action_capabilities(client_caps); ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { @@ -112,3 +84,29 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti experimental: Default::default(), } } + +fn code_action_capabilities(client_caps: &ClientCapabilities) -> CodeActionProviderCapability { + client_caps + .text_document + .as_ref() + .and_then(|it| it.code_action.as_ref()) + .and_then(|it| it.code_action_literal_support.as_ref()) + .map_or(CodeActionProviderCapability::Simple(true), |_| { + 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(), + }) + }) +} From acc5e8d64b9b3d75798407d4ea4a6ba39d96eb60 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Tue, 19 May 2020 18:12:07 -0400 Subject: [PATCH 3/3] Add version --- crates/rust-analyzer/src/bin/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index f5b4fee2bc7a..e82fd57de84d 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -85,7 +85,7 @@ fn run_server() -> Result<()> { capabilities: server_capabilities, server_info: Some(lsp_types::ServerInfo { name: String::from("rust-analyzer"), - version: None, + version: Some(String::from(env!("REV"))), }), };