1111//! receiver (thus, implementing the Future<Item = Value> model).
1212
1313use std:: cell:: { Ref , RefCell } ;
14- use std:: io:: { Read , Write } ;
1514use std:: process:: { Command , Stdio } ;
1615use std:: rc:: Rc ;
1716
18- use futures:: Poll ;
1917use futures:: sink:: Sink ;
2018use futures:: stream:: { SplitSink , Stream } ;
2119use futures:: unsync:: oneshot;
@@ -28,11 +26,14 @@ use serde_json::{json, Value};
2826use tokio:: io:: { AsyncRead , AsyncWrite } ;
2927use tokio:: runtime:: current_thread:: Runtime ;
3028use tokio:: util:: { FutureExt , StreamExt } ;
31- use tokio_process:: { Child , CommandExt } ;
3229
3330use super :: project_builder:: Project ;
3431use super :: { rls_exe, rls_timeout} ;
3532
33+ use child_process:: ChildProcess ;
34+
35+ mod child_process;
36+
3637// `Rc` because we share those in message reader stream and the RlsHandle.
3738// `RefCell` because borrows don't overlap. This is safe, because `process_msg`
3839// is only called (synchronously) when we execute some work on the runtime,
@@ -41,61 +42,13 @@ use super::{rls_exe, rls_timeout};
4142type Messages = Rc < RefCell < Vec < Value > > > ;
4243type Channels = Rc < RefCell < Vec < ( Box < Fn ( & Value ) -> bool > , oneshot:: Sender < Value > ) > > > ;
4344
44- pub struct ChildProcess {
45- stdin : tokio_process:: ChildStdin ,
46- stdout : tokio_process:: ChildStdout ,
47- child : Rc < tokio_process:: Child > ,
48- }
49-
50- impl Read for ChildProcess {
51- fn read ( & mut self , buf : & mut [ u8 ] ) -> std:: io:: Result < usize > {
52- Read :: read ( & mut self . stdout , buf)
53- }
54- }
55-
56- impl Write for ChildProcess {
57- fn write ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < usize > {
58- Write :: write ( & mut self . stdin , buf)
59- }
60- fn flush ( & mut self ) -> std:: io:: Result < ( ) > {
61- Write :: flush ( & mut self . stdin )
62- }
63- }
64-
65- impl AsyncRead for ChildProcess { }
66- impl AsyncWrite for ChildProcess {
67- fn shutdown ( & mut self ) -> Poll < ( ) , std:: io:: Error > {
68- AsyncWrite :: shutdown ( & mut self . stdin )
69- }
70- }
71-
72- impl ChildProcess {
73- pub fn spawn_from_command ( mut cmd : Command ) -> Result < ChildProcess , std:: io:: Error > {
74- cmd. stdin ( Stdio :: piped ( ) ) ;
75- cmd. stdout ( Stdio :: piped ( ) ) ;
76- let mut child = cmd. spawn_async ( ) ?;
77-
78- Ok ( ChildProcess {
79- stdout : child. stdout ( ) . take ( ) . unwrap ( ) ,
80- stdin : child. stdin ( ) . take ( ) . unwrap ( ) ,
81- child : Rc :: new ( child) ,
82- } )
83- }
84-
85- /// Returns a handle to the underlying `Child` process.
86- /// Useful when waiting until child process exits.
87- pub fn child ( & self ) -> Rc < Child > {
88- Rc :: clone ( & self . child )
89- }
90- }
91-
9245type LspFramed < T > = tokio:: codec:: Framed < T , LspCodec > ;
9346
9447trait LspFramedExt < T : AsyncRead + AsyncWrite > {
9548 fn from_transport ( transport : T ) -> Self ;
9649}
9750
98- impl < T > LspFramedExt < T > for LspFramed < T > where T : AsyncRead + AsyncWrite {
51+ impl < T : AsyncRead + AsyncWrite > LspFramedExt < T > for LspFramed < T > {
9952 fn from_transport ( transport : T ) -> Self {
10053 tokio:: codec:: Framed :: new ( transport, LspCodec :: default ( ) )
10154 }
@@ -106,19 +59,28 @@ impl Project {
10659 let mut cmd = Command :: new ( rls_exe ( ) ) ;
10760 cmd. current_dir ( self . root ( ) ) ;
10861 cmd. stderr ( Stdio :: inherit ( ) ) ;
62+
10963 cmd
11064 }
11165
112- pub fn spawn_rls_with_runtime ( & self , mut rt : Runtime ) -> RlsHandle < ChildProcess > {
113- let cmd = self . rls_cmd ( ) ;
66+ pub fn spawn_rls_async ( & self ) -> RlsHandle < ChildProcess > {
67+ let rt = Runtime :: new ( ) . unwrap ( ) ;
11468
69+ let cmd = self . rls_cmd ( ) ;
11570 let process = ChildProcess :: spawn_from_command ( cmd) . unwrap ( ) ;
116- let ( sink, stream) = LspFramed :: from_transport ( process) . split ( ) ;
11771
72+ self . spawn_rls_with_params ( rt, process)
73+ }
74+
75+ fn spawn_rls_with_params < T > ( & self , mut rt : Runtime , transport : T ) -> RlsHandle < T >
76+ where
77+ T : AsyncRead + AsyncWrite + ' static ,
78+ {
79+ let ( finished_reading, reader_closed) = oneshot:: channel ( ) ;
11880 let msgs = Messages :: default ( ) ;
11981 let chans = Channels :: default ( ) ;
12082
121- let ( finished_reading , reader_closed ) = oneshot :: channel ( ) ;
83+ let ( sink , stream ) = LspFramed :: from_transport ( transport ) . split ( ) ;
12284
12385 let reader = stream
12486 . timeout ( rls_timeout ( ) )
@@ -133,19 +95,7 @@ impl Project {
13395
13496 let sink = Some ( sink) ;
13597
136- RlsHandle {
137- writer : sink,
138- runtime : rt,
139- reader_closed,
140- messages : msgs,
141- channels : chans
142- }
143- }
144-
145- pub fn spawn_rls_async ( & self ) -> RlsHandle < ChildProcess > {
146- let rt = Runtime :: new ( ) . unwrap ( ) ;
147-
148- self . spawn_rls_with_runtime ( rt)
98+ RlsHandle { writer : sink, runtime : rt, reader_closed, messages : msgs, channels : chans }
14999 }
150100}
151101
@@ -326,4 +276,4 @@ impl<T: AsyncRead + AsyncWrite> Drop for RlsHandle<T> {
326276
327277 self . runtime . block_on ( reader_closed) . unwrap ( ) ;
328278 }
329- }
279+ }
0 commit comments