Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 735212f

Browse files
committed
Separate ChildProcess transport to a submodule
1 parent 39fe80c commit 735212f

File tree

2 files changed

+75
-70
lines changed

2 files changed

+75
-70
lines changed

tests/support/client/child_process.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use std::io::{Read, Write};
2+
use std::process::{Command, Stdio};
3+
use std::rc::Rc;
4+
5+
use futures::Poll;
6+
use tokio::io::{AsyncRead, AsyncWrite};
7+
use tokio_process::{Child, CommandExt};
8+
9+
pub struct ChildProcess {
10+
stdin: tokio_process::ChildStdin,
11+
stdout: tokio_process::ChildStdout,
12+
child: Rc<tokio_process::Child>,
13+
}
14+
15+
impl Read for ChildProcess {
16+
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
17+
Read::read(&mut self.stdout, buf)
18+
}
19+
}
20+
21+
impl Write for ChildProcess {
22+
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
23+
Write::write(&mut self.stdin, buf)
24+
}
25+
fn flush(&mut self) -> std::io::Result<()> {
26+
Write::flush(&mut self.stdin)
27+
}
28+
}
29+
30+
impl AsyncRead for ChildProcess {}
31+
impl AsyncWrite for ChildProcess {
32+
fn shutdown(&mut self) -> Poll<(), std::io::Error> {
33+
AsyncWrite::shutdown(&mut self.stdin)
34+
}
35+
}
36+
37+
impl ChildProcess {
38+
pub fn spawn_from_command(mut cmd: Command) -> Result<ChildProcess, std::io::Error> {
39+
cmd.stdin(Stdio::piped());
40+
cmd.stdout(Stdio::piped());
41+
let mut child = cmd.spawn_async()?;
42+
43+
Ok(ChildProcess {
44+
stdout: child.stdout().take().unwrap(),
45+
stdin: child.stdin().take().unwrap(),
46+
child: Rc::new(child),
47+
})
48+
}
49+
50+
/// Returns a handle to the underlying `Child` process.
51+
/// Useful when waiting until child process exits.
52+
pub fn child(&self) -> Rc<Child> {
53+
Rc::clone(&self.child)
54+
}
55+
}

tests/support/client.rs renamed to tests/support/client/mod.rs

Lines changed: 20 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,9 @@
1111
//! receiver (thus, implementing the Future<Item = Value> model).
1212
1313
use std::cell::{Ref, RefCell};
14-
use std::io::{Read, Write};
1514
use std::process::{Command, Stdio};
1615
use std::rc::Rc;
1716

18-
use futures::Poll;
1917
use futures::sink::Sink;
2018
use futures::stream::{SplitSink, Stream};
2119
use futures::unsync::oneshot;
@@ -28,11 +26,14 @@ use serde_json::{json, Value};
2826
use tokio::io::{AsyncRead, AsyncWrite};
2927
use tokio::runtime::current_thread::Runtime;
3028
use tokio::util::{FutureExt, StreamExt};
31-
use tokio_process::{Child, CommandExt};
3229

3330
use super::project_builder::Project;
3431
use 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};
4142
type Messages = Rc<RefCell<Vec<Value>>>;
4243
type 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-
9245
type LspFramed<T> = tokio::codec::Framed<T, LspCodec>;
9346

9447
trait 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

Comments
 (0)