aboutsummaryrefslogtreecommitdiffstats
path: root/lua/mason-lspconfig/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/mason-lspconfig/init.lua')
-rw-r--r--lua/mason-lspconfig/init.lua139
1 files changed, 139 insertions, 0 deletions
diff --git a/lua/mason-lspconfig/init.lua b/lua/mason-lspconfig/init.lua
new file mode 100644
index 00000000..850c1069
--- /dev/null
+++ b/lua/mason-lspconfig/init.lua
@@ -0,0 +1,139 @@
+local log = require "mason.log"
+local Package = require "mason.core.package"
+local Optional = require "mason.core.optional"
+local _ = require "mason.core.functional"
+local settings = require "mason-lspconfig.settings"
+local server_mapping = require "mason-lspconfig.server-mapping"
+
+local M = {}
+
+---@param lspconfig_server_name string
+function M.resolve_package(lspconfig_server_name)
+ return Optional.of_nilable(server_mapping.lspconfig_to_package[lspconfig_server_name]):map(function(package_name)
+ local ok, package = pcall(require, ("mason.packages.%s"):format(package_name))
+ if ok then
+ return package
+ end
+ end)
+end
+
+---@param lspconfig_server_name string
+function M.resolve_server_config_factory(lspconfig_server_name)
+ local ok, server_config = pcall(
+ require,
+ ("mason.adapters.lspconfig.server_configurations.%s"):format(lspconfig_server_name)
+ )
+ if ok then
+ return Optional.of(server_config)
+ end
+ return Optional.empty()
+end
+
+---@param t1 table
+---@param t2 table
+local function merge_in_place(t1, t2)
+ for k, v in pairs(t2) do
+ if type(v) == "table" then
+ if type(t1[k]) == "table" and not vim.tbl_islist(t1[k]) then
+ merge_in_place(t1[k], v)
+ else
+ t1[k] = v
+ end
+ else
+ t1[k] = v
+ end
+ end
+ return t1
+end
+
+local memoized_set = _.memoize(_.set_of)
+
+---@param server_name string
+local function should_auto_install(server_name)
+ if settings.current.automatic_installation == true then
+ return true
+ end
+ if type(settings.current.automatic_installation) == "table" then
+ return not memoized_set(settings.current.automatic_installation.exclude)[server_name]
+ end
+ return false
+end
+
+local function setup_lspconfig_hook()
+ local util = require "lspconfig.util"
+ util.on_setup = util.add_hook_before(util.on_setup, function(config)
+ M.resolve_package(config.name):if_present(
+ ---@param pkg Package
+ function(pkg)
+ if pkg:is_installed() then
+ M.resolve_server_config_factory(config.name):if_present(function(config_factory)
+ merge_in_place(config, config_factory(pkg:get_install_path()))
+ end)
+ else
+ if should_auto_install(config.name) then
+ pkg:install()
+ end
+ end
+ end
+ )
+ end)
+end
+
+local function ensure_installed()
+ for _, server_identifier in ipairs(settings.current.ensure_installed) do
+ local server_name, version = Package.Parse(server_identifier)
+ M.resolve_package(server_name):if_present(
+ ---@param pkg Package
+ function(pkg)
+ if not pkg:is_installed() then
+ pkg:install {
+ version = version,
+ }
+ end
+ end
+ )
+ end
+end
+
+---@param config MasonLspconfigSettings | nil
+function M.setup(config)
+ if config then
+ settings.set(config)
+ end
+
+ setup_lspconfig_hook()
+ ensure_installed()
+end
+
+---@param handlers table<string, fun(server_name: string)>
+function M.setup_handlers(handlers)
+ local default_handler = Optional.of_nilable(handlers[1])
+ local indexer = require "mason.core.package.indexer"
+
+ ---@param pkg_name string
+ local function get_server_name(pkg_name)
+ return Optional.of_nilable(server_mapping.package_to_lspconfig[pkg_name])
+ end
+
+ local function call_handler(server_name)
+ log.fmt_trace("Checking handler for %s", server_name)
+ Optional.of_nilable(handlers[server_name]):or_(_.always(default_handler)):if_present(function(handler)
+ log.fmt_trace("Calling handler for %s", server_name)
+ local ok, err = pcall(handler, server_name)
+ if not ok then
+ vim.notify(err, vim.log.levels.ERROR)
+ end
+ end)
+ end
+
+ local installed_servers = _.filter_map(get_server_name, indexer.get_installed_package_names())
+ _.each(call_handler, installed_servers)
+ indexer:on(
+ "package:install:success",
+ vim.schedule_wrap(function(pkg)
+ get_server_name(pkg.name):if_present(call_handler)
+ end)
+ )
+end
+
+return M