mirror of
https://github.com/neovim/neovim
synced 2025-07-16 01:01:49 +00:00
fix(lsp): handle non-existent configs in lsp.config/enable
This commit is contained in:
committed by
Lewis Russell
parent
c63e794b10
commit
ed07167261
@ -374,26 +374,31 @@ lsp.config = setmetatable({ _configs = {} }, {
|
||||
validate('name', name, 'string')
|
||||
|
||||
local rconfig = lsp._enabled_configs[name] or {}
|
||||
self._configs[name] = self._configs[name] or {}
|
||||
|
||||
if not rconfig.resolved_config then
|
||||
-- Resolve configs from lsp/*.lua
|
||||
-- Calls to vim.lsp.config in lsp/* have a lower precedence than calls from other sites.
|
||||
local rtp_config = {} ---@type vim.lsp.Config
|
||||
local rtp_config --- @type vim.lsp.Config?
|
||||
for _, v in ipairs(api.nvim_get_runtime_file(('lsp/%s.lua'):format(name), true)) do
|
||||
local config = assert(loadfile(v))() ---@type any?
|
||||
if type(config) == 'table' then
|
||||
rtp_config = vim.tbl_deep_extend('force', rtp_config, config)
|
||||
--- @type vim.lsp.Config?
|
||||
rtp_config = vim.tbl_deep_extend('force', rtp_config or {}, config)
|
||||
else
|
||||
log.warn(string.format('%s does not return a table, ignoring', v))
|
||||
end
|
||||
end
|
||||
|
||||
if not rtp_config and not self._configs[name] then
|
||||
log.warn(string.format('%s does not have a configuration', name))
|
||||
return
|
||||
end
|
||||
|
||||
rconfig.resolved_config = vim.tbl_deep_extend(
|
||||
'force',
|
||||
lsp.config._configs['*'] or {},
|
||||
rtp_config,
|
||||
lsp.config._configs[name] or {}
|
||||
rtp_config or {},
|
||||
self._configs[name] or {}
|
||||
)
|
||||
rconfig.resolved_config.name = name
|
||||
end
|
||||
@ -424,6 +429,50 @@ lsp.config = setmetatable({ _configs = {} }, {
|
||||
|
||||
local lsp_enable_autocmd_id --- @type integer?
|
||||
|
||||
local function validate_cmd(v)
|
||||
if type(v) == 'table' then
|
||||
if vim.fn.executable(v[1]) == 0 then
|
||||
return false, v[1] .. ' is not executable'
|
||||
end
|
||||
return true
|
||||
end
|
||||
return type(v) == 'function'
|
||||
end
|
||||
|
||||
--- @param config vim.lsp.Config
|
||||
local function validate_config(config)
|
||||
validate('cmd', config.cmd, validate_cmd, 'expected function or table with executable command')
|
||||
validate('reuse_client', config.reuse_client, 'function', true)
|
||||
validate('filetypes', config.filetypes, 'table', true)
|
||||
end
|
||||
|
||||
--- @param bufnr integer
|
||||
--- @param name string
|
||||
--- @param config vim.lsp.Config
|
||||
local function can_start(bufnr, name, config)
|
||||
local config_ok, err = pcall(validate_config, config)
|
||||
if not config_ok then
|
||||
log.error(('cannot start %s due to config error: %s'):format(name, err))
|
||||
return false
|
||||
end
|
||||
|
||||
if config.filetypes and not vim.tbl_contains(config.filetypes, vim.bo[bufnr].filetype) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- @param bufnr integer
|
||||
--- @param config vim.lsp.Config
|
||||
local function start_config(bufnr, config)
|
||||
return vim.lsp.start(config, {
|
||||
bufnr = bufnr,
|
||||
reuse_client = config.reuse_client,
|
||||
_root_markers = config.root_markers,
|
||||
})
|
||||
end
|
||||
|
||||
--- @param bufnr integer
|
||||
local function lsp_enable_callback(bufnr)
|
||||
-- Only ever attach to buffers that represent an actual file.
|
||||
@ -431,32 +480,9 @@ local function lsp_enable_callback(bufnr)
|
||||
return
|
||||
end
|
||||
|
||||
--- @param config vim.lsp.Config
|
||||
local function can_start(config)
|
||||
if config.filetypes and not vim.tbl_contains(config.filetypes, vim.bo[bufnr].filetype) then
|
||||
return false
|
||||
elseif type(config.cmd) == 'table' and vim.fn.executable(config.cmd[1]) == 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- @param config vim.lsp.Config
|
||||
local function start(config)
|
||||
return vim.lsp.start(config, {
|
||||
bufnr = bufnr,
|
||||
reuse_client = config.reuse_client,
|
||||
_root_markers = config.root_markers,
|
||||
})
|
||||
end
|
||||
|
||||
for name in vim.spairs(lsp._enabled_configs) do
|
||||
local config = lsp.config[name]
|
||||
validate('cmd', config.cmd, { 'function', 'table' })
|
||||
validate('cmd', config.reuse_client, 'function', true)
|
||||
|
||||
if can_start(config) then
|
||||
if config and can_start(bufnr, name, config) then
|
||||
-- Deepcopy config so changes done in the client
|
||||
-- do not propagate back to the enabled configs.
|
||||
config = vim.deepcopy(config)
|
||||
@ -466,11 +492,11 @@ local function lsp_enable_callback(bufnr)
|
||||
config.root_dir(bufnr, function(root_dir)
|
||||
config.root_dir = root_dir
|
||||
vim.schedule(function()
|
||||
start(config)
|
||||
start_config(bufnr, config)
|
||||
end)
|
||||
end)
|
||||
else
|
||||
start(config)
|
||||
start_config(bufnr, config)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user