11
11
//! receiver (thus, implementing the Future<Item = Value> model).
12
12
13
13
use std:: cell:: { Ref , RefCell } ;
14
- use std:: io:: { Read , Write } ;
15
14
use std:: process:: { Command , Stdio } ;
16
15
use std:: rc:: Rc ;
17
16
18
- use futures:: Poll ;
19
17
use futures:: sink:: Sink ;
20
18
use futures:: stream:: { SplitSink , Stream } ;
21
19
use futures:: unsync:: oneshot;
@@ -28,11 +26,14 @@ use serde_json::{json, Value};
28
26
use tokio:: io:: { AsyncRead , AsyncWrite } ;
29
27
use tokio:: runtime:: current_thread:: Runtime ;
30
28
use tokio:: util:: { FutureExt , StreamExt } ;
31
- use tokio_process:: { Child , CommandExt } ;
32
29
33
30
use super :: project_builder:: Project ;
34
31
use super :: { rls_exe, rls_timeout} ;
35
32
33
+ use child_process:: ChildProcess ;
34
+
35
+ mod child_process;
36
+
36
37
// `Rc` because we share those in message reader stream and the RlsHandle.
37
38
// `RefCell` because borrows don't overlap. This is safe, because `process_msg`
38
39
// is only called (synchronously) when we execute some work on the runtime,
@@ -41,61 +42,13 @@ use super::{rls_exe, rls_timeout};
41
42
type Messages = Rc < RefCell < Vec < Value > > > ;
42
43
type Channels = Rc < RefCell < Vec < ( Box < Fn ( & Value ) -> bool > , oneshot:: Sender < Value > ) > > > ;
43
44
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
-
92
45
type LspFramed < T > = tokio:: codec:: Framed < T , LspCodec > ;
93
46
94
47
trait LspFramedExt < T : AsyncRead + AsyncWrite > {
95
48
fn from_transport ( transport : T ) -> Self ;
96
49
}
97
50
98
- impl < T > LspFramedExt < T > for LspFramed < T > where T : AsyncRead + AsyncWrite {
51
+ impl < T : AsyncRead + AsyncWrite > LspFramedExt < T > for LspFramed < T > {
99
52
fn from_transport ( transport : T ) -> Self {
100
53
tokio:: codec:: Framed :: new ( transport, LspCodec :: default ( ) )
101
54
}
@@ -106,19 +59,28 @@ impl Project {
106
59
let mut cmd = Command :: new ( rls_exe ( ) ) ;
107
60
cmd. current_dir ( self . root ( ) ) ;
108
61
cmd. stderr ( Stdio :: inherit ( ) ) ;
62
+
109
63
cmd
110
64
}
111
65
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 ( ) ;
114
68
69
+ let cmd = self . rls_cmd ( ) ;
115
70
let process = ChildProcess :: spawn_from_command ( cmd) . unwrap ( ) ;
116
- let ( sink, stream) = LspFramed :: from_transport ( process) . split ( ) ;
117
71
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 ( ) ;
118
80
let msgs = Messages :: default ( ) ;
119
81
let chans = Channels :: default ( ) ;
120
82
121
- let ( finished_reading , reader_closed ) = oneshot :: channel ( ) ;
83
+ let ( sink , stream ) = LspFramed :: from_transport ( transport ) . split ( ) ;
122
84
123
85
let reader = stream
124
86
. timeout ( rls_timeout ( ) )
@@ -133,19 +95,7 @@ impl Project {
133
95
134
96
let sink = Some ( sink) ;
135
97
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 }
149
99
}
150
100
}
151
101
@@ -326,4 +276,4 @@ impl<T: AsyncRead + AsyncWrite> Drop for RlsHandle<T> {
326
276
327
277
self . runtime . block_on ( reader_closed) . unwrap ( ) ;
328
278
}
329
- }
279
+ }
0 commit comments