on master help sign in
helix-lsp cleanup
commitea6667070f05227f5d87eaf977ca0c7ddc982c0a authorEgor Karavaev <batonius.kirov@gmail.com> dateMon 7 Jun 2021, 22:11 (5 years ago) parent960bc9f
5 files changed+125−180
Cargo.lock−16 helix-lsp/Cargo.toml+8−13 helix-lsp/src/client.rs+20−41 helix-lsp/src/lib.rs+10−17 helix-lsp/src/transport.rs+87−93
Cargo.lock−16
@@ -237,12 +237,6 @@ dependencies = [
237237 "wasi",
238238]
239239
240−[[package]]
241−name = "glob"
242−version = "0.3.0"
243−source = "registry+https://github.com/rust-lang/crates.io-index"
244−checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
245−
246240[[package]]
247241name = "globset"
248242version = "0.4.6"
@@ -282,19 +276,15 @@ dependencies = [
282276 "anyhow",
283277 "futures-executor",
284278 "futures-util",
285− "glob",
286279 "helix-core",
287280 "jsonrpc-core",
288281 "log",
289282 "lsp-types",
290− "once_cell",
291− "pathdiff",
292283 "serde",
293284 "serde_json",
294285 "thiserror",
295286 "tokio",
296287 "tokio-stream",
297− "url",
298288]
299289
300290[[package]]
@@ -596,12 +586,6 @@ dependencies = [
596586 "winapi",
597587]
598588
599−[[package]]
600−name = "pathdiff"
601−version = "0.2.0"
602−source = "registry+https://github.com/rust-lang/crates.io-index"
603−checksum = "877630b3de15c0b64cc52f659345724fbf6bdad9bd9566699fc53688f3c34a34"
604−
605589[[package]]
606590name = "percent-encoding"
607591version = "2.1.0"
helix-lsp/Cargo.toml+8−13
@@ -10,19 +10,14 @@ license = "MPL-2.0"
1010[dependencies]
1111helix-core = { path = "../helix-core" }
1212
13−once_cell = "1.4"
14−
13+anyhow = "1.0"
14+futures-executor = "0.3"
15+futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
16+jsonrpc-core = { version = "17.1", default-features = false } # don't pull in all of futures
17+log = "0.4"
1518lsp-types = { version = "0.89", features = ["proposed"] }
16−tokio = { version = "1", features = ["full"] }
17−tokio-stream = "0.1.5"
18−futures-executor = { version = "0.3" }
19−url = "2"
20−pathdiff = "0.2"
21−glob = "0.3"
22−anyhow = "1"
23−serde_json = "1.0"
2419serde = { version = "1.0", features = ["derive"] }
25−jsonrpc-core = { version = "17.1", default-features = false } # don't pull in all of futures
26−futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
20+serde_json = "1.0"
2721thiserror = "1.0"
28−log = "~0.4"
22+tokio = { version = "1.6", features = ["full"] }
23+tokio-stream = "0.1.6"
helix-lsp/src/client.rs+20−41
@@ -4,30 +4,22 @@ use crate::{
44};
55
66use helix_core::{find_root, ChangeSet, Rope};
7−
8−// use std::collections::HashMap;
9−use std::future::Future;
10−use std::sync::atomic::{AtomicU64, Ordering};
11−
127use jsonrpc_core as jsonrpc;
138use lsp_types as lsp;
149use serde_json::Value;
15−
10+use std::future::Future;
1611use std::process::Stdio;
12+use std::sync::atomic::{AtomicU64, Ordering};
1713use tokio::{
1814 io::{BufReader, BufWriter},
19− // prelude::*,
2015 process::{Child, Command},
2116 sync::mpsc::{channel, UnboundedReceiver, UnboundedSender},
2217};
2318
2419pub struct Client {
2520 _process: Child,
26−
27− outgoing: UnboundedSender<Payload>,
28− // pub incoming: Receiver<Call>,
29− pub request_counter: AtomicU64,
30−
21+ server_tx: UnboundedSender<Payload>,
22+ request_counter: AtomicU64,
3123 capabilities: Option<lsp::ServerCapabilities>,
3224 offset_encoding: OffsetEncoding,
3325}
@@ -43,40 +35,27 @@ impl Client {
4335 .kill_on_drop(true)
4436 .spawn();
4537
46− // use std::io::ErrorKind;
47− let mut process = match process {
48− Ok(process) => process,
49− Err(err) => match err.kind() {
50− // ErrorKind::NotFound | ErrorKind::PermissionDenied => {
51− // return Err(Error::Other(err.into()))
52− // }
53− _kind => return Err(Error::Other(err.into())),
54− },
55− };
38+ let mut process = process?;
5639
5740 // TODO: do we need bufreader/writer here? or do we use async wrappers on unblock?
5841 let writer = BufWriter::new(process.stdin.take().expect("Failed to open stdin"));
5942 let reader = BufReader::new(process.stdout.take().expect("Failed to open stdout"));
6043 let stderr = BufReader::new(process.stderr.take().expect("Failed to open stderr"));
6144
62− let (incoming, outgoing) = Transport::start(reader, writer, stderr);
45+ let (server_rx, server_tx) = Transport::start(reader, writer, stderr);
6346
6447 let client = Self {
6548 _process: process,
66−
67− outgoing,
68− // incoming,
49+ server_tx,
6950 request_counter: AtomicU64::new(0),
70−
7151 capabilities: None,
72− // diagnostics: HashMap::new(),
7352 offset_encoding: OffsetEncoding::Utf8,
7453 };
7554
7655 // TODO: async client.initialize()
7756 // maybe use an arc<atomic> flag
7857
79− Ok((client, incoming))
58+ Ok((client, server_rx))
8059 }
8160
8261 fn next_request_id(&self) -> jsonrpc::Id {
@@ -106,7 +85,7 @@ impl Client {
10685 }
10786
10887 /// Execute a RPC request on the language server.
109− pub async fn request<R: lsp::request::Request>(&self, params: R::Params) -> Result<R::Result>
88+ async fn request<R: lsp::request::Request>(&self, params: R::Params) -> Result<R::Result>
11089 where
11190 R::Params: serde::Serialize,
11291 R::Result: core::fmt::Debug, // TODO: temporary
@@ -118,17 +97,20 @@ impl Client {
11897 }
11998
12099 /// Execute a RPC request on the language server.
121− pub fn call<R: lsp::request::Request>(
100+ fn call<R: lsp::request::Request>(
122101 &self,
123102 params: R::Params,
124103 ) -> impl Future<Output = Result<Value>>
125104 where
126105 R::Params: serde::Serialize,
127106 {
128− let outgoing = self.outgoing.clone();
107+ let server_tx = self.server_tx.clone();
129108 let id = self.next_request_id();
130109
131110 async move {
111+ use std::time::Duration;
112+ use tokio::time::timeout;
113+
132114 let params = serde_json::to_value(params)?;
133115
134116 let request = jsonrpc::MethodCall {
@@ -140,16 +122,13 @@ impl Client {
140122
141123 let (tx, mut rx) = channel::<Result<Value>>(1);
142124
143− outgoing
125+ server_tx
144126 .send(Payload::Request {
145127 chan: tx,
146128 value: request,
147129 })
148130 .map_err(|e| Error::Other(e.into()))?;
149131
150− use std::time::Duration;
151− use tokio::time::timeout;
152−
153132 timeout(Duration::from_secs(2), rx.recv())
154133 .await
155134 .map_err(|_| Error::Timeout)? // return Timeout
@@ -158,14 +137,14 @@ impl Client {
158137 }
159138
160139 /// Send a RPC notification to the language server.
161− pub fn notify<R: lsp::notification::Notification>(
140+ fn notify<R: lsp::notification::Notification>(
162141 &self,
163142 params: R::Params,
164143 ) -> impl Future<Output = Result<()>>
165144 where
166145 R::Params: serde::Serialize,
167146 {
168− let outgoing = self.outgoing.clone();
147+ let server_tx = self.server_tx.clone();
169148
170149 async move {
171150 let params = serde_json::to_value(params)?;
@@ -176,7 +155,7 @@ impl Client {
176155 params: Self::value_into_params(params),
177156 };
178157
179− outgoing
158+ server_tx
180159 .send(Payload::Notification(notification))
181160 .map_err(|e| Error::Other(e.into()))?;
182161
@@ -205,7 +184,7 @@ impl Client {
205184 }),
206185 };
207186
208− self.outgoing
187+ self.server_tx
209188 .send(Payload::Response(output))
210189 .map_err(|e| Error::Other(e.into()))?;
211190
@@ -216,7 +195,7 @@ impl Client {
216195 // General messages
217196 // -------------------------------------------------------------------------------------------
218197
219− pub async fn initialize(&mut self) -> Result<()> {
198+ pub(crate) async fn initialize(&mut self) -> Result<()> {
220199 // TODO: delay any requests that are triggered prior to initialize
221200 let root = find_root(None).and_then(|root| lsp::Url::from_file_path(root).ok());
222201
helix-lsp/src/lib.rs+10−17
@@ -1,28 +1,27 @@
11mod client;
22mod transport;
33
4−pub use jsonrpc_core as jsonrpc;
5−pub use lsp_types as lsp;
6−
74pub use client::Client;
5+pub use futures_executor::block_on;
6+pub use jsonrpc::Call;
7+pub use jsonrpc_core as jsonrpc;
88pub use lsp::{Position, Url};
9+pub use lsp_types as lsp;
910
10−pub type Result<T> = core::result::Result<T, Error>;
11−
11+use futures_util::stream::select_all::SelectAll;
1212use helix_core::syntax::LanguageConfiguration;
1313
14−use thiserror::Error;
15−
1614use std::{
1715 collections::{hash_map::Entry, HashMap},
1816 sync::Arc,
1917};
2018
2119use serde::{Deserialize, Serialize};
22−
20+use thiserror::Error;
2321use tokio_stream::wrappers::UnboundedReceiverStream;
2422
25−pub use futures_executor::block_on;
23+pub type Result<T> = core::result::Result<T, Error>;
24+type LanguageId = String;
2625
2726#[derive(Error, Debug)]
2827pub enum Error {
@@ -30,6 +29,8 @@ pub enum Error {
3029 Rpc(#[from] jsonrpc::Error),
3130 #[error("failed to parse: {0}")]
3231 Parse(#[from] serde_json::Error),
32+ #[error("IO Error: {0}")]
33+ IO(#[from] std::io::Error),
3334 #[error("request timed out")]
3435 Timeout,
3536 #[error("server closed the stream")]
@@ -126,8 +127,6 @@ pub mod util {
126127 }),
127128 )
128129 }
129−
130− // apply_insert_replace_edit
131130}
132131
133132#[derive(Debug, PartialEq, Clone)]
@@ -173,12 +172,6 @@ impl Notification {
173172 }
174173}
175174
176−pub use jsonrpc::Call;
177−
178−type LanguageId = String;
179−
180−use futures_util::stream::select_all::SelectAll;
181−
182175pub struct Registry {
183176 inner: HashMap<LanguageId, Arc<Client>>,
184177
helix-lsp/src/transport.rs+87−93
@@ -1,15 +1,9 @@
1−use std::collections::HashMap;
2−use std::io;
3−
4−use log::{error, info};
5−
6−use crate::Error;
7−
8−type Result<T> = core::result::Result<T, Error>;
9−
1+use crate::Result;
102use jsonrpc_core as jsonrpc;
3+use log::{error, info};
4+use serde::{Deserialize, Serialize};
115use serde_json::Value;
12−
6+use std::collections::HashMap;
137use tokio::{
148 io::{AsyncBufRead, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader, BufWriter},
159 process::{ChildStderr, ChildStdin, ChildStdout},
@@ -26,12 +20,11 @@ pub enum Payload {
2620 Response(jsonrpc::Output),
2721}
2822
29−use serde::{Deserialize, Serialize};
3023/// A type representing all possible values sent from the server to the client.
3124#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
3225#[serde(deny_unknown_fields)]
3326#[serde(untagged)]
34−enum Message {
27+enum ServerMessage {
3528 /// A regular JSON-RPC request output (single response).
3629 Output(jsonrpc::Output),
3730 /// A JSON-RPC request or notification.
@@ -39,34 +32,32 @@ enum Message {
3932}
4033
4134pub struct Transport {
42− incoming: UnboundedSender<jsonrpc::Call>,
43− outgoing: UnboundedReceiver<Payload>,
35+ client_tx: UnboundedSender<jsonrpc::Call>,
36+ client_rx: UnboundedReceiver<Payload>,
4437
4538 pending_requests: HashMap<jsonrpc::Id, Sender<Result<Value>>>,
46− headers: HashMap<String, String>,
4739
48− writer: BufWriter<ChildStdin>,
49− reader: BufReader<ChildStdout>,
50− stderr: BufReader<ChildStderr>,
40+ server_stdin: BufWriter<ChildStdin>,
41+ server_stdout: BufReader<ChildStdout>,
42+ server_stderr: BufReader<ChildStderr>,
5143}
5244
5345impl Transport {
5446 pub fn start(
55− reader: BufReader<ChildStdout>,
56− writer: BufWriter<ChildStdin>,
57− stderr: BufReader<ChildStderr>,
47+ server_stdout: BufReader<ChildStdout>,
48+ server_stdin: BufWriter<ChildStdin>,
49+ server_stderr: BufReader<ChildStderr>,
5850 ) -> (UnboundedReceiver<jsonrpc::Call>, UnboundedSender<Payload>) {
59− let (incoming, rx) = unbounded_channel();
60− let (tx, outgoing) = unbounded_channel();
51+ let (client_tx, rx) = unbounded_channel();
52+ let (tx, client_rx) = unbounded_channel();
6153
6254 let transport = Self {
63− reader,
64− writer,
65− stderr,
66− incoming,
67− outgoing,
55+ server_stdout,
56+ server_stdin,
57+ server_stderr,
58+ client_tx,
59+ client_rx,
6860 pending_requests: HashMap::default(),
69− headers: HashMap::default(),
7061 };
7162
7263 tokio::spawn(transport.duplex());
@@ -74,105 +65,104 @@ impl Transport {
7465 (rx, tx)
7566 }
7667
77− async fn recv(
68+ async fn recv_server_message(
7869 reader: &mut (impl AsyncBufRead + Unpin + Send),
79− headers: &mut HashMap<String, String>,
80− ) -> core::result::Result<Message, std::io::Error> {
81− // read headers
70+ buffer: &mut String,
71+ ) -> Result<ServerMessage> {
72+ let mut content_length = None;
8273 loop {
83− let mut header = String::new();
84− // detect pipe closed if 0
85− reader.read_line(&mut header).await?;
86− let header = header.trim();
74+ buffer.truncate(0);
75+ reader.read_line(buffer).await?;
76+ let header = buffer.trim();
8777
8878 if header.is_empty() {
8979 break;
9080 }
9181
92− let parts: Vec<&str> = header.split(": ").collect();
93− if parts.len() != 2 {
94− return Err(std::io::Error::new(
95− std::io::ErrorKind::Other,
96− "Failed to parse header",
97− ));
82+ let mut parts = header.split(": ");
83+
84+ match (parts.next(), parts.next(), parts.next()) {
85+ (Some("Content-Length"), Some(value), None) => {
86+ content_length = Some(value.parse().unwrap());
87+ }
88+ (Some(_), Some(_), None) => {}
89+ _ => {
90+ return Err(std::io::Error::new(
91+ std::io::ErrorKind::Other,
92+ "Failed to parse header",
93+ )
94+ .into());
95+ }
9896 }
99− headers.insert(parts[0].to_string(), parts[1].to_string());
10097 }
10198
102− // find content-length
103− let content_length = headers.get("Content-Length").unwrap().parse().unwrap();
99+ let content_length = content_length.unwrap();
104100
101+ //TODO: reuse vector
105102 let mut content = vec![0; content_length];
106103 reader.read_exact(&mut content).await?;
107104 let msg = String::from_utf8(content).unwrap();
108105
109− // read data
110−
111106 info!("<- {}", msg);
112107
113108 // try parsing as output (server response) or call (server request)
114− let output: serde_json::Result<Message> = serde_json::from_str(&msg);
109+ let output: serde_json::Result<ServerMessage> = serde_json::from_str(&msg);
115110
116111 Ok(output?)
117112 }
118113
119− async fn err(
114+ async fn recv_server_error(
120115 err: &mut (impl AsyncBufRead + Unpin + Send),
121− ) -> core::result::Result<(), std::io::Error> {
122− let mut line = String::new();
123− err.read_line(&mut line).await?;
124− error!("err <- {}", line);
116+ buffer: &mut String,
117+ ) -> Result<()> {
118+ buffer.truncate(0);
119+ err.read_line(buffer).await?;
120+ error!("err <- {}", buffer);
125121
126122 Ok(())
127123 }
128124
129− pub async fn send_payload(&mut self, payload: Payload) -> io::Result<()> {
130− match payload {
125+ async fn send_payload_to_server(&mut self, payload: Payload) -> Result<()> {
126+ //TODO: reuse string
127+ let json = match payload {
131128 Payload::Request { chan, value } => {
132129 self.pending_requests.insert(value.id.clone(), chan);
133−
134− let json = serde_json::to_string(&value)?;
135− self.send(json).await
136− }
137− Payload::Notification(value) => {
138− let json = serde_json::to_string(&value)?;
139− self.send(json).await
130+ serde_json::to_string(&value)?
140131 }
141− Payload::Response(error) => {
142− let json = serde_json::to_string(&error)?;
143− self.send(json).await
144− }
145− }
132+ Payload::Notification(value) => serde_json::to_string(&value)?,
133+ Payload::Response(error) => serde_json::to_string(&error)?,
134+ };
135+ self.send_string_to_server(json).await
146136 }
147137
148− pub async fn send(&mut self, request: String) -> io::Result<()> {
138+ async fn send_string_to_server(&mut self, request: String) -> Result<()> {
149139 info!("-> {}", request);
150140
151141 // send the headers
152− self.writer
142+ self.server_stdin
153143 .write_all(format!("Content-Length: {}\r\n\r\n", request.len()).as_bytes())
154144 .await?;
155145
156146 // send the body
157− self.writer.write_all(request.as_bytes()).await?;
147+ self.server_stdin.write_all(request.as_bytes()).await?;
158148
159− self.writer.flush().await?;
149+ self.server_stdin.flush().await?;
160150
161151 Ok(())
162152 }
163153
164− async fn recv_msg(&mut self, msg: Message) -> anyhow::Result<()> {
154+ async fn process_server_message(&mut self, msg: ServerMessage) -> Result<()> {
165155 match msg {
166− Message::Output(output) => self.recv_response(output).await?,
167− Message::Call(call) => {
168− self.incoming.send(call).unwrap();
156+ ServerMessage::Output(output) => self.process_request_response(output).await?,
157+ ServerMessage::Call(call) => {
158+ self.client_tx.send(call).unwrap();
169159 // let notification = Notification::parse(&method, params);
170160 }
171161 };
172162 Ok(())
173163 }
174164
175− async fn recv_response(&mut self, output: jsonrpc::Output) -> io::Result<()> {
165+ async fn process_request_response(&mut self, output: jsonrpc::Output) -> Result<()> {
176166 let (id, result) = match output {
177167 jsonrpc::Output::Success(jsonrpc::Success { id, result, .. }) => {
178168 info!("<- {}", result);
@@ -200,29 +190,33 @@ impl Transport {
200190 Ok(())
201191 }
202192
203− pub async fn duplex(mut self) {
193+ async fn duplex(mut self) {
194+ let mut recv_buffer = String::new();
195+ let mut err_buffer = String::new();
204196 loop {
205197 tokio::select! {
206198 // client -> server
207− msg = self.outgoing.recv() => {
208− if msg.is_none() {
209− break;
199+ msg = self.client_rx.recv() => {
200+ match msg {
201+ Some(msg) => {
202+ self.send_payload_to_server(msg).await.unwrap()
203+ },
204+ None => break
210205 }
211− let msg = msg.unwrap();
212−
213− self.send_payload(msg).await.unwrap();
214206 }
215− // server <- client
216− msg = Self::recv(&mut self.reader, &mut self.headers) => {
217− if msg.is_err() {
218− error!("err: <- {:?}", msg);
219− break;
207+ // server -> client
208+ msg = Self::recv_server_message(&mut self.server_stdout, &mut recv_buffer) => {
209+ match msg {
210+ Ok(msg) => {
211+ self.process_server_message(msg).await.unwrap();
212+ }
213+ Err(_) => {
214+ error!("err: <- {:?}", msg);
215+ break;
216+ },
220217 }
221− let msg = msg.unwrap();
222−
223− self.recv_msg(msg).await.unwrap();
224218 }
225− _msg = Self::err(&mut self.stderr) => {}
219+ _msg = Self::recv_server_error(&mut self.server_stderr, &mut err_buffer) => {}
226220 }
227221 }
228222 }