restart lsp if crashed

This commit is contained in:
Dongdong Zhou 2022-03-03 12:41:02 +00:00
parent 963456830c
commit d84062aaa4
1 changed files with 1025 additions and 998 deletions

View File

@ -2,7 +2,7 @@
collections::HashMap,
io::BufRead,
io::{BufReader, BufWriter, Write},
process::{self, Child, Command, Stdio},
process::{self, Child, ChildStdout, Command, Stdio},
sync::{mpsc::channel, Arc},
thread,
time::Duration,
@ -52,8 +52,10 @@ pub struct LspState {
pub is_initialized: bool,
}
#[derive(Clone)]
pub struct LspClient {
language_id: String,
exec_path: String,
options: Option<Value>,
state: Arc<Mutex<LspState>>,
dispatcher: Dispatcher,
@ -339,20 +341,13 @@ pub fn new(
options: Option<Value>,
dispatcher: Dispatcher,
) -> Arc<LspClient> {
let mut process = Command::new(exec_path);
#[cfg(target_os = "windows")]
let mut process = process.creation_flags(0x08000000);
let mut process = process
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("Error Occurred");
let mut process = Self::process(exec_path);
let writer = Box::new(BufWriter::new(process.stdin.take().unwrap()));
let stdout = process.stdout.take().unwrap();
let lsp_client = Arc::new(LspClient {
dispatcher,
exec_path: exec_path.to_string(),
language_id,
options,
state: Arc::new(Mutex::new(LspState {
@ -366,7 +361,14 @@ pub fn new(
})),
});
let local_lsp_client = lsp_client.clone();
lsp_client.handle_stdout(stdout);
lsp_client.initialize();
lsp_client
}
fn handle_stdout(&self, stdout: ChildStdout) {
let local_lsp_client = self.clone();
thread::spawn(move || {
let mut reader = Box::new(BufReader::new(stdout));
loop {
@ -375,15 +377,42 @@ pub fn new(
local_lsp_client.handle_message(message_str.as_ref());
}
Err(err) => {
local_lsp_client.stop();
local_lsp_client.reload();
return;
}
};
}
});
}
lsp_client.initialize();
fn process(exec_path: &str) -> Child {
let mut process = Command::new(exec_path);
#[cfg(target_os = "windows")]
let mut process = process.creation_flags(0x08000000);
process
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("Error Occurred")
}
lsp_client
fn reload(&self) {
let mut process = Self::process(&self.exec_path);
let writer = Box::new(BufWriter::new(process.stdin.take().unwrap()));
let stdout = process.stdout.take().unwrap();
let mut state = self.state.lock();
state.next_id = 0;
state.pending.clear();
state.opened_documents.clear();
state.server_capabilities = None;
state.is_initialized = false;
state.writer = writer;
state.process = process;
self.handle_stdout(stdout);
self.initialize();
}
fn stop(&self) {
@ -469,13 +498,11 @@ pub fn handle_response(&self, id: u64, result: Result<Value>) {
callback.call(self, result);
}
pub fn write(&self, msg: &str) {
pub fn write(&self, msg: &str) -> Result<()> {
let mut state = self.state.lock();
state
.writer
.write_all(msg.as_bytes())
.expect("error writing to stdin");
state.writer.flush().expect("error flushing child stdin");
state.writer.write_all(msg.as_bytes())?;
state.writer.flush()?;
Ok(())
}
fn send_rpc(&self, value: &Value) {