feat(lsp): use uv_spawn to check if server executable (#16430)

Previously, the built-in language server client checked if the first
argument of cmd was executable via vim.fn.executable. This ignores PATH
injected via cmd_env. Instead, we now start the client via uv.spawn, and
handle the failure mode, reporting the error back to the user.

Co-authored-by: Mathias Fußenegger <mfussenegger@users.noreply.github.com>
This commit is contained in:
Michael Lingelbach 2021-11-25 07:54:45 -05:00 committed by GitHub
parent 6ea5e80393
commit 1a60580925
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 11 additions and 3 deletions

View File

@ -790,6 +790,9 @@ function lsp.start_client(config)
env = config.cmd_env; env = config.cmd_env;
}) })
-- Return nil if client fails to start
if not rpc then return end
local client = { local client = {
id = client_id; id = client_id;
name = name; name = name;

View File

@ -264,8 +264,6 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
if extra_spawn_params and extra_spawn_params.cwd then if extra_spawn_params and extra_spawn_params.cwd then
assert(is_dir(extra_spawn_params.cwd), "cwd must be a directory") assert(is_dir(extra_spawn_params.cwd), "cwd must be a directory")
elseif not (vim.fn.executable(cmd) == 1) then
error(string.format("The given command %q is not executable.", cmd))
end end
if dispatchers then if dispatchers then
local user_dispatchers = dispatchers local user_dispatchers = dispatchers
@ -325,7 +323,14 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end end
handle, pid = uv.spawn(cmd, spawn_params, onexit) handle, pid = uv.spawn(cmd, spawn_params, onexit)
if handle == nil then if handle == nil then
error(string.format("start `%s` failed: %s", cmd, pid)) local msg = string.format("Spawning language server with cmd: `%s` failed", cmd)
if string.match(pid, "ENOENT") then
msg = msg .. ". The language server is either not installed, missing from PATH, or not executable."
else
msg = msg .. string.format(" with error message: %s", pid)
end
vim.notify(msg, vim.log.levels.ERROR)
return
end end
end end