neoconf.nvim/lua/neoconf/plugins/lspconfig.lua

110 lines
3.7 KiB
Lua

local Config = require("neoconf.config")
local Settings = require("neoconf.settings")
local Util = require("neoconf.util")
---@type SettingsPlugin
local M = {}
function M.on_schema(schema)
schema:set("lspconfig", {
description = "lsp server settings for lspconfig",
})
for name, s in pairs(require("neoconf.build.schemas").get_schemas()) do
if Config.options.plugins.jsonls.configured_servers_only == false or Util.has_lspconfig(name) then
schema:set("lspconfig." .. name, {
anyOf = {
{ const = "false", description = "Set to false to disable this lsp server" },
{
["$ref"] = vim.uri_from_fname(s.settings_file),
},
},
})
end
end
end
function M.setup()
local settings_root = Util.root_pattern(unpack(Util.file_patterns({ global = false })))
Util.on_config({
name = "settings/plugins/lspconfig",
on_config = M.on_new_config,
root_dir = settings_root,
})
end
function M.on_new_config(config, root_dir, original_config)
local options = Config.get({ file = root_dir })
if not options.plugins.lspconfig.enabled then
return
end
-- backup original lsp config
config.original_settings = vim.deepcopy(original_config.settings or {})
root_dir = require("neoconf.workspace").find_root({ file = root_dir })
local enabled = Settings.get_local(root_dir):get("lspconfig." .. config.name, { expand = true })
if enabled == false then
config.enabled = false
return
end
config.settings = Util.merge(
config.settings,
-- merge in global lsp settings
Settings.get_global():get("lspconfig." .. config.name, { expand = true }) or {},
options.import.coc and Settings.get_global():get("coc") or {},
options.import.nlsp and Settings.get_global():get("nlsp." .. config.name) or {},
-- merge in local lsp settings
options.import.vscode and Settings.get_local(root_dir):get("vscode") or {},
options.import.coc and Settings.get_local(root_dir):get("coc") or {},
options.import.nlsp and Settings.get_local(root_dir):get("nlsp." .. config.name) or {},
Settings.get_local(root_dir):get("lspconfig." .. config.name, { expand = true }) or {}
)
end
function M.on_update(fname)
local is_global = Util.is_global(fname)
local clients = vim.lsp.get_clients()
for _, client in ipairs(clients) do
local settings_root = require("neoconf.workspace").find_root({ file = client.config.root_dir })
-- reload this client if the global file changed, or its root dir equals the local one
if is_global or Util.has_file(settings_root, client.config.root_dir) then
local old_settings = vim.deepcopy(client.config.settings)
-- retrieve new settings only
client.config.settings = vim.deepcopy(client.config.original_settings or {})
local document_config = Util.has_lspconfig(client.name) and require("lspconfig")[client.name].document_config
-- re-apply config from any other plugins that were overriding on_new_config
if document_config and document_config.on_new_config then
pcall(document_config.on_new_config, client.config, client.config.root_dir)
end
if client.config.on_new_config then
pcall(client.config.on_new_config, client.config, client.config.root_dir)
end
-- only send update when confiuration actually changed
if not vim.deep_equal(old_settings, client.config.settings) then
-- notify the lsp server of thr new config
local ok = pcall(client.notify, "workspace/didChangeConfiguration", {
settings = client.config.settings,
})
if ok then
Util.info("Reloaded settings for " .. client.name)
else
Util.error("Reloading settings failed for " .. client.name)
end
end
end
end
end
return M