@@ -3,8 +3,8 @@ use log::{debug, info, warn};
33use options:: { Options , Run , WorkspaceOption } ;
44use rustc_hash:: FxBuildHasher ;
55use 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 } ;
88use tower_lsp_server:: {
99 Client , LanguageServer , LspService , Server ,
1010 jsonrpc:: { Error , ErrorCode , Result } ,
@@ -42,7 +42,10 @@ struct Backend {
4242 // We must respect each program inside with its own root folder
4343 // and can not use shared programmes across multiple workspaces.
4444 // 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 > > > ,
4649 capabilities : OnceCell < Capabilities > ,
4750}
4851
@@ -115,7 +118,7 @@ impl LanguageServer for Backend {
115118 }
116119 }
117120
118- * self . workspace_workers . lock ( ) . await = workers;
121+ * self . workspace_workers . write ( ) . await = workers;
119122
120123 self . capabilities . set ( capabilities. clone ( ) ) . map_err ( |err| {
121124 let message = match err {
@@ -144,7 +147,7 @@ impl LanguageServer for Backend {
144147 return ;
145148 } ;
146149
147- let workers = & * self . workspace_workers . lock ( ) . await ;
150+ let workers = & * self . workspace_workers . read ( ) . await ;
148151 let needed_configurations =
149152 ConcurrentHashMap :: with_capacity_and_hasher ( workers. len ( ) , FxBuildHasher ) ;
150153 let needed_configurations = needed_configurations. pin_owned ( ) ;
@@ -200,7 +203,7 @@ impl LanguageServer for Backend {
200203 }
201204
202205 async fn did_change_configuration ( & self , params : DidChangeConfigurationParams ) {
203- let workers = self . workspace_workers . lock ( ) . await ;
206+ let workers = self . workspace_workers . read ( ) . await ;
204207 let new_diagnostics: papaya:: HashMap < String , Vec < Diagnostic > , FxBuildHasher > =
205208 ConcurrentHashMap :: default ( ) ;
206209 let mut removing_registrations = vec ! [ ] ;
@@ -340,7 +343,7 @@ impl LanguageServer for Backend {
340343 }
341344
342345 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 ;
344347 // ToDo: what if an empty changes flag is passed?
345348 debug ! ( "watched file did change" ) ;
346349 let all_diagnostics: papaya:: HashMap < String , Vec < Diagnostic > , FxBuildHasher > =
@@ -379,7 +382,7 @@ impl LanguageServer for Backend {
379382 }
380383
381384 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 ;
383386 let mut cleared_diagnostics = vec ! [ ] ;
384387 let mut added_registrations = vec ! [ ] ;
385388 let mut removed_registrations = vec ! [ ] ;
@@ -454,7 +457,7 @@ impl LanguageServer for Backend {
454457 async fn did_save ( & self , params : DidSaveTextDocumentParams ) {
455458 debug ! ( "oxc server did save" ) ;
456459 let uri = & params. text_document . uri ;
457- let workers = self . workspace_workers . lock ( ) . await ;
460+ let workers = self . workspace_workers . read ( ) . await ;
458461 let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
459462 return ;
460463 } ;
@@ -476,7 +479,7 @@ impl LanguageServer for Backend {
476479 /// get the file context from the language client
477480 async fn did_change ( & self , params : DidChangeTextDocumentParams ) {
478481 let uri = & params. text_document . uri ;
479- let workers = self . workspace_workers . lock ( ) . await ;
482+ let workers = self . workspace_workers . read ( ) . await ;
480483 let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
481484 return ;
482485 } ;
@@ -497,7 +500,7 @@ impl LanguageServer for Backend {
497500
498501 async fn did_open ( & self , params : DidOpenTextDocumentParams ) {
499502 let uri = & params. text_document . uri ;
500- let workers = self . workspace_workers . lock ( ) . await ;
503+ let workers = self . workspace_workers . read ( ) . await ;
501504 let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
502505 return ;
503506 } ;
@@ -516,7 +519,7 @@ impl LanguageServer for Backend {
516519
517520 async fn did_close ( & self , params : DidCloseTextDocumentParams ) {
518521 let uri = & params. text_document . uri ;
519- let workers = self . workspace_workers . lock ( ) . await ;
522+ let workers = self . workspace_workers . read ( ) . await ;
520523 let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
521524 return ;
522525 } ;
@@ -525,7 +528,7 @@ impl LanguageServer for Backend {
525528
526529 async fn code_action ( & self , params : CodeActionParams ) -> Result < Option < CodeActionResponse > > {
527530 let uri = & params. text_document . uri ;
528- let workers = self . workspace_workers . lock ( ) . await ;
531+ let workers = self . workspace_workers . read ( ) . await ;
529532 let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) ) else {
530533 return Ok ( None ) ;
531534 } ;
@@ -558,7 +561,7 @@ impl LanguageServer for Backend {
558561 FixAllCommandArgs :: try_from ( params. arguments ) . map_err ( Error :: invalid_params) ?;
559562
560563 let uri = & Uri :: from_str ( & args. uri ) . unwrap ( ) ;
561- let workers = self . workspace_workers . lock ( ) . await ;
564+ let workers = self . workspace_workers . read ( ) . await ;
562565 let Some ( worker) = workers. iter ( ) . find ( |worker| worker. is_responsible_for_uri ( uri) )
563566 else {
564567 return Ok ( None ) ;
@@ -618,7 +621,7 @@ impl Backend {
618621 // clears all diagnostics for workspace folders
619622 async fn clear_all_diagnostics ( & self ) {
620623 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 ( ) {
622625 cleared_diagnostics. extend ( worker. get_clear_diagnostics ( ) ) ;
623626 }
624627 self . publish_all_diagnostics ( & cleared_diagnostics) . await ;
@@ -641,7 +644,7 @@ async fn main() {
641644
642645 let ( service, socket) = LspService :: build ( |client| Backend {
643646 client,
644- workspace_workers : Mutex :: new ( vec ! [ ] ) ,
647+ workspace_workers : Arc :: new ( RwLock :: new ( vec ! [ ] ) ) ,
645648 capabilities : OnceCell :: new ( ) ,
646649 } )
647650 . finish ( ) ;
0 commit comments