mirror of https://github.com/lapce/lapce.git
restart lsp if crashed
This commit is contained in:
parent
963456830c
commit
d84062aaa4
|
@ -2,7 +2,7 @@
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io::BufRead,
|
io::BufRead,
|
||||||
io::{BufReader, BufWriter, Write},
|
io::{BufReader, BufWriter, Write},
|
||||||
process::{self, Child, Command, Stdio},
|
process::{self, Child, ChildStdout, Command, Stdio},
|
||||||
sync::{mpsc::channel, Arc},
|
sync::{mpsc::channel, Arc},
|
||||||
thread,
|
thread,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
|
@ -52,8 +52,10 @@ pub struct LspState {
|
||||||
pub is_initialized: bool,
|
pub is_initialized: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct LspClient {
|
pub struct LspClient {
|
||||||
language_id: String,
|
language_id: String,
|
||||||
|
exec_path: String,
|
||||||
options: Option<Value>,
|
options: Option<Value>,
|
||||||
state: Arc<Mutex<LspState>>,
|
state: Arc<Mutex<LspState>>,
|
||||||
dispatcher: Dispatcher,
|
dispatcher: Dispatcher,
|
||||||
|
@ -339,20 +341,13 @@ pub fn new(
|
||||||
options: Option<Value>,
|
options: Option<Value>,
|
||||||
dispatcher: Dispatcher,
|
dispatcher: Dispatcher,
|
||||||
) -> Arc<LspClient> {
|
) -> Arc<LspClient> {
|
||||||
let mut process = Command::new(exec_path);
|
let mut process = Self::process(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 writer = Box::new(BufWriter::new(process.stdin.take().unwrap()));
|
let writer = Box::new(BufWriter::new(process.stdin.take().unwrap()));
|
||||||
let stdout = process.stdout.take().unwrap();
|
let stdout = process.stdout.take().unwrap();
|
||||||
|
|
||||||
let lsp_client = Arc::new(LspClient {
|
let lsp_client = Arc::new(LspClient {
|
||||||
dispatcher,
|
dispatcher,
|
||||||
|
exec_path: exec_path.to_string(),
|
||||||
language_id,
|
language_id,
|
||||||
options,
|
options,
|
||||||
state: Arc::new(Mutex::new(LspState {
|
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 || {
|
thread::spawn(move || {
|
||||||
let mut reader = Box::new(BufReader::new(stdout));
|
let mut reader = Box::new(BufReader::new(stdout));
|
||||||
loop {
|
loop {
|
||||||
|
@ -375,15 +377,42 @@ pub fn new(
|
||||||
local_lsp_client.handle_message(message_str.as_ref());
|
local_lsp_client.handle_message(message_str.as_ref());
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
local_lsp_client.stop();
|
||||||
|
local_lsp_client.reload();
|
||||||
return;
|
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) {
|
fn stop(&self) {
|
||||||
|
@ -469,13 +498,11 @@ pub fn handle_response(&self, id: u64, result: Result<Value>) {
|
||||||
callback.call(self, result);
|
callback.call(self, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self, msg: &str) {
|
pub fn write(&self, msg: &str) -> Result<()> {
|
||||||
let mut state = self.state.lock();
|
let mut state = self.state.lock();
|
||||||
state
|
state.writer.write_all(msg.as_bytes())?;
|
||||||
.writer
|
state.writer.flush()?;
|
||||||
.write_all(msg.as_bytes())
|
Ok(())
|
||||||
.expect("error writing to stdin");
|
|
||||||
state.writer.flush().expect("error flushing child stdin");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_rpc(&self, value: &Value) {
|
fn send_rpc(&self, value: &Value) {
|
||||||
|
|
Loading…
Reference in New Issue