diff options
author | kjeremy <[email protected]> | 2020-05-19 16:56:51 +0100 |
---|---|---|
committer | kjeremy <[email protected]> | 2020-05-19 16:56:51 +0100 |
commit | 6bf4fc27d923207df36d06da295d815d768f3a0b (patch) | |
tree | 7c7e3de3ca91efd1d15b51d8102f5e226c055c7c | |
parent | 5c1c23ecc7c94fae0948abe8af7a700e42e20921 (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.lock | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/main.rs | 17 | ||||
-rw-r--r-- | crates/rust-analyzer/src/caps.rs | 62 |
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]] |
660 | name = "lsp-server" | 660 | name = "lsp-server" |
661 | version = "0.3.1" | 661 | version = "0.3.2" |
662 | source = "registry+https://github.com/rust-lang/crates.io-index" | 662 | source = "registry+https://github.com/rust-lang/crates.io-index" |
663 | checksum = "5383e043329615624bbf45e1ba27bd75c176762b2592855c659bc28ac580a06b" | 663 | checksum = "dccec31bfd027ac0dd288a78e19005fd89624d9099456e284b5241316a6c3072" |
664 | dependencies = [ | 664 | dependencies = [ |
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; | |||
4 | use crate::semantic_tokens; | 4 | use crate::semantic_tokens; |
5 | 5 | ||
6 | use lsp_types::{ | 6 | use 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 | ||
16 | pub fn server_capabilities() -> ServerCapabilities { | 17 | pub 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, |