@@ -114,19 +114,19 @@ impl LanguageServer for Backend {
114
114
// we will init the linter after requesting for the workspace configuration.
115
115
if !capabilities. workspace_configuration || options. is_some ( ) {
116
116
for worker in & workers {
117
- worker
118
- . init_linter (
119
- & options
120
- . clone ( )
121
- . unwrap_or_default ( )
122
- . iter ( )
123
- . find ( |workspace_option| {
124
- worker . is_responsible_for_uri ( & workspace_option . workspace_uri )
125
- } )
126
- . map ( |workspace_options| workspace_options . options . clone ( ) )
127
- . unwrap_or_default ( ) ,
128
- )
129
- . await ;
117
+ let option = & options
118
+ . clone ( )
119
+ . unwrap_or_default ( )
120
+ . iter ( )
121
+ . find ( |workspace_option| {
122
+ worker . is_responsible_for_uri ( & workspace_option . workspace_uri )
123
+ } )
124
+ . map ( |workspace_options| workspace_options . options . clone ( ) )
125
+ . unwrap_or_default ( ) ;
126
+
127
+ worker . init_options ( option ) . await ;
128
+ worker . init_linter ( & option . lint ) . await ;
129
+ worker . init_formatter ( & option . format ) . await ;
130
130
}
131
131
}
132
132
@@ -164,11 +164,9 @@ impl LanguageServer for Backend {
164
164
ConcurrentHashMap :: with_capacity_and_hasher ( workers. len ( ) , FxBuildHasher ) ;
165
165
let needed_configurations = needed_configurations. pin_owned ( ) ;
166
166
for worker in workers {
167
- if worker. needs_init_linter ( ) . await {
167
+ if worker. needs_init_linter ( ) . await || worker . needs_init_formatter ( ) . await {
168
168
needed_configurations. insert ( worker. get_root_uri ( ) . clone ( ) , worker) ;
169
169
}
170
- // ToDo: check for configuration
171
- worker. init_formatter ( ) . await ;
172
170
}
173
171
174
172
if !needed_configurations. is_empty ( ) {
@@ -178,23 +176,22 @@ impl LanguageServer for Backend {
178
176
// every worker should be initialized already in `initialize` request
179
177
vec ! [ Some ( Options :: default ( ) ) ; needed_configurations. len( ) ]
180
178
} ;
179
+ let default_options = Options :: default ( ) ;
181
180
182
181
for ( index, worker) in needed_configurations. values ( ) . enumerate ( ) {
183
- worker
184
- . init_linter (
185
- configurations
186
- . get ( index)
187
- . unwrap_or ( & None )
188
- . as_ref ( )
189
- . unwrap_or ( & Options :: default ( ) ) ,
190
- )
191
- . await ;
182
+ let configuration =
183
+ configurations. get ( index) . unwrap_or ( & None ) . as_ref ( ) . unwrap_or ( & default_options) ;
184
+
185
+ worker. init_options ( configuration) . await ;
186
+ worker. init_linter ( & configuration. lint ) . await ;
187
+ worker. init_formatter ( & configuration. format ) . await ;
192
188
}
193
189
}
194
190
191
+ let mut registrations = vec ! [ ] ;
192
+
195
193
// init all file watchers
196
194
if capabilities. dynamic_watchers {
197
- let mut registrations = vec ! [ ] ;
198
195
for worker in workers {
199
196
registrations. push ( Registration {
200
197
id : format ! ( "watcher-{}" , worker. get_root_uri( ) . as_str( ) ) ,
@@ -204,11 +201,33 @@ impl LanguageServer for Backend {
204
201
} ) ) ,
205
202
} ) ;
206
203
}
204
+ }
207
205
208
- if let Err ( err) = self . client . register_capability ( registrations) . await {
209
- warn ! ( "sending registerCapability.didChangeWatchedFiles failed: {err}" ) ;
206
+ if capabilities. dynamic_formatting {
207
+ // check if one workspace has formatting enabled
208
+ let mut started_worker = false ;
209
+ for worker in workers {
210
+ if !worker. needs_init_formatter ( ) . await {
211
+ started_worker = true ;
212
+ break ;
213
+ }
214
+ }
215
+
216
+ if started_worker {
217
+ registrations. push ( Registration {
218
+ id : "dynamic-formatting" . to_string ( ) ,
219
+ method : "textDocument/formatting" . to_string ( ) ,
220
+ register_options : None ,
221
+ } ) ;
210
222
}
211
223
}
224
+
225
+ if registrations. is_empty ( ) {
226
+ return ;
227
+ }
228
+ if let Err ( err) = self . client . register_capability ( registrations) . await {
229
+ warn ! ( "sending registerCapability.didChangeWatchedFiles failed: {err}" ) ;
230
+ }
212
231
}
213
232
214
233
async fn shutdown ( & self ) -> Result < ( ) > {
@@ -279,14 +298,26 @@ impl LanguageServer for Backend {
279
298
return ;
280
299
} ;
281
300
301
+ let mut global_formatting_added = false ;
302
+ let mut global_formatting_removed = false ;
303
+
282
304
for option in resolved_options {
283
305
let Some ( worker) =
284
306
workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( & option. workspace_uri ) )
285
307
else {
286
308
continue ;
287
309
} ;
288
310
289
- let ( diagnostics, watcher) = worker. did_change_configuration ( & option. options ) . await ;
311
+ let ( diagnostics, watcher, formatting) =
312
+ worker. did_change_configuration ( & option. options ) . await ;
313
+
314
+ if self . capabilities . get ( ) . is_some_and ( |c| c. dynamic_formatting ) {
315
+ if Some ( true ) == formatting {
316
+ global_formatting_added = true ;
317
+ } else if Some ( false ) == formatting {
318
+ global_formatting_removed = true ;
319
+ }
320
+ }
290
321
291
322
if let Some ( diagnostics) = diagnostics {
292
323
for ( uri, reports) in & diagnostics. pin ( ) {
@@ -297,7 +328,9 @@ impl LanguageServer for Backend {
297
328
}
298
329
}
299
330
300
- if let Some ( watcher) = watcher {
331
+ if let Some ( watcher) = watcher
332
+ && self . capabilities . get ( ) . is_some_and ( |capabilities| capabilities. dynamic_watchers )
333
+ {
301
334
// remove the old watcher
302
335
removing_registrations. push ( Unregistration {
303
336
id : format ! ( "watcher-{}" , worker. get_root_uri( ) . as_str( ) ) ,
@@ -324,16 +357,27 @@ impl LanguageServer for Backend {
324
357
self . publish_all_diagnostics ( x) . await ;
325
358
}
326
359
327
- if self . capabilities . get ( ) . is_some_and ( |capabilities| capabilities. dynamic_watchers ) {
328
- if !removing_registrations. is_empty ( ) {
329
- if let Err ( err) = self . client . unregister_capability ( removing_registrations) . await {
330
- warn ! ( "sending unregisterCapability.didChangeWatchedFiles failed: {err}" ) ;
331
- }
360
+ if global_formatting_added {
361
+ adding_registrations. push ( Registration {
362
+ id : "dynamic-formatting" . to_string ( ) ,
363
+ method : "textDocument/formatting" . to_string ( ) ,
364
+ register_options : None ,
365
+ } ) ;
366
+ } else if global_formatting_removed {
367
+ removing_registrations. push ( Unregistration {
368
+ id : "dynamic-formatting" . to_string ( ) ,
369
+ method : "textDocument/formatting" . to_string ( ) ,
370
+ } ) ;
371
+ }
372
+
373
+ if !removing_registrations. is_empty ( ) {
374
+ if let Err ( err) = self . client . unregister_capability ( removing_registrations) . await {
375
+ warn ! ( "sending unregisterCapability.didChangeWatchedFiles failed: {err}" ) ;
332
376
}
333
- if !adding_registrations . is_empty ( ) {
334
- if let Err ( err ) = self . client . register_capability ( adding_registrations ) . await {
335
- warn ! ( "sending registerCapability.didChangeWatchedFiles failed: {err}" ) ;
336
- }
377
+ }
378
+ if !adding_registrations . is_empty ( ) {
379
+ if let Err ( err ) = self . client . register_capability ( adding_registrations ) . await {
380
+ warn ! ( "sending registerCapability.didChangeWatchedFiles failed: {err}" ) ;
337
381
}
338
382
}
339
383
}
@@ -401,6 +445,8 @@ impl LanguageServer for Backend {
401
445
402
446
self . publish_all_diagnostics ( & cleared_diagnostics) . await ;
403
447
448
+ let default_options = Options :: default ( ) ;
449
+
404
450
// client support `workspace/configuration` request
405
451
if self . capabilities . get ( ) . is_some_and ( |capabilities| capabilities. workspace_configuration )
406
452
{
@@ -414,7 +460,12 @@ impl LanguageServer for Backend {
414
460
let worker = WorkspaceWorker :: new ( folder. uri . clone ( ) ) ;
415
461
// get the configuration from the response and init the linter
416
462
let options = configurations. get ( index) . unwrap_or ( & None ) ;
417
- worker. init_linter ( options. as_ref ( ) . unwrap_or ( & Options :: default ( ) ) ) . await ;
463
+ let options = options. as_ref ( ) . unwrap_or ( & default_options) ;
464
+
465
+ worker. init_options ( options) . await ;
466
+ worker. init_linter ( & options. lint ) . await ;
467
+ worker. init_formatter ( & options. format ) . await ;
468
+
418
469
added_registrations. push ( Registration {
419
470
id : format ! ( "watcher-{}" , worker. get_root_uri( ) . as_str( ) ) ,
420
471
method : "workspace/didChangeWatchedFiles" . to_string ( ) ,
@@ -429,7 +480,9 @@ impl LanguageServer for Backend {
429
480
for folder in params. event . added {
430
481
let worker = WorkspaceWorker :: new ( folder. uri ) ;
431
482
// use default options
432
- worker. init_linter ( & Options :: default ( ) ) . await ;
483
+ worker. init_options ( & default_options) . await ;
484
+ worker. init_linter ( & default_options. lint ) . await ;
485
+ worker. init_formatter ( & default_options. format ) . await ;
433
486
workers. push ( worker) ;
434
487
}
435
488
}
@@ -603,7 +656,7 @@ impl LanguageServer for Backend {
603
656
let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
604
657
return Ok ( None ) ;
605
658
} ;
606
- Ok ( worker. format_file ( uri) . await )
659
+ Ok ( worker. format_file ( uri, self . file_system . read ( ) . await . get ( uri ) ) . await )
607
660
}
608
661
}
609
662
0 commit comments