11use std:: collections:: VecDeque ;
22
3- use serde_json:: json;
3+ use serde_json:: { Value , json} ;
44use tokio:: io:: { AsyncReadExt , AsyncWriteExt , DuplexStream } ;
55use tower_lsp_server:: {
6- Client , LanguageServer , LspService , Server ,
6+ Client , LspService , Server ,
77 jsonrpc:: { ErrorCode , Id , Request , Response } ,
88 lsp_types:: * ,
99} ;
1010
11- use crate :: { Tool , ToolBuilder , ToolRestartChanges } ;
11+ use crate :: { Tool , ToolBuilder , ToolRestartChanges , backend :: Backend } ;
1212
1313pub struct FakeToolBuilder ;
1414
@@ -159,15 +159,27 @@ struct TestServer {
159159}
160160
161161impl TestServer {
162- fn new < F , S > ( init : F ) -> Self
162+ fn new < F > ( init : F ) -> Self
163163 where
164- F : FnOnce ( Client ) -> S ,
165- S : LanguageServer ,
164+ F : FnOnce ( Client ) -> Backend ,
166165 {
166+ async fn test_configuration_handler (
167+ service : & Backend ,
168+ _params : Value ,
169+ ) -> Result < Value , tower_lsp_server:: jsonrpc:: Error > {
170+ let mut configs = vec ! [ ] ;
171+ for worker in & * service. workspace_workers . read ( ) . await {
172+ configs. push ( worker. options . lock ( ) . await . clone ( ) ) ;
173+ }
174+ Ok ( json ! ( configs) )
175+ }
176+
167177 let ( req_client, req_server) = tokio:: io:: duplex ( 1024 ) ;
168178 let ( res_server, res_client) = tokio:: io:: duplex ( 1024 ) ;
169179
170- let ( service, socket) = LspService :: new ( init) ;
180+ let ( service, socket) = LspService :: build ( init)
181+ . custom_method ( "test/configuration" , test_configuration_handler)
182+ . finish ( ) ;
171183
172184 tokio:: spawn ( Server :: new ( req_server, res_server, socket) . serve ( service) ) ;
173185
@@ -243,10 +255,9 @@ impl TestServer {
243255
244256 /// Creates a new TestServer and performs the initialize and initialized sequence.
245257 /// The `init` closure is used to create the LanguageServer instance.
246- async fn new_initialized < F , S > ( init : F , initialize : Request ) -> Self
258+ async fn new_initialized < F > ( init : F , initialize : Request ) -> Self
247259 where
248- F : FnOnce ( Client ) -> S ,
249- S : LanguageServer ,
260+ F : FnOnce ( Client ) -> Backend ,
250261 {
251262 let mut server = Self :: new ( init) ;
252263 let initialize_id = initialize. id ( ) . cloned ( ) ;
@@ -288,6 +299,7 @@ fn initialize_request(
288299 workspace_configuration : bool ,
289300 dynamic_watchers : bool ,
290301 workspace_edit : bool ,
302+ initialization_options : Option < Value > ,
291303) -> Request {
292304 let params = InitializeParams {
293305 workspace_folders : Some ( vec ! [ WorkspaceFolder {
@@ -306,6 +318,9 @@ fn initialize_request(
306318 } ) ,
307319 ..Default :: default ( )
308320 } ,
321+ initialization_options,
322+ #[ expect( deprecated) ]
323+ root_uri : Some ( WORKSPACE . parse ( ) . unwrap ( ) ) ,
309324 ..Default :: default ( )
310325 } ;
311326
@@ -448,6 +463,10 @@ fn code_action(id: i64, uri: &str) -> Request {
448463 Request :: build ( "textDocument/codeAction" ) . id ( id) . params ( json ! ( params) ) . finish ( )
449464}
450465
466+ fn test_configuration_request ( id : i64 ) -> Request {
467+ Request :: build ( "test/configuration" ) . id ( id) . params ( json ! ( null) ) . finish ( )
468+ }
469+
451470#[ cfg( test) ]
452471mod test_suite {
453472 use serde_json:: { Value , json} ;
@@ -466,7 +485,7 @@ mod test_suite {
466485 acknowledge_unregistrations, code_action, did_change, did_change_configuration,
467486 did_change_watched_files, did_close, did_open, did_save, execute_command_request,
468487 initialize_request, initialized_notification, response_to_configuration,
469- shutdown_request, workspace_folders_changed,
488+ shutdown_request, test_configuration_request , workspace_folders_changed,
470489 } ,
471490 } ;
472491
@@ -478,7 +497,7 @@ mod test_suite {
478497 async fn test_basic_start_and_shutdown_flow ( ) {
479498 let mut server = TestServer :: new ( |client| Backend :: new ( client, server_info ( ) , vec ! [ ] ) ) ;
480499 // initialize request
481- server. send_request ( initialize_request ( false , false , false ) ) . await ;
500+ server. send_request ( initialize_request ( false , false , false , None ) ) . await ;
482501 let initialize_result = server. recv_response ( ) . await ;
483502
484503 assert ! ( initialize_result. is_ok( ) ) ;
@@ -502,11 +521,81 @@ mod test_suite {
502521 // is handled by the lsp service itself
503522 }
504523
524+ #[ tokio:: test]
525+ async fn test_initialize_with_options ( ) {
526+ let init_options = json ! ( [
527+ {
528+ "workspaceUri" : WORKSPACE ,
529+ "options" : {
530+ "run" : true ,
531+ "configPath" : "./custom.json" ,
532+ "fmt.experimental" : true
533+ }
534+ }
535+ ] ) ;
536+
537+ let mut server = TestServer :: new_initialized (
538+ |client| Backend :: new ( client, server_info ( ) , vec ! [ ] ) ,
539+ initialize_request ( false , false , false , Some ( init_options. clone ( ) ) ) ,
540+ )
541+ . await ;
542+
543+ server. send_request ( test_configuration_request ( 2 ) ) . await ;
544+ let config_response = server. recv_response ( ) . await ;
545+
546+ assert ! ( config_response. is_ok( ) ) ;
547+ assert_eq ! ( config_response. id( ) , & Id :: Number ( 2 ) ) ;
548+ assert_eq ! (
549+ * config_response. result( ) . unwrap( ) ,
550+ json!( [ {
551+ "run" : true ,
552+ "configPath" : "./custom.json" ,
553+ "fmt.experimental" : true
554+ } ] )
555+ ) ;
556+
557+ // shutdown request
558+ server. shutdown ( 3 ) . await ;
559+ }
560+
561+ #[ tokio:: test]
562+ async fn test_initialize_with_deprecated_options ( ) {
563+ let init_options = json ! ( {
564+ "settings" : {
565+ "run" : true ,
566+ "configPath" : "./custom.json" ,
567+ "fmt.experimental" : true
568+ }
569+ } ) ;
570+
571+ let mut server = TestServer :: new_initialized (
572+ |client| Backend :: new ( client, server_info ( ) , vec ! [ ] ) ,
573+ initialize_request ( false , false , false , Some ( init_options) ) ,
574+ )
575+ . await ;
576+
577+ server. send_request ( test_configuration_request ( 2 ) ) . await ;
578+ let config_response = server. recv_response ( ) . await ;
579+
580+ assert ! ( config_response. is_ok( ) ) ;
581+ assert_eq ! ( config_response. id( ) , & Id :: Number ( 2 ) ) ;
582+ assert_eq ! (
583+ * config_response. result( ) . unwrap( ) ,
584+ json!( [ {
585+ "run" : true ,
586+ "configPath" : "./custom.json" ,
587+ "fmt.experimental" : true
588+ } ] )
589+ ) ;
590+ // shutdown request
591+ server. shutdown ( 3 ) . await ;
592+ }
593+
505594 #[ tokio:: test]
506595 async fn test_workspace_configuration_on_initialized ( ) {
507596 let mut server = TestServer :: new_initialized (
508597 |client| Backend :: new ( client, server_info ( ) , vec ! [ ] ) ,
509- initialize_request ( true , false , false ) ,
598+ initialize_request ( true , false , false , None ) ,
510599 )
511600 . await ;
512601
@@ -544,7 +633,7 @@ mod test_suite {
544633 async fn test_dynamic_watched_files_registration ( ) {
545634 let mut server = TestServer :: new_initialized (
546635 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
547- initialize_request ( false , true , false ) ,
636+ initialize_request ( false , true , false , None ) ,
548637 )
549638 . await ;
550639
@@ -610,7 +699,7 @@ mod test_suite {
610699 async fn test_execute_workspace_command_with_apply_edit ( ) {
611700 let mut server = TestServer :: new_initialized (
612701 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
613- initialize_request ( false , false , true ) ,
702+ initialize_request ( false , false , true , None ) ,
614703 )
615704 . await ;
616705
@@ -656,7 +745,7 @@ mod test_suite {
656745 async fn test_execute_workspace_command_with_no_edit ( ) {
657746 let mut server = TestServer :: new_initialized (
658747 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
659- initialize_request ( false , false , false ) ,
748+ initialize_request ( false , false , false , None ) ,
660749 )
661750 . await ;
662751
@@ -678,7 +767,7 @@ mod test_suite {
678767 async fn test_execute_workspace_command_with_invalid_command ( ) {
679768 let mut server = TestServer :: new_initialized (
680769 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
681- initialize_request ( false , false , false ) ,
770+ initialize_request ( false , false , false , None ) ,
682771 )
683772 . await ;
684773
@@ -708,7 +797,7 @@ mod test_suite {
708797
709798 let mut server = TestServer :: new_initialized (
710799 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
711- initialize_request ( false , false , false ) ,
800+ initialize_request ( false , false , false , None ) ,
712801 )
713802 . await ;
714803 server. send_request ( folders_changed_notification) . await ;
@@ -730,7 +819,7 @@ mod test_suite {
730819
731820 let mut server = TestServer :: new_initialized (
732821 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
733- initialize_request ( false , true , false ) ,
822+ initialize_request ( false , true , false , None ) ,
734823 )
735824 . await ;
736825 acknowledge_registrations ( & mut server) . await ;
@@ -754,7 +843,7 @@ mod test_suite {
754843
755844 let mut server = TestServer :: new_initialized (
756845 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
757- initialize_request ( true , false , false ) ,
846+ initialize_request ( true , false , false , None ) ,
758847 )
759848 . await ;
760849 // workspace configuration request expected, one for initial workspace
@@ -781,7 +870,7 @@ mod test_suite {
781870
782871 let mut server = TestServer :: new_initialized (
783872 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
784- initialize_request ( false , false , false ) ,
873+ initialize_request ( false , false , false , None ) ,
785874 )
786875 . await ;
787876 server. send_request ( folders_changed_notification) . await ;
@@ -803,7 +892,7 @@ mod test_suite {
803892
804893 let mut server = TestServer :: new_initialized (
805894 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
806- initialize_request ( false , true , false ) ,
895+ initialize_request ( false , true , false , None ) ,
807896 )
808897 . await ;
809898 acknowledge_registrations ( & mut server) . await ;
@@ -819,7 +908,7 @@ mod test_suite {
819908 async fn test_watched_file_changed_unknown ( ) {
820909 let mut server = TestServer :: new_initialized (
821910 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
822- initialize_request ( false , true , false ) ,
911+ initialize_request ( false , true , false , None ) ,
823912 )
824913 . await ;
825914 acknowledge_registrations ( & mut server) . await ;
@@ -839,7 +928,7 @@ mod test_suite {
839928 async fn test_watched_file_changed_new_watchers ( ) {
840929 let mut server = TestServer :: new_initialized (
841930 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
842- initialize_request ( false , true , false ) ,
931+ initialize_request ( false , true , false , None ) ,
843932 )
844933 . await ;
845934 acknowledge_registrations ( & mut server) . await ;
@@ -861,7 +950,7 @@ mod test_suite {
861950 async fn test_did_change_configuration_no_changes ( ) {
862951 let mut server = TestServer :: new_initialized (
863952 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
864- initialize_request ( false , true , false ) ,
953+ initialize_request ( false , true , false , None ) ,
865954 )
866955 . await ;
867956 acknowledge_registrations ( & mut server) . await ;
@@ -879,7 +968,7 @@ mod test_suite {
879968 async fn test_did_change_configuration_config_passed_new_watchers ( ) {
880969 let mut server = TestServer :: new_initialized (
881970 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
882- initialize_request ( false , true , false ) ,
971+ initialize_request ( false , true , false , None ) ,
883972 )
884973 . await ;
885974 acknowledge_registrations ( & mut server) . await ;
@@ -905,7 +994,7 @@ mod test_suite {
905994 async fn test_did_change_configuration_config_requested_new_watchers ( ) {
906995 let mut server = TestServer :: new_initialized (
907996 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
908- initialize_request ( true , true , false ) ,
997+ initialize_request ( true , true , false , None ) ,
909998 )
910999 . await ;
9111000 response_to_configuration ( & mut server, vec ! [ json!( null) ] ) . await ;
@@ -930,7 +1019,7 @@ mod test_suite {
9301019 async fn test_file_notifications ( ) {
9311020 let mut server = TestServer :: new_initialized (
9321021 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
933- initialize_request ( false , false , false ) ,
1022+ initialize_request ( false , false , false , None ) ,
9341023 )
9351024 . await ;
9361025
@@ -947,7 +1036,7 @@ mod test_suite {
9471036 async fn test_code_action_no_actions ( ) {
9481037 let mut server = TestServer :: new_initialized (
9491038 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
950- initialize_request ( false , false , false ) ,
1039+ initialize_request ( false , false , false , None ) ,
9511040 )
9521041 . await ;
9531042
@@ -969,7 +1058,7 @@ mod test_suite {
9691058 async fn test_code_actions_with_actions ( ) {
9701059 let mut server = TestServer :: new_initialized (
9711060 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
972- initialize_request ( false , false , false ) ,
1061+ initialize_request ( false , false , false , None ) ,
9731062 )
9741063 . await ;
9751064
@@ -994,7 +1083,7 @@ mod test_suite {
9941083 async fn test_diagnostic_on_open ( ) {
9951084 let mut server = TestServer :: new_initialized (
9961085 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
997- initialize_request ( false , false , false ) ,
1086+ initialize_request ( false , false , false , None ) ,
9981087 )
9991088 . await ;
10001089
@@ -1020,7 +1109,7 @@ mod test_suite {
10201109 async fn test_diagnostic_on_change ( ) {
10211110 let mut server = TestServer :: new_initialized (
10221111 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
1023- initialize_request ( false , false , false ) ,
1112+ initialize_request ( false , false , false , None ) ,
10241113 )
10251114 . await ;
10261115
@@ -1050,7 +1139,7 @@ mod test_suite {
10501139 async fn test_diagnostic_on_save ( ) {
10511140 let mut server = TestServer :: new_initialized (
10521141 |client| Backend :: new ( client, server_info ( ) , vec ! [ Box :: new( FakeToolBuilder ) ] ) ,
1053- initialize_request ( false , false , false ) ,
1142+ initialize_request ( false , false , false , None ) ,
10541143 )
10551144 . await ;
10561145
0 commit comments