11use tower_lsp_server:: lsp_types:: {
2- ClientCapabilities , CodeActionKind , CodeActionOptions , CodeActionProviderCapability ,
3- ExecuteCommandOptions , OneOf , SaveOptions , ServerCapabilities , TextDocumentSyncCapability ,
2+ ClientCapabilities , OneOf , SaveOptions , ServerCapabilities , TextDocumentSyncCapability ,
43 TextDocumentSyncKind , TextDocumentSyncOptions , TextDocumentSyncSaveOptions ,
5- WorkDoneProgressOptions , WorkspaceFoldersServerCapabilities , WorkspaceServerCapabilities ,
4+ WorkspaceFoldersServerCapabilities , WorkspaceServerCapabilities ,
65} ;
76
8- use crate :: ToolBuilder ;
9-
107#[ derive( Clone , Default ) ]
118pub struct Capabilities {
12- pub code_action_provider : bool ,
139 pub workspace_apply_edit : bool ,
14- pub workspace_execute_command : bool ,
1510 pub workspace_configuration : bool ,
1611 pub dynamic_watchers : bool ,
1712 pub dynamic_formatting : bool ,
1813}
1914
2015impl From < ClientCapabilities > for Capabilities {
2116 fn from ( value : ClientCapabilities ) -> Self {
22- // check if the client support some code action literal support
23- let code_action_provider = value. text_document . as_ref ( ) . is_some_and ( |capability| {
24- capability. code_action . as_ref ( ) . is_some_and ( |code_action| {
25- code_action. code_action_literal_support . as_ref ( ) . is_some_and ( |literal_support| {
26- !literal_support. code_action_kind . value_set . is_empty ( )
27- } )
28- } )
29- } ) ;
3017 let workspace_apply_edit =
3118 value. workspace . as_ref ( ) . is_some_and ( |workspace| workspace. apply_edit . is_some ( ) ) ;
32- let workspace_execute_command =
33- value. workspace . as_ref ( ) . is_some_and ( |workspace| workspace. execute_command . is_some ( ) ) ;
3419 let workspace_configuration = value
3520 . workspace
3621 . as_ref ( )
@@ -46,193 +31,39 @@ impl From<ClientCapabilities> for Capabilities {
4631 } )
4732 } ) ;
4833
49- Self {
50- code_action_provider,
51- workspace_apply_edit,
52- workspace_execute_command,
53- workspace_configuration,
54- dynamic_watchers,
55- dynamic_formatting,
56- }
34+ Self { workspace_apply_edit, workspace_configuration, dynamic_watchers, dynamic_formatting }
5735 }
5836}
5937
60- impl Capabilities {
61- pub fn server_capabilities ( & self , tools : & [ Box < dyn ToolBuilder > ] ) -> ServerCapabilities {
62- let code_action_kinds: Vec < CodeActionKind > =
63- tools. iter ( ) . flat_map ( |tool| tool. provided_code_action_kinds ( ) ) . collect ( ) ;
64-
65- let commands: Vec < String > =
66- tools. iter ( ) . flat_map ( |tool| tool. provided_commands ( ) ) . collect ( ) ;
67-
68- ServerCapabilities {
69- text_document_sync : Some ( TextDocumentSyncCapability :: Options (
70- TextDocumentSyncOptions {
71- change : Some ( TextDocumentSyncKind :: FULL ) ,
72- open_close : Some ( true ) ,
73- save : Some ( TextDocumentSyncSaveOptions :: SaveOptions ( SaveOptions {
74- include_text : Some ( false ) ,
75- } ) ) ,
76- ..Default :: default ( )
77- } ,
78- ) ) ,
79- workspace : Some ( WorkspaceServerCapabilities {
80- workspace_folders : Some ( WorkspaceFoldersServerCapabilities {
81- supported : Some ( true ) ,
82- change_notifications : Some ( OneOf :: Left ( true ) ) ,
83- } ) ,
84- file_operations : None ,
38+ pub fn server_capabilities ( ) -> ServerCapabilities {
39+ ServerCapabilities {
40+ text_document_sync : Some ( TextDocumentSyncCapability :: Options ( TextDocumentSyncOptions {
41+ change : Some ( TextDocumentSyncKind :: FULL ) ,
42+ open_close : Some ( true ) ,
43+ save : Some ( TextDocumentSyncSaveOptions :: SaveOptions ( SaveOptions {
44+ include_text : Some ( false ) ,
45+ } ) ) ,
46+ ..Default :: default ( )
47+ } ) ) ,
48+ workspace : Some ( WorkspaceServerCapabilities {
49+ workspace_folders : Some ( WorkspaceFoldersServerCapabilities {
50+ supported : Some ( true ) ,
51+ change_notifications : Some ( OneOf :: Left ( true ) ) ,
8552 } ) ,
86- code_action_provider : if self . code_action_provider && !code_action_kinds. is_empty ( ) {
87- Some ( CodeActionProviderCapability :: Options ( CodeActionOptions {
88- code_action_kinds : Some ( code_action_kinds) ,
89- work_done_progress_options : WorkDoneProgressOptions {
90- work_done_progress : None ,
91- } ,
92- resolve_provider : None ,
93- } ) )
94- } else {
95- None
96- } ,
97- execute_command_provider : if self . workspace_execute_command && !commands. is_empty ( ) {
98- Some ( ExecuteCommandOptions { commands, ..Default :: default ( ) } )
99- } else {
100- None
101- } ,
102- // the server supports formatting, but it will tell the client if he enabled the setting
103- document_formatting_provider : None ,
104- ..ServerCapabilities :: default ( )
105- }
53+ file_operations : None ,
54+ } ) ,
55+ ..ServerCapabilities :: default ( )
10656 }
10757}
10858
10959#[ cfg( test) ]
11060mod test {
11161 use tower_lsp_server:: lsp_types:: {
112- ClientCapabilities , CodeActionClientCapabilities , CodeActionKindLiteralSupport ,
113- CodeActionLiteralSupport , DidChangeWatchedFilesClientCapabilities ,
114- DynamicRegistrationClientCapabilities , TextDocumentClientCapabilities ,
115- WorkspaceClientCapabilities ,
62+ ClientCapabilities , DidChangeWatchedFilesClientCapabilities , WorkspaceClientCapabilities ,
11663 } ;
11764
11865 use super :: Capabilities ;
11966
120- #[ test]
121- fn test_code_action_provider_vscode ( ) {
122- let client_capabilities = ClientCapabilities {
123- text_document : Some ( TextDocumentClientCapabilities {
124- code_action : Some ( CodeActionClientCapabilities {
125- code_action_literal_support : Some ( CodeActionLiteralSupport {
126- code_action_kind : CodeActionKindLiteralSupport {
127- // this is from build (see help, about):
128- // Version: 1.95.3 (user setup)
129- // Commit: f1a4fb101478ce6ec82fe9627c43efbf9e98c813
130- value_set : vec ! [
131- #[ expect( clippy:: manual_string_new) ]
132- "" . into( ) ,
133- "quickfix" . into( ) ,
134- "refactor" . into( ) ,
135- "refactor.extract" . into( ) ,
136- "refactor.inline" . into( ) ,
137- "refactor.rewrite" . into( ) ,
138- "source" . into( ) ,
139- "source.organizeImports" . into( ) ,
140- ] ,
141- } ,
142- } ) ,
143- ..CodeActionClientCapabilities :: default ( )
144- } ) ,
145- ..TextDocumentClientCapabilities :: default ( )
146- } ) ,
147- ..ClientCapabilities :: default ( )
148- } ;
149-
150- let capabilities = Capabilities :: from ( client_capabilities) ;
151-
152- assert ! ( capabilities. code_action_provider) ;
153- }
154-
155- #[ test]
156- fn test_code_action_provider_intellij ( ) {
157- let client_capabilities = ClientCapabilities {
158- text_document : Some ( TextDocumentClientCapabilities {
159- code_action : Some ( CodeActionClientCapabilities {
160- code_action_literal_support : Some ( CodeActionLiteralSupport {
161- code_action_kind : CodeActionKindLiteralSupport {
162- // this is from build (see help, about):
163- // Build #IU-243.22562.145, built on December 8, 2024
164- value_set : vec ! [
165- "quickfix" . into( ) ,
166- #[ expect( clippy:: manual_string_new) ]
167- "" . into( ) ,
168- "source" . into( ) ,
169- "refactor" . into( ) ,
170- ] ,
171- } ,
172- } ) ,
173- ..CodeActionClientCapabilities :: default ( )
174- } ) ,
175- ..TextDocumentClientCapabilities :: default ( )
176- } ) ,
177- ..ClientCapabilities :: default ( )
178- } ;
179-
180- let capabilities = Capabilities :: from ( client_capabilities) ;
181-
182- assert ! ( capabilities. code_action_provider) ;
183- }
184-
185- #[ test]
186- fn test_code_action_provider_nvim ( ) {
187- let client_capabilities = ClientCapabilities {
188- text_document : Some ( TextDocumentClientCapabilities {
189- code_action : Some ( CodeActionClientCapabilities {
190- code_action_literal_support : Some ( CodeActionLiteralSupport {
191- code_action_kind : CodeActionKindLiteralSupport {
192- // nvim 0.10.3
193- value_set : vec ! [
194- #[ expect( clippy:: manual_string_new) ]
195- "" . into( ) ,
196- "quickfix" . into( ) ,
197- "refactor" . into( ) ,
198- "refactor.extract" . into( ) ,
199- "refactor.inline" . into( ) ,
200- "refactor.rewrite" . into( ) ,
201- "source" . into( ) ,
202- "source.organizeImports" . into( ) ,
203- ] ,
204- } ,
205- } ) ,
206- ..CodeActionClientCapabilities :: default ( )
207- } ) ,
208- ..TextDocumentClientCapabilities :: default ( )
209- } ) ,
210- ..ClientCapabilities :: default ( )
211- } ;
212-
213- let capabilities = Capabilities :: from ( client_capabilities) ;
214-
215- assert ! ( capabilities. code_action_provider) ;
216- }
217-
218- // This tests code, intellij and neovim (at least nvim 0.10.0+), as they all support dynamic registration.
219- #[ test]
220- fn test_workspace_execute_command ( ) {
221- let client_capabilities = ClientCapabilities {
222- workspace : Some ( WorkspaceClientCapabilities {
223- execute_command : Some ( DynamicRegistrationClientCapabilities {
224- dynamic_registration : Some ( true ) ,
225- } ) ,
226- ..WorkspaceClientCapabilities :: default ( )
227- } ) ,
228- ..ClientCapabilities :: default ( )
229- } ;
230-
231- let capabilities = Capabilities :: from ( client_capabilities) ;
232-
233- assert ! ( capabilities. workspace_execute_command) ;
234- }
235-
23667 #[ test]
23768 fn test_workspace_edit_nvim ( ) {
23869 let client_capabilities = ClientCapabilities {
0 commit comments