11mod client;
22mod server;
33
4+ use std:: collections:: VecDeque ;
45use std:: io:: { self , Write } ;
56use std:: sync:: Arc ;
67
@@ -17,7 +18,7 @@ use rsground_runner::{PipeWriter, Runner};
1718use tokio:: sync:: broadcast;
1819use uuid:: Uuid ;
1920
20- use crate :: utils:: { define_local_logger, ArcStr } ;
21+ use crate :: utils:: { define_local_logger, ArcStr , Truncate } ;
2122use crate :: ws:: messages:: InternalMessage ;
2223
2324use super :: project_runner:: { start_job, AbortSender } ;
@@ -36,10 +37,12 @@ define_local_logger!(local_log as "backend::lsp" {
3637const LSP_INITIALIZATION_ID : & str = "rsground::initialize" ;
3738
3839pub struct ProjectLsp {
39- project_id : Uuid ,
4040 broadcast : broadcast:: Sender < InternalMessage > ,
41- runner : Arc < Runner > ,
4241 instance : Option < ( AbortSender , PipeWriter ) > ,
42+ project_id : Uuid ,
43+ queue : VecDeque < Stdin > ,
44+ ready : bool ,
45+ runner : Arc < Runner > ,
4346}
4447
4548impl ProjectLsp {
@@ -49,10 +52,12 @@ impl ProjectLsp {
4952 runner : Arc < Runner > ,
5053 ) -> Addr < Self > {
5154 let project_lsp = Self {
52- project_id,
5355 broadcast,
54- runner,
5556 instance : None ,
57+ project_id,
58+ queue : VecDeque :: new ( ) ,
59+ ready : false ,
60+ runner,
5661 } ;
5762
5863 project_lsp. start ( )
@@ -63,6 +68,39 @@ impl Actor for ProjectLsp {
6368 type Context = Context < ProjectLsp > ;
6469}
6570
71+ pub trait ProjectLspActor {
72+ fn send_request < T : Request , const QUEUE : bool > (
73+ & self ,
74+ id : impl serde:: Serialize ,
75+ params : & T :: Params ,
76+ ) ;
77+ fn send_notify < T : Notification , const QUEUE : bool > ( & self , params : & T :: Params ) ;
78+ }
79+
80+ impl ProjectLspActor for Addr < ProjectLsp > {
81+ fn send_request < T : Request , const QUEUE : bool > (
82+ & self ,
83+ id : impl serde:: Serialize ,
84+ params : & T :: Params ,
85+ ) {
86+ match LspInput :: request :: < T > ( id, params) {
87+ Ok ( req) => self . do_send ( Stdin :: < QUEUE > ( req) ) ,
88+ Err ( err) => {
89+ local_log:: stdin:: error!( "Serialize: {err:?}" ) ;
90+ }
91+ }
92+ }
93+
94+ fn send_notify < T : Notification , const QUEUE : bool > ( & self , params : & T :: Params ) {
95+ match LspInput :: notify :: < T > ( params) {
96+ Ok ( req) => self . do_send ( Stdin :: < QUEUE > ( req) ) ,
97+ Err ( err) => {
98+ local_log:: stdin:: error!( "Serialize: {err:?}" ) ;
99+ }
100+ }
101+ }
102+ }
103+
66104// Client-side messages
67105
68106#[ derive( Message ) ]
@@ -71,7 +109,7 @@ pub struct Execute;
71109
72110#[ derive( Message ) ]
73111#[ rtype( result = "()" ) ]
74- pub struct Stdin ( String ) ;
112+ pub struct Stdin < const QUEUE : bool = true > ( String ) ;
75113
76114#[ derive( Message ) ]
77115#[ rtype( result = "()" ) ]
@@ -103,19 +141,10 @@ impl Handler<Execute> for ProjectLsp {
103141 move |abort, this, ctx| {
104142 this. instance . replace ( ( abort, stdin) ) ;
105143
106- match LspInput :: request :: < Initialize > (
144+ ctx . address ( ) . send_request :: < Initialize , false > (
107145 LSP_INITIALIZATION_ID ,
108146 & * client:: LSP_INITIALIZATION ,
109- ) {
110- Ok ( req) => {
111- local_log:: initialize:: info!( target: this. project_id, "Initialize sended" ) ;
112- ctx. notify ( Stdin ( req) )
113- }
114- Err ( err) => {
115- local_log:: initialize:: error!( target: this. project_id, "{err:?}" ) ;
116- ctx. notify ( Kill ) ;
117- }
118- }
147+ ) ;
119148 } ,
120149 async move |abort| child. wait_or_abort ( abort) . await ,
121150 |_, this, _| {
@@ -132,21 +161,26 @@ impl Handler<Kill> for ProjectLsp {
132161 type Result = ( ) ;
133162
134163 fn handle ( & mut self , _: Kill , _: & mut Self :: Context ) -> Self :: Result {
164+ self . ready = false ;
135165 if let Some ( ( abort, _) ) = self . instance . take ( ) {
136166 _ = abort. send ( ( ) ) ;
137167 }
138168 }
139169}
140170
141- impl Handler < Stdin > for ProjectLsp {
171+ impl < const QUEUE : bool > Handler < Stdin < QUEUE > > for ProjectLsp {
142172 type Result = ( ) ;
143173
144- fn handle ( & mut self , Stdin ( msg) : Stdin , _: & mut Self :: Context ) -> Self :: Result {
145- if let Some ( ( _, stdin) ) = self . instance . as_mut ( ) {
146- let msg = format ! ( "Content-Length: {}\r \n \r \n {msg}" , msg. len( ) ) ;
147- if let Err ( err) = stdin. write_all ( msg. as_bytes ( ) ) . and_then ( |_| stdin. flush ( ) ) {
148- local_log:: stdin:: error!( target: self . project_id, "Cannot write: {err}" )
174+ fn handle ( & mut self , Stdin ( msg) : Stdin < QUEUE > , _: & mut Self :: Context ) -> Self :: Result {
175+ if !QUEUE || self . ready {
176+ if let Some ( ( _, stdin) ) = self . instance . as_mut ( ) {
177+ let msg = format ! ( "Content-Length: {}\r \n \r \n {msg}" , msg. len( ) ) ;
178+ if let Err ( err) = stdin. write_all ( msg. as_bytes ( ) ) . and_then ( |_| stdin. flush ( ) ) {
179+ local_log:: stdin:: error!( target: self . project_id, "Cannot write: {err}" )
180+ }
149181 }
182+ } else {
183+ self . queue . push_back ( Stdin ( msg) ) ;
150184 }
151185 }
152186}
@@ -229,7 +263,7 @@ impl Handler<ClientStdin> for ProjectLsp {
229263 return ;
230264 } ;
231265
232- ctx. notify ( Stdin ( msg) ) ;
266+ ctx. notify ( Stdin :: < true > ( msg) ) ;
233267 }
234268}
235269
@@ -248,9 +282,16 @@ impl StreamHandler<Stdout> for ProjectLsp {
248282 LspOutput :: Response ( res) if res. id ( ) == LSP_INITIALIZATION_ID => match res {
249283 LspResponse :: Ok { result, .. } => {
250284 local_log:: initialize:: info!( target: self . project_id, "Initialize received" ) ;
251- local_log:: initialize:: trace!( target: self . project_id, "{result:?}" ) ;
252- if let Ok ( noti) = LspInput :: notify :: < Initialized > ( InitializedParams { } ) {
253- ctx. notify ( Stdin ( noti) ) ;
285+ local_log:: initialize:: trace!( target: self . project_id, "{:?}" , result. truncate:: <256 >( ) ) ;
286+
287+ self . ready = true ;
288+
289+ if let Ok ( noti) = LspInput :: notify :: < Initialized > ( & InitializedParams { } ) {
290+ ctx. notify ( Stdin :: < false > ( noti) ) ;
291+ }
292+
293+ while let Some ( msg) = self . queue . pop_front ( ) {
294+ ctx. notify ( msg) ;
254295 }
255296 }
256297 LspResponse :: Err { error, .. } => {
@@ -260,7 +301,7 @@ impl StreamHandler<Stdout> for ProjectLsp {
260301 } ,
261302
262303 LspOutput :: Response ( res) => {
263- local_log:: response:: trace!( target: self . project_id, "{res :?}" ) ;
304+ local_log:: response:: trace!( target: self . project_id, "{:?}" , ( & res ) . truncate :: < 256 > ( ) ) ;
264305 let ( client_id, res_id) = res
265306 . id ( )
266307 . clone ( )
0 commit comments