aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkjeremy <[email protected]>2020-05-19 16:56:51 +0100
committerkjeremy <[email protected]>2020-05-19 16:56:51 +0100
commit6bf4fc27d923207df36d06da295d815d768f3a0b (patch)
tree7c7e3de3ca91efd1d15b51d8102f5e226c055c7c
parent5c1c23ecc7c94fae0948abe8af7a700e42e20921 (diff)
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.
-rw-r--r--Cargo.lock4
-rw-r--r--crates/rust-analyzer/src/bin/main.rs17
-rw-r--r--crates/rust-analyzer/src/caps.rs62
3 files changed, 57 insertions, 26 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c06236692..5ce35c5b1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -658,9 +658,9 @@ dependencies = [
658 658
659[[package]] 659[[package]]
660name = "lsp-server" 660name = "lsp-server"
661version = "0.3.1" 661version = "0.3.2"
662source = "registry+https://github.com/rust-lang/crates.io-index" 662source = "registry+https://github.com/rust-lang/crates.io-index"
663checksum = "5383e043329615624bbf45e1ba27bd75c176762b2592855c659bc28ac580a06b" 663checksum = "dccec31bfd027ac0dd288a78e19005fd89624d9099456e284b5241316a6c3072"
664dependencies = [ 664dependencies = [
665 "crossbeam-channel", 665 "crossbeam-channel",
666 "log", 666 "log",
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 09908458d..f5b4fee2b 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<()> {
74 log::info!("lifecycle: server started"); 74 log::info!("lifecycle: server started");
75 75
76 let (connection, io_threads) = Connection::stdio(); 76 let (connection, io_threads) = Connection::stdio();
77 let server_capabilities = serde_json::to_value(rust_analyzer::server_capabilities()).unwrap();
78 77
79 let initialize_params = connection.initialize(server_capabilities)?; 78 let (initialize_id, initialize_params) = connection.initialize_start()?;
80 let initialize_params = 79 let initialize_params =
81 from_json::<lsp_types::InitializeParams>("InitializeParams", initialize_params)?; 80 from_json::<lsp_types::InitializeParams>("InitializeParams", initialize_params)?;
82 81
82 let server_capabilities = rust_analyzer::server_capabilities(&initialize_params.capabilities);
83
84 let initialize_result = lsp_types::InitializeResult {
85 capabilities: server_capabilities,
86 server_info: Some(lsp_types::ServerInfo {
87 name: String::from("rust-analyzer"),
88 version: None,
89 }),
90 };
91
92 let initialize_result = serde_json::to_value(initialize_result).unwrap();
93
94 connection.initialize_finish(initialize_id, initialize_result)?;
95
83 if let Some(client_info) = initialize_params.client_info { 96 if let Some(client_info) = initialize_params.client_info {
84 log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); 97 log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default());
85 } 98 }
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 110c9a442..5ac98c657 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -4,16 +4,47 @@ use std::env;
4use crate::semantic_tokens; 4use crate::semantic_tokens;
5 5
6use lsp_types::{ 6use lsp_types::{
7 CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability, 7 CallHierarchyServerCapability, ClientCapabilities, CodeActionOptions,
8 CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions, 8 CodeActionProviderCapability, CodeLensOptions, CompletionOptions,
9 FoldingRangeProviderCapability, ImplementationProviderCapability, RenameOptions, 9 DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability,
10 RenameProviderCapability, SaveOptions, SelectionRangeProviderCapability, 10 ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions,
11 SemanticTokensDocumentProvider, SemanticTokensLegend, SemanticTokensOptions, 11 SelectionRangeProviderCapability, SemanticTokensDocumentProvider, SemanticTokensLegend,
12 ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, 12 SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability,
13 TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, 13 TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability,
14 WorkDoneProgressOptions,
14}; 15};
15 16
16pub fn server_capabilities() -> ServerCapabilities { 17pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabilities {
18 let mut code_action_provider = CodeActionProviderCapability::Simple(true);
19
20 match client_caps.text_document.as_ref() {
21 Some(it) => {
22 match it.code_action.as_ref().and_then(|c| c.code_action_literal_support.as_ref()) {
23 Some(_literal_support) => {
24 code_action_provider =
25 CodeActionProviderCapability::Options(CodeActionOptions {
26 // Advertise support for all built-in CodeActionKinds.
27 // Ideally we would base this off of the client capabilities
28 // but the client is supposed to fall back gracefully for unknown values.
29 code_action_kinds: Some(vec![
30 lsp_types::code_action_kind::EMPTY.to_string(),
31 lsp_types::code_action_kind::QUICKFIX.to_string(),
32 lsp_types::code_action_kind::REFACTOR.to_string(),
33 lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(),
34 lsp_types::code_action_kind::REFACTOR_INLINE.to_string(),
35 lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(),
36 lsp_types::code_action_kind::SOURCE.to_string(),
37 lsp_types::code_action_kind::SOURCE_ORGANIZE_IMPORTS.to_string(),
38 ]),
39 work_done_progress_options: Default::default(),
40 });
41 }
42 None => {}
43 }
44 }
45 None => {}
46 };
47
17 ServerCapabilities { 48 ServerCapabilities {
18 text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { 49 text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
19 open_close: Some(true), 50 open_close: Some(true),
@@ -45,20 +76,7 @@ pub fn server_capabilities() -> ServerCapabilities {
45 document_highlight_provider: Some(true), 76 document_highlight_provider: Some(true),
46 document_symbol_provider: Some(true), 77 document_symbol_provider: Some(true),
47 workspace_symbol_provider: Some(true), 78 workspace_symbol_provider: Some(true),
48 code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions { 79 code_action_provider: Some(code_action_provider),
49 // Advertise support for all built-in CodeActionKinds
50 code_action_kinds: Some(vec![
51 lsp_types::code_action_kind::EMPTY.to_string(),
52 lsp_types::code_action_kind::QUICKFIX.to_string(),
53 lsp_types::code_action_kind::REFACTOR.to_string(),
54 lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(),
55 lsp_types::code_action_kind::REFACTOR_INLINE.to_string(),
56 lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(),
57 lsp_types::code_action_kind::SOURCE.to_string(),
58 lsp_types::code_action_kind::SOURCE_ORGANIZE_IMPORTS.to_string(),
59 ]),
60 work_done_progress_options: Default::default(),
61 })),
62 code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), 80 code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
63 document_formatting_provider: Some(true), 81 document_formatting_provider: Some(true),
64 document_range_formatting_provider: None, 82 document_range_formatting_provider: None,