@@ -3,8 +3,8 @@ use log::{debug, info, warn};
3
3
use options:: { Options , Run , WorkspaceOption } ;
4
4
use rustc_hash:: FxBuildHasher ;
5
5
use serde_json:: json;
6
- use std:: str:: FromStr ;
7
- use tokio:: sync:: { Mutex , OnceCell , SetError } ;
6
+ use std:: { str:: FromStr , sync :: Arc } ;
7
+ use tokio:: sync:: { OnceCell , RwLock , SetError } ;
8
8
use tower_lsp_server:: {
9
9
Client , LanguageServer , LspService , Server ,
10
10
jsonrpc:: { Error , ErrorCode , Result } ,
@@ -42,7 +42,10 @@ struct Backend {
42
42
// We must respect each program inside with its own root folder
43
43
// and can not use shared programmes across multiple workspaces.
44
44
// Each Workspace can have its own server configuration and program root configuration.
45
- workspace_workers : Mutex < Vec < WorkspaceWorker > > ,
45
+ // WorkspaceWorkers are only written on 2 occasions:
46
+ // 1. `initialize` request with workspace folders
47
+ // 2. `workspace/didChangeWorkspaceFolders` request
48
+ workspace_workers : Arc < RwLock < Vec < WorkspaceWorker > > > ,
46
49
capabilities : OnceCell < Capabilities > ,
47
50
}
48
51
@@ -115,7 +118,7 @@ impl LanguageServer for Backend {
115
118
}
116
119
}
117
120
118
- * self . workspace_workers . lock ( ) . await = workers;
121
+ * self . workspace_workers . write ( ) . await = workers;
119
122
120
123
self . capabilities . set ( capabilities. clone ( ) ) . map_err ( |err| {
121
124
let message = match err {
@@ -144,7 +147,7 @@ impl LanguageServer for Backend {
144
147
return ;
145
148
} ;
146
149
147
- let workers = & * self . workspace_workers . lock ( ) . await ;
150
+ let workers = & * self . workspace_workers . read ( ) . await ;
148
151
let needed_configurations =
149
152
ConcurrentHashMap :: with_capacity_and_hasher ( workers. len ( ) , FxBuildHasher ) ;
150
153
let needed_configurations = needed_configurations. pin_owned ( ) ;
@@ -200,7 +203,7 @@ impl LanguageServer for Backend {
200
203
}
201
204
202
205
async fn did_change_configuration ( & self , params : DidChangeConfigurationParams ) {
203
- let workers = self . workspace_workers . lock ( ) . await ;
206
+ let workers = self . workspace_workers . read ( ) . await ;
204
207
let new_diagnostics: papaya:: HashMap < String , Vec < Diagnostic > , FxBuildHasher > =
205
208
ConcurrentHashMap :: default ( ) ;
206
209
let mut removing_registrations = vec ! [ ] ;
@@ -340,7 +343,7 @@ impl LanguageServer for Backend {
340
343
}
341
344
342
345
async fn did_change_watched_files ( & self , params : DidChangeWatchedFilesParams ) {
343
- let workers = self . workspace_workers . lock ( ) . await ;
346
+ let workers = self . workspace_workers . read ( ) . await ;
344
347
// ToDo: what if an empty changes flag is passed?
345
348
debug ! ( "watched file did change" ) ;
346
349
let all_diagnostics: papaya:: HashMap < String , Vec < Diagnostic > , FxBuildHasher > =
@@ -379,7 +382,7 @@ impl LanguageServer for Backend {
379
382
}
380
383
381
384
async fn did_change_workspace_folders ( & self , params : DidChangeWorkspaceFoldersParams ) {
382
- let mut workers = self . workspace_workers . lock ( ) . await ;
385
+ let mut workers = self . workspace_workers . write ( ) . await ;
383
386
let mut cleared_diagnostics = vec ! [ ] ;
384
387
let mut added_registrations = vec ! [ ] ;
385
388
let mut removed_registrations = vec ! [ ] ;
@@ -454,7 +457,7 @@ impl LanguageServer for Backend {
454
457
async fn did_save ( & self , params : DidSaveTextDocumentParams ) {
455
458
debug ! ( "oxc server did save" ) ;
456
459
let uri = & params. text_document . uri ;
457
- let workers = self . workspace_workers . lock ( ) . await ;
460
+ let workers = self . workspace_workers . read ( ) . await ;
458
461
let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
459
462
return ;
460
463
} ;
@@ -476,7 +479,7 @@ impl LanguageServer for Backend {
476
479
/// get the file context from the language client
477
480
async fn did_change ( & self , params : DidChangeTextDocumentParams ) {
478
481
let uri = & params. text_document . uri ;
479
- let workers = self . workspace_workers . lock ( ) . await ;
482
+ let workers = self . workspace_workers . read ( ) . await ;
480
483
let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
481
484
return ;
482
485
} ;
@@ -497,7 +500,7 @@ impl LanguageServer for Backend {
497
500
498
501
async fn did_open ( & self , params : DidOpenTextDocumentParams ) {
499
502
let uri = & params. text_document . uri ;
500
- let workers = self . workspace_workers . lock ( ) . await ;
503
+ let workers = self . workspace_workers . read ( ) . await ;
501
504
let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
502
505
return ;
503
506
} ;
@@ -516,7 +519,7 @@ impl LanguageServer for Backend {
516
519
517
520
async fn did_close ( & self , params : DidCloseTextDocumentParams ) {
518
521
let uri = & params. text_document . uri ;
519
- let workers = self . workspace_workers . lock ( ) . await ;
522
+ let workers = self . workspace_workers . read ( ) . await ;
520
523
let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
521
524
return ;
522
525
} ;
@@ -525,7 +528,7 @@ impl LanguageServer for Backend {
525
528
526
529
async fn code_action ( & self , params : CodeActionParams ) -> Result < Option < CodeActionResponse > > {
527
530
let uri = & params. text_document . uri ;
528
- let workers = self . workspace_workers . lock ( ) . await ;
531
+ let workers = self . workspace_workers . read ( ) . await ;
529
532
let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
530
533
return Ok ( None ) ;
531
534
} ;
@@ -558,7 +561,7 @@ impl LanguageServer for Backend {
558
561
FixAllCommandArgs :: try_from ( params. arguments ) . map_err ( Error :: invalid_params) ?;
559
562
560
563
let uri = & Uri :: from_str ( & args. uri ) . unwrap ( ) ;
561
- let workers = self . workspace_workers . lock ( ) . await ;
564
+ let workers = self . workspace_workers . read ( ) . await ;
562
565
let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) )
563
566
else {
564
567
return Ok ( None ) ;
@@ -618,7 +621,7 @@ impl Backend {
618
621
// clears all diagnostics for workspace folders
619
622
async fn clear_all_diagnostics ( & self ) {
620
623
let mut cleared_diagnostics = vec ! [ ] ;
621
- for worker in self . workspace_workers . lock ( ) . await . iter ( ) {
624
+ for worker in self . workspace_workers . read ( ) . await . iter ( ) {
622
625
cleared_diagnostics. extend ( worker. get_clear_diagnostics ( ) ) ;
623
626
}
624
627
self . publish_all_diagnostics ( & cleared_diagnostics) . await ;
@@ -641,7 +644,7 @@ async fn main() {
641
644
642
645
let ( service, socket) = LspService :: build ( |client| Backend {
643
646
client,
644
- workspace_workers : Mutex :: new ( vec ! [ ] ) ,
647
+ workspace_workers : Arc :: new ( RwLock :: new ( vec ! [ ] ) ) ,
645
648
capabilities : OnceCell :: new ( ) ,
646
649
} )
647
650
. finish ( ) ;
0 commit comments