@@ -4,7 +4,7 @@ use serde_json::{Value, json};
44use tokio:: io:: { AsyncReadExt , AsyncWriteExt , DuplexStream } ;
55use tower_lsp_server:: {
66 Client , LspService , Server ,
7- jsonrpc:: { ErrorCode , Id , Request , Response } ,
7+ jsonrpc:: { ErrorCode , Request , Response } ,
88 lsp_types:: * ,
99} ;
1010
@@ -22,7 +22,7 @@ pub struct FakeTool;
2222
2323pub const FAKE_COMMAND : & str = "fake.command" ;
2424
25- const WORKSPACE : & str = "file:///path/to/workspace" ;
25+ pub const WORKSPACE : & str = "file:///path/to/workspace" ;
2626
2727impl Tool for FakeTool {
2828 fn name ( & self ) -> & ' static str {
@@ -152,14 +152,14 @@ impl Tool for FakeTool {
152152
153153// A test server that can send requests and receive responses.
154154// Copied from <https://github.com/veryl-lang/veryl/blob/888d83abaa58ca5a7ffef501a1c557e48c750b92/crates/languageserver/src/tests.rs>
155- struct TestServer {
155+ pub struct TestServer {
156156 req_stream : DuplexStream ,
157157 res_stream : DuplexStream ,
158158 responses : VecDeque < String > ,
159159}
160160
161161impl TestServer {
162- fn new < F > ( init : F ) -> Self
162+ pub fn new < F > ( init : F ) -> Self
163163 where
164164 F : FnOnce ( Client ) -> Backend ,
165165 {
@@ -208,26 +208,37 @@ impl TestServer {
208208 ret
209209 }
210210
211- async fn send_request ( & mut self , req : Request ) {
211+ /// Sends a request to the server.
212+ ///
213+ /// # Panics
214+ /// - If the stream cannot be written to.
215+ pub async fn send_request ( & mut self , req : Request ) {
212216 let req = serde_json:: to_string ( & req) . unwrap ( ) ;
213217 let req = Self :: encode ( & req) ;
214218 self . req_stream . write_all ( req. as_bytes ( ) ) . await . unwrap ( ) ;
215219 }
216220
221+ #[ cfg( test) ]
217222 async fn send_response ( & mut self , res : Response ) {
218223 let res = serde_json:: to_string ( & res) . unwrap ( ) ;
219224 let res = Self :: encode ( & res) ;
220225 self . req_stream . write_all ( res. as_bytes ( ) ) . await . unwrap ( ) ;
221226 }
222227
223- async fn send_ack ( & mut self , id : & Id ) {
228+ #[ cfg( test) ]
229+ async fn send_ack ( & mut self , id : & tower_lsp_server:: jsonrpc:: Id ) {
224230 let req = Response :: from_ok ( id. clone ( ) , None :: < serde_json:: Value > . into ( ) ) ;
225231 let req = serde_json:: to_string ( & req) . unwrap ( ) ;
226232 let req = Self :: encode ( & req) ;
227233 self . req_stream . write_all ( req. as_bytes ( ) ) . await . unwrap ( ) ;
228234 }
229235
230- async fn recv_response ( & mut self ) -> Response {
236+ /// Receives a response from the server.
237+ ///
238+ /// # Panics
239+ /// - If the stream cannot be read.
240+ /// - If the response cannot be deserialized.
241+ pub async fn recv_response ( & mut self ) -> Response {
231242 if self . responses . is_empty ( ) {
232243 let mut buf = vec ! [ 0 ; 1024 ] ;
233244 let n = self . res_stream . read ( & mut buf) . await . unwrap ( ) ;
@@ -240,6 +251,7 @@ impl TestServer {
240251 serde_json:: from_str ( & res) . unwrap ( )
241252 }
242253
254+ #[ cfg( test) ]
243255 async fn recv_notification ( & mut self ) -> Request {
244256 if self . responses . is_empty ( ) {
245257 let mut buf = vec ! [ 0 ; 1024 ] ;
@@ -255,6 +267,7 @@ impl TestServer {
255267
256268 /// Creates a new TestServer and performs the initialize and initialized sequence.
257269 /// The `init` closure is used to create the LanguageServer instance.
270+ #[ cfg( test) ]
258271 async fn new_initialized < F > ( init : F , initialize : Request ) -> Self
259272 where
260273 F : FnOnce ( Client ) -> Backend ,
@@ -273,13 +286,15 @@ impl TestServer {
273286 server
274287 }
275288
289+ #[ cfg( test) ]
276290 async fn shutdown ( & mut self , id : i64 ) {
277291 self . send_request ( shutdown_request ( id) ) . await ;
278292 let shutdown_result = self . recv_response ( ) . await ;
279293 assert ! ( shutdown_result. is_ok( ) ) ;
280- assert_eq ! ( shutdown_result. id( ) , & Id :: Number ( id) ) ;
294+ assert_eq ! ( shutdown_result. id( ) , & tower_lsp_server :: jsonrpc :: Id :: Number ( id) ) ;
281295 }
282296
297+ #[ cfg( test) ]
283298 async fn shutdown_with_watchers ( & mut self , id : i64 ) {
284299 // shutdown request
285300 self . send_request ( shutdown_request ( id) ) . await ;
@@ -291,11 +306,15 @@ impl TestServer {
291306 let shutdown_result = self . recv_response ( ) . await ;
292307
293308 assert ! ( shutdown_result. is_ok( ) ) ;
294- assert_eq ! ( shutdown_result. id( ) , & Id :: Number ( id) ) ;
309+ assert_eq ! ( shutdown_result. id( ) , & tower_lsp_server :: jsonrpc :: Id :: Number ( id) ) ;
295310 }
296311}
297312
298- fn initialize_request (
313+ /// Creates an initialize request with the given parameters.
314+ ///
315+ /// # Panics
316+ /// - If the workspace URI is not a valid URI.
317+ pub fn initialize_request (
299318 workspace_configuration : bool ,
300319 dynamic_watchers : bool ,
301320 workspace_edit : bool ,
@@ -327,16 +346,17 @@ fn initialize_request(
327346 Request :: build ( "initialize" ) . params ( json ! ( params) ) . id ( 1 ) . finish ( )
328347}
329348
330- fn initialized_notification ( ) -> Request {
349+ pub fn initialized_notification ( ) -> Request {
331350 let params = InitializedParams { } ;
332351
333352 Request :: build ( "initialized" ) . params ( json ! ( params) ) . finish ( )
334353}
335354
336- fn shutdown_request ( id : i64 ) -> Request {
355+ pub fn shutdown_request ( id : i64 ) -> Request {
337356 Request :: build ( "shutdown" ) . id ( id) . finish ( )
338357}
339358
359+ #[ cfg( test) ]
340360fn execute_command_request ( command : & str , arguments : & [ serde_json:: Value ] , id : i64 ) -> Request {
341361 Request :: build ( "workspace/executeCommand" )
342362 . id ( id)
@@ -347,6 +367,7 @@ fn execute_command_request(command: &str, arguments: &[serde_json::Value], id: i
347367 . finish ( )
348368}
349369
370+ #[ cfg( test) ]
350371fn workspace_folders_changed (
351372 added : Vec < WorkspaceFolder > ,
352373 removed : Vec < WorkspaceFolder > ,
@@ -357,6 +378,7 @@ fn workspace_folders_changed(
357378 Request :: build ( "workspace/didChangeWorkspaceFolders" ) . params ( json ! ( params) ) . finish ( )
358379}
359380
381+ #[ cfg( test) ]
360382async fn acknowledge_registrations ( server : & mut TestServer ) {
361383 // client/registerCapability request
362384 let register_request = server. recv_notification ( ) . await ;
@@ -366,6 +388,7 @@ async fn acknowledge_registrations(server: &mut TestServer) {
366388 server. send_ack ( register_request. id ( ) . unwrap ( ) ) . await ;
367389}
368390
391+ #[ cfg( test) ]
369392async fn acknowledge_unregistrations ( server : & mut TestServer ) {
370393 // client/unregisterCapability request
371394 let unregister_request = server. recv_notification ( ) . await ;
@@ -375,6 +398,7 @@ async fn acknowledge_unregistrations(server: &mut TestServer) {
375398 server. send_ack ( unregister_request. id ( ) . unwrap ( ) ) . await ;
376399}
377400
401+ #[ cfg( test) ]
378402async fn response_to_configuration (
379403 server : & mut TestServer ,
380404 configurations : Vec < serde_json:: Value > ,
@@ -389,6 +413,7 @@ async fn response_to_configuration(
389413 . await ;
390414}
391415
416+ #[ cfg( test) ]
392417fn did_change_watched_files ( uri : & str ) -> Request {
393418 Request :: build ( "workspace/didChangeWatchedFiles" )
394419 . params ( json ! ( {
@@ -402,13 +427,18 @@ fn did_change_watched_files(uri: &str) -> Request {
402427 . finish ( )
403428}
404429
430+ #[ cfg( test) ]
405431fn did_change_configuration ( new_config : Option < serde_json:: Value > ) -> Request {
406432 Request :: build ( "workspace/didChangeConfiguration" )
407433 . params ( json ! ( DidChangeConfigurationParams { settings: new_config. unwrap_or_default( ) } ) )
408434 . finish ( )
409435}
410436
411- fn did_open ( uri : & str , text : & str ) -> Request {
437+ /// Creates a didOpen notification for the given URI and text.
438+ ///
439+ /// # Panics
440+ /// - If the URI is not a valid URI.
441+ pub fn did_open ( uri : & str , text : & str ) -> Request {
412442 let params = DidOpenTextDocumentParams {
413443 text_document : TextDocumentItem {
414444 uri : uri. parse ( ) . unwrap ( ) ,
@@ -421,6 +451,7 @@ fn did_open(uri: &str, text: &str) -> Request {
421451 Request :: build ( "textDocument/didOpen" ) . params ( json ! ( params) ) . finish ( )
422452}
423453
454+ #[ cfg( test) ]
424455fn did_change ( uri : & str , text : & str ) -> Request {
425456 let params = DidChangeTextDocumentParams {
426457 text_document : VersionedTextDocumentIdentifier { uri : uri. parse ( ) . unwrap ( ) , version : 2 } ,
@@ -434,6 +465,7 @@ fn did_change(uri: &str, text: &str) -> Request {
434465 Request :: build ( "textDocument/didChange" ) . params ( json ! ( params) ) . finish ( )
435466}
436467
468+ #[ cfg( test) ]
437469fn did_save ( uri : & str , text : & str ) -> Request {
438470 let params = DidSaveTextDocumentParams {
439471 text_document : TextDocumentIdentifier { uri : uri. parse ( ) . unwrap ( ) } ,
@@ -443,6 +475,7 @@ fn did_save(uri: &str, text: &str) -> Request {
443475 Request :: build ( "textDocument/didSave" ) . params ( json ! ( params) ) . finish ( )
444476}
445477
478+ #[ cfg( test) ]
446479fn did_close ( uri : & str ) -> Request {
447480 let params = DidCloseTextDocumentParams {
448481 text_document : TextDocumentIdentifier { uri : uri. parse ( ) . unwrap ( ) } ,
@@ -451,6 +484,7 @@ fn did_close(uri: &str) -> Request {
451484 Request :: build ( "textDocument/didClose" ) . params ( json ! ( params) ) . finish ( )
452485}
453486
487+ #[ cfg( test) ]
454488fn code_action ( id : i64 , uri : & str ) -> Request {
455489 let params = CodeActionParams {
456490 text_document : TextDocumentIdentifier { uri : uri. parse ( ) . unwrap ( ) } ,
@@ -463,23 +497,29 @@ fn code_action(id: i64, uri: &str) -> Request {
463497 Request :: build ( "textDocument/codeAction" ) . id ( id) . params ( json ! ( params) ) . finish ( )
464498}
465499
500+ #[ cfg( test) ]
466501fn test_configuration_request ( id : i64 ) -> Request {
467502 Request :: build ( "test/configuration" ) . id ( id) . params ( json ! ( null) ) . finish ( )
468503}
469504
505+ pub fn server_info ( ) -> ServerInfo {
506+ ServerInfo { name : "oxc" . to_owned ( ) , version : Some ( "1.0.0" . to_owned ( ) ) }
507+ }
508+
470509#[ cfg( test) ]
471510mod test_suite {
472511 use serde_json:: { Value , json} ;
473512 use tower_lsp_server:: {
474513 jsonrpc:: { Id , Response } ,
475514 lsp_types:: {
476- ApplyWorkspaceEditResponse , InitializeResult , PublishDiagnosticsParams , ServerInfo ,
477- WorkspaceEdit , WorkspaceFolder ,
515+ ApplyWorkspaceEditResponse , InitializeResult , PublishDiagnosticsParams , WorkspaceEdit ,
516+ WorkspaceFolder ,
478517 } ,
479518 } ;
480519
481520 use crate :: {
482521 backend:: Backend ,
522+ server_info,
483523 tests:: {
484524 FAKE_COMMAND , FakeToolBuilder , TestServer , WORKSPACE , acknowledge_registrations,
485525 acknowledge_unregistrations, code_action, did_change, did_change_configuration,
@@ -489,10 +529,6 @@ mod test_suite {
489529 } ,
490530 } ;
491531
492- fn server_info ( ) -> ServerInfo {
493- ServerInfo { name : "oxc" . to_owned ( ) , version : Some ( "1.0.0" . to_owned ( ) ) }
494- }
495-
496532 #[ tokio:: test]
497533 async fn test_basic_start_and_shutdown_flow ( ) {
498534 let mut server = TestServer :: new ( |client| Backend :: new ( client, server_info ( ) , vec ! [ ] ) ) ;
0 commit comments