diff options
-rw-r--r-- | crates/rust-analyzer/src/caps.rs | 108 |
1 files changed, 72 insertions, 36 deletions
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 37d695448..34fefe034 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs | |||
@@ -7,16 +7,18 @@ use lsp_types::{ | |||
7 | DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, HoverProviderCapability, | 7 | DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, HoverProviderCapability, |
8 | ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions, | 8 | ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions, |
9 | SelectionRangeProviderCapability, SemanticTokensDocumentProvider, SemanticTokensLegend, | 9 | SelectionRangeProviderCapability, SemanticTokensDocumentProvider, SemanticTokensLegend, |
10 | SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, | 10 | SemanticTokensOptions, SemanticTokensServerCapabilities, ServerCapabilities, |
11 | TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability, | 11 | SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, |
12 | WorkDoneProgressOptions, | 12 | TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, |
13 | }; | 13 | }; |
14 | use serde_json::json; | 14 | use serde_json::{json, Value}; |
15 | 15 | ||
16 | use crate::semantic_tokens; | 16 | use crate::semantic_tokens; |
17 | 17 | ||
18 | pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabilities { | 18 | pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabilities { |
19 | let code_action_provider = code_action_capabilities(client_caps); | 19 | let code_action_provider = code_action_capabilities(client_caps); |
20 | let semantic_tokens_provider = semantic_tokens_capabilities(client_caps); | ||
21 | let experimental = experimental_capabilities(client_caps); | ||
20 | 22 | ||
21 | ServerCapabilities { | 23 | ServerCapabilities { |
22 | text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { | 24 | text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { |
@@ -69,29 +71,58 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti | |||
69 | execute_command_provider: None, | 71 | execute_command_provider: None, |
70 | workspace: None, | 72 | workspace: None, |
71 | call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)), | 73 | call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)), |
72 | semantic_tokens_provider: Some( | 74 | semantic_tokens_provider, |
73 | SemanticTokensOptions { | 75 | experimental, |
74 | legend: SemanticTokensLegend { | 76 | } |
75 | token_types: semantic_tokens::SUPPORTED_TYPES.to_vec(), | 77 | } |
76 | token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.to_vec(), | ||
77 | }, | ||
78 | 78 | ||
79 | document_provider: Some(SemanticTokensDocumentProvider::Bool(true)), | 79 | fn experimental_capabilities(client_caps: &ClientCapabilities) -> Option<Value> { |
80 | range_provider: Some(true), | 80 | client_caps.experimental.as_ref().and_then(|it| { |
81 | work_done_progress_options: Default::default(), | 81 | it.as_object().map(|map| { |
82 | let mut obj = json!({}); | ||
83 | let result = obj.as_object_mut().unwrap(); | ||
84 | |||
85 | if map.contains_key("joinLines") { | ||
86 | result.insert("joinLines".into(), true.into()); | ||
87 | } | ||
88 | |||
89 | if map.contains_key("ssr") { | ||
90 | result.insert("ssr".into(), true.into()); | ||
91 | } | ||
92 | |||
93 | if map.contains_key("onEnter") { | ||
94 | result.insert("onEnter".into(), true.into()); | ||
82 | } | 95 | } |
83 | .into(), | 96 | |
84 | ), | 97 | if map.contains_key("parentModule") { |
85 | experimental: Some(json!({ | 98 | result.insert("parentModule".into(), true.into()); |
86 | "joinLines": true, | 99 | } |
87 | "ssr": true, | 100 | |
88 | "onEnter": true, | 101 | if map.contains_key("runnables") { |
89 | "parentModule": true, | 102 | result.insert("runnables".into(), json!({ "kinds": [ "cargo" ] })); |
90 | "runnables": { | 103 | } |
91 | "kinds": [ "cargo" ], | 104 | |
105 | obj | ||
106 | }) | ||
107 | }) | ||
108 | } | ||
109 | |||
110 | fn semantic_tokens_capabilities( | ||
111 | client_caps: &ClientCapabilities, | ||
112 | ) -> Option<SemanticTokensServerCapabilities> { | ||
113 | client_caps.text_document.as_ref().and_then(|it| it.semantic_tokens.as_ref()).map(|_| | ||
114 | // client supports semanticTokens | ||
115 | SemanticTokensOptions { | ||
116 | legend: SemanticTokensLegend { | ||
117 | token_types: semantic_tokens::SUPPORTED_TYPES.to_vec(), | ||
118 | token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.to_vec(), | ||
92 | }, | 119 | }, |
93 | })), | 120 | |
94 | } | 121 | document_provider: Some(SemanticTokensDocumentProvider::Bool(true)), |
122 | range_provider: Some(true), | ||
123 | work_done_progress_options: Default::default(), | ||
124 | } | ||
125 | .into()) | ||
95 | } | 126 | } |
96 | 127 | ||
97 | fn code_action_capabilities(client_caps: &ClientCapabilities) -> CodeActionProviderCapability { | 128 | fn code_action_capabilities(client_caps: &ClientCapabilities) -> CodeActionProviderCapability { |
@@ -100,19 +131,24 @@ fn code_action_capabilities(client_caps: &ClientCapabilities) -> CodeActionProvi | |||
100 | .as_ref() | 131 | .as_ref() |
101 | .and_then(|it| it.code_action.as_ref()) | 132 | .and_then(|it| it.code_action.as_ref()) |
102 | .and_then(|it| it.code_action_literal_support.as_ref()) | 133 | .and_then(|it| it.code_action_literal_support.as_ref()) |
103 | .map_or(CodeActionProviderCapability::Simple(true), |_| { | 134 | .map_or(CodeActionProviderCapability::Simple(true), |caps| { |
135 | let mut action_kinds = vec![ | ||
136 | CodeActionKind::EMPTY, | ||
137 | CodeActionKind::QUICKFIX, | ||
138 | CodeActionKind::REFACTOR, | ||
139 | CodeActionKind::REFACTOR_EXTRACT, | ||
140 | CodeActionKind::REFACTOR_INLINE, | ||
141 | CodeActionKind::REFACTOR_REWRITE, | ||
142 | ]; | ||
143 | |||
144 | // Not all clients can fall back gracefully for unknown values. | ||
145 | // Microsoft.VisualStudio.LanguageServer.Protocol.CodeActionKind does not support CodeActionKind::EMPTY | ||
146 | // So have to filter out. | ||
147 | action_kinds | ||
148 | .retain(|it| caps.code_action_kind.value_set.contains(&it.as_str().to_owned())); | ||
149 | |||
104 | CodeActionProviderCapability::Options(CodeActionOptions { | 150 | CodeActionProviderCapability::Options(CodeActionOptions { |
105 | // Advertise support for all built-in CodeActionKinds. | 151 | code_action_kinds: Some(action_kinds), |
106 | // Ideally we would base this off of the client capabilities | ||
107 | // but the client is supposed to fall back gracefully for unknown values. | ||
108 | code_action_kinds: Some(vec![ | ||
109 | CodeActionKind::EMPTY, | ||
110 | CodeActionKind::QUICKFIX, | ||
111 | CodeActionKind::REFACTOR, | ||
112 | CodeActionKind::REFACTOR_EXTRACT, | ||
113 | CodeActionKind::REFACTOR_INLINE, | ||
114 | CodeActionKind::REFACTOR_REWRITE, | ||
115 | ]), | ||
116 | work_done_progress_options: Default::default(), | 152 | work_done_progress_options: Default::default(), |
117 | }) | 153 | }) |
118 | }) | 154 | }) |