11use tower_lsp_server:: lsp_types:: {
22 ClientCapabilities , CodeActionKind , CodeActionOptions , CodeActionProviderCapability ,
3- ExecuteCommandOptions , OneOf , SaveOptions , ServerCapabilities , TextDocumentSyncCapability ,
4- TextDocumentSyncKind , TextDocumentSyncOptions , TextDocumentSyncSaveOptions ,
5- WorkDoneProgressOptions , WorkspaceFoldersServerCapabilities , WorkspaceServerCapabilities ,
3+ DiagnosticOptions , DiagnosticServerCapabilities , ExecuteCommandOptions , OneOf , SaveOptions ,
4+ ServerCapabilities , TextDocumentSyncCapability , TextDocumentSyncKind , TextDocumentSyncOptions ,
5+ TextDocumentSyncSaveOptions , WorkDoneProgressOptions , WorkspaceFoldersServerCapabilities ,
6+ WorkspaceServerCapabilities ,
67} ;
78
89use crate :: { code_actions:: CODE_ACTION_KIND_SOURCE_FIX_ALL_OXC , commands:: FIX_ALL_COMMAND_ID } ;
910
10- #[ derive( Clone , Default ) ]
11+ /// Represents the capabilities of the client that the server can use to determine
12+ /// which features to enable or disable.
13+ #[ derive( Clone , Default , Debug ) ]
1114pub struct Capabilities {
1215 pub code_action_provider : bool ,
1316 pub workspace_apply_edit : bool ,
1417 pub workspace_execute_command : bool ,
1518 pub workspace_configuration : bool ,
19+ /// Whether the client supports dynamic registration of file watchers.
1620 pub dynamic_watchers : bool ,
21+ /// Whether the client supports pull diagnostics.
22+ pull_diagnostics : bool ,
23+ /// Whether the client supports the `workspace/diagnostic/refresh` request.
24+ refresh_diagnostics : bool ,
1725}
1826
19- impl From < ClientCapabilities > for Capabilities {
20- fn from ( value : ClientCapabilities ) -> Self {
27+ impl Capabilities {
28+ /// The server supports pull and push diagnostics.
29+ /// Only use push diagnostics if the client does not support pull diagnostics,
30+ /// or we can not the client to refresh diagnostics.
31+ pub fn use_push_diagnostics ( & self ) -> bool {
32+ !self . pull_diagnostics || !self . refresh_diagnostics
33+ }
34+ }
35+
36+ impl From < & ClientCapabilities > for Capabilities {
37+ fn from ( value : & ClientCapabilities ) -> Self {
2138 // check if the client support some code action literal support
2239 let code_action_provider = value. text_document . as_ref ( ) . is_some_and ( |capability| {
2340 capability. code_action . as_ref ( ) . is_some_and ( |code_action| {
@@ -34,18 +51,33 @@ impl From<ClientCapabilities> for Capabilities {
3451 . workspace
3552 . as_ref ( )
3653 . is_some_and ( |workspace| workspace. configuration . is_some_and ( |config| config) ) ;
37- let dynamic_watchers = value. workspace . is_some_and ( |workspace| {
38- workspace. did_change_watched_files . is_some_and ( |watched_files| {
39- watched_files. dynamic_registration . is_some_and ( |dynamic| dynamic)
54+ let dynamic_watchers = value. workspace . as_ref ( ) . is_some_and ( |workspace| {
55+ workspace. did_change_watched_files . as_ref ( ) . is_some_and ( |watched_files| {
56+ watched_files. dynamic_registration . as_ref ( ) . is_some_and ( |dynamic| * dynamic)
4057 } )
4158 } ) ;
4259
60+ let pull_diagnostics = value
61+ . text_document
62+ . as_ref ( )
63+ . is_some_and ( |text_document| text_document. diagnostic . is_some ( ) ) ;
64+
65+ // BUG: see https://github.com/tower-lsp-community/tower-lsp-server/issues/50
66+ // let refresh_diagnostics = value.workspace.as_ref().is_some_and(|workspace| {
67+ // workspace
68+ // .diagnostic
69+ // .as_ref()
70+ // .is_some_and(|diagnostic| diagnostic.refresh_support.is_some_and(|refresh| refresh))
71+ // });
72+
4373 Self {
4474 code_action_provider,
4575 workspace_apply_edit,
4676 workspace_execute_command,
4777 workspace_configuration,
4878 dynamic_watchers,
79+ pull_diagnostics,
80+ refresh_diagnostics : true ,
4981 }
5082 }
5183}
@@ -92,6 +124,11 @@ impl From<Capabilities> for ServerCapabilities {
92124 } else {
93125 None
94126 } ,
127+ diagnostic_provider : if value. use_push_diagnostics ( ) {
128+ None
129+ } else {
130+ Some ( DiagnosticServerCapabilities :: Options ( DiagnosticOptions :: default ( ) ) )
131+ } ,
95132 ..ServerCapabilities :: default ( )
96133 }
97134 }
@@ -108,6 +145,37 @@ mod test {
108145
109146 use super :: Capabilities ;
110147
148+ #[ test]
149+ fn test_use_push_diagnostics ( ) {
150+ let capabilities = Capabilities {
151+ pull_diagnostics : true ,
152+ refresh_diagnostics : true ,
153+ ..Default :: default ( )
154+ } ;
155+ assert ! ( !capabilities. use_push_diagnostics( ) ) ;
156+
157+ let capabilities = Capabilities {
158+ pull_diagnostics : false ,
159+ refresh_diagnostics : true ,
160+ ..Default :: default ( )
161+ } ;
162+ assert ! ( capabilities. use_push_diagnostics( ) ) ;
163+
164+ let capabilities = Capabilities {
165+ pull_diagnostics : true ,
166+ refresh_diagnostics : false ,
167+ ..Default :: default ( )
168+ } ;
169+ assert ! ( capabilities. use_push_diagnostics( ) ) ;
170+
171+ let capabilities = Capabilities {
172+ pull_diagnostics : false ,
173+ refresh_diagnostics : false ,
174+ ..Default :: default ( )
175+ } ;
176+ assert ! ( capabilities. use_push_diagnostics( ) ) ;
177+ }
178+
111179 #[ test]
112180 fn test_code_action_provider_vscode ( ) {
113181 let client_capabilities = ClientCapabilities {
@@ -138,7 +206,7 @@ mod test {
138206 ..ClientCapabilities :: default ( )
139207 } ;
140208
141- let capabilities = Capabilities :: from ( client_capabilities) ;
209+ let capabilities = Capabilities :: from ( & client_capabilities) ;
142210
143211 assert ! ( capabilities. code_action_provider) ;
144212 }
@@ -168,7 +236,7 @@ mod test {
168236 ..ClientCapabilities :: default ( )
169237 } ;
170238
171- let capabilities = Capabilities :: from ( client_capabilities) ;
239+ let capabilities = Capabilities :: from ( & client_capabilities) ;
172240
173241 assert ! ( capabilities. code_action_provider) ;
174242 }
@@ -201,7 +269,7 @@ mod test {
201269 ..ClientCapabilities :: default ( )
202270 } ;
203271
204- let capabilities = Capabilities :: from ( client_capabilities) ;
272+ let capabilities = Capabilities :: from ( & client_capabilities) ;
205273
206274 assert ! ( capabilities. code_action_provider) ;
207275 }
@@ -219,7 +287,7 @@ mod test {
219287 ..ClientCapabilities :: default ( )
220288 } ;
221289
222- let capabilities = Capabilities :: from ( client_capabilities) ;
290+ let capabilities = Capabilities :: from ( & client_capabilities) ;
223291
224292 assert ! ( capabilities. workspace_execute_command) ;
225293 }
@@ -235,7 +303,7 @@ mod test {
235303 ..ClientCapabilities :: default ( )
236304 } ;
237305
238- let capabilities = Capabilities :: from ( client_capabilities) ;
306+ let capabilities = Capabilities :: from ( & client_capabilities) ;
239307
240308 assert ! ( capabilities. workspace_apply_edit) ;
241309 }
@@ -253,7 +321,7 @@ mod test {
253321 ..Default :: default ( )
254322 } ;
255323
256- let capabilities = Capabilities :: from ( client_capabilities) ;
324+ let capabilities = Capabilities :: from ( & client_capabilities) ;
257325 assert ! ( capabilities. dynamic_watchers) ;
258326 }
259327
@@ -270,7 +338,7 @@ mod test {
270338 ..Default :: default ( )
271339 } ;
272340
273- let capabilities = Capabilities :: from ( client_capabilities) ;
341+ let capabilities = Capabilities :: from ( & client_capabilities) ;
274342 assert ! ( capabilities. dynamic_watchers) ;
275343 }
276344}
0 commit comments