lsp: Gracefully fail if binary doesn't exist.

This commit is contained in:
Blaž Hrastnik 2021-04-07 13:38:24 +09:00
parent 9dfd6f6bbc
commit 5aed1f3c00
2 changed files with 22 additions and 10 deletions

View File

@ -34,15 +34,25 @@ pub struct Client {
} }
impl Client { impl Client {
pub fn start(ex: &Executor, cmd: &str, args: &[String]) -> (Self, Receiver<Call>) { pub fn start(ex: &Executor, cmd: &str, args: &[String]) -> Result<(Self, Receiver<Call>)> {
let mut process = Command::new(cmd) // smol makes sure the process is reaped on drop, but using kill_on_drop(true) maybe?
let process = Command::new(cmd)
.args(args) .args(args)
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.spawn() .spawn();
.expect("Failed to start language server");
// smol makes sure the process is reaped on drop, but using kill_on_drop(true) maybe? // use std::io::ErrorKind;
let mut process = match process {
Ok(process) => process,
Err(err) => match err.kind() {
// ErrorKind::NotFound | ErrorKind::PermissionDenied => {
// return Err(Error::Other(err.into()))
// }
_kind => return Err(Error::Other(err.into())),
},
};
// TODO: do we need bufreader/writer here? or do we use async wrappers on unblock? // TODO: do we need bufreader/writer here? or do we use async wrappers on unblock?
let writer = BufWriter::new(process.stdin.take().expect("Failed to open stdin")); let writer = BufWriter::new(process.stdin.take().expect("Failed to open stdin"));
@ -65,7 +75,7 @@ pub fn start(ex: &Executor, cmd: &str, args: &[String]) -> (Self, Receiver<Call>
// TODO: async client.initialize() // TODO: async client.initialize()
// maybe use an arc<atomic> flag // maybe use an arc<atomic> flag
(client, incoming) Ok((client, incoming))
} }
fn next_request_id(&self) -> jsonrpc::Id { fn next_request_id(&self) -> jsonrpc::Id {

View File

@ -104,7 +104,7 @@ pub fn parse(method: &str, params: jsonrpc::Params) -> Notification {
use smol::channel::Receiver; use smol::channel::Receiver;
pub struct Registry { pub struct Registry {
inner: HashMap<LanguageId, Arc<Client>>, inner: HashMap<LanguageId, Option<Arc<Client>>>,
pub incoming: SelectAll<Receiver<Call>>, pub incoming: SelectAll<Receiver<Call>>,
} }
@ -140,17 +140,19 @@ pub fn get(
// TODO: lookup defaults for id (name, args) // TODO: lookup defaults for id (name, args)
// initialize a new client // initialize a new client
let (mut client, incoming) = Client::start(&ex, &config.command, &config.args); let (mut client, incoming) =
Client::start(&ex, &config.command, &config.args).ok()?;
// TODO: run this async without blocking // TODO: run this async without blocking
smol::block_on(client.initialize()).unwrap(); smol::block_on(client.initialize()).unwrap();
s_incoming.push(incoming); s_incoming.push(incoming);
Arc::new(client) Some(Arc::new(client))
}) })
.clone(); .clone();
return Some(language_server); return language_server;
} }
None None