Skip to content

Commit

Permalink
feat: lazily require modules on ad-hoc basis (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
williamboman committed Jul 22, 2022
1 parent 051f164 commit 6a948db
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 109 deletions.
33 changes: 33 additions & 0 deletions lua/mason-lspconfig/ensure_installed.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
local settings = require "mason-lspconfig.settings"

---@param lspconfig_server_name string
local function resolve_package(lspconfig_server_name)
local registry = require "mason-registry"
local Optional = require "mason-core.optional"
local server_mapping = require "mason-lspconfig.mappings.server"

return Optional.of_nilable(server_mapping.lspconfig_to_package[lspconfig_server_name]):map(function(package_name)
local ok, pkg = pcall(registry.get_package, package_name)
if ok then
return pkg
end
end)
end

return function()
for _, server_identifier in ipairs(settings.current.ensure_installed) do
local Package = require "mason-core.package"

local server_name, version = Package.Parse(server_identifier)
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
125 changes: 16 additions & 109 deletions lua/mason-lspconfig/init.lua
Original file line number Diff line number Diff line change
@@ -1,130 +1,33 @@
local log = require "mason-core.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.mappings.server"
local path = require "mason-core.path"
local registry = require "mason-registry"
local notify = require "mason-core.notify"
local platform = require "mason-core.platform"

local M = {}

---@param lspconfig_server_name string
local function resolve_package(lspconfig_server_name)
return Optional.of_nilable(server_mapping.lspconfig_to_package[lspconfig_server_name]):map(function(package_name)
local ok, pkg = pcall(registry.get_package, package_name)
if ok then
return pkg
end
end)
end

---@param lspconfig_server_name string
local function resolve_server_config_factory(lspconfig_server_name)
local ok, server_config = pcall(require, ("mason-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"
local win_exepath_compat = platform.is.win and require "mason-lspconfig.win-exepath-compat"

util.on_setup = util.add_hook_before(util.on_setup, function(config)
local pkg_name = server_mapping.lspconfig_to_package[config.name]
if not pkg_name then
return
end

if registry.is_installed(pkg_name) then
resolve_server_config_factory(config.name):if_present(function(config_factory)
merge_in_place(config, config_factory(path.package_prefix(pkg_name), config))
if win_exepath_compat and win_exepath_compat[config.name] and config.cmd and config.cmd[1] then
local exepath = vim.fn.exepath(config.cmd[1])
if exepath ~= "" then
config.cmd[1] = exepath
else
log.error("Failed to expand cmd path", config.name, config.cmd)
end
end
end)
elseif should_auto_install(config.name) then
local pkg = registry.get_package(pkg_name)
pkg:install():once("closed", function()
if pkg:is_installed() then
-- reload config
require("lspconfig")[config.name].setup(config)
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)
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)
local settings = require "mason-lspconfig.settings"

if config then
settings.set(config)
end

setup_lspconfig_hook()
ensure_installed()
require "mason-lspconfig.lspconfig_hook"()

if #settings.current.ensure_installed > 0 then
require "mason-lspconfig.ensure_installed"()
end

require "mason-lspconfig.api.command"
end

---See `:h mason-lspconfig.setup_handlers()`
---@param handlers table<string, fun(server_name: string)>
function M.setup_handlers(handlers)
local Optional = require "mason-core.optional"
local server_mapping = require "mason-lspconfig.mappings.server"
local registry = require "mason-registry"
local notify = require "mason-core.notify"

local default_handler = Optional.of_nilable(handlers[1])

_.each(function(handler)
Expand Down Expand Up @@ -166,6 +69,10 @@ end

---@return string[]
function M.get_installed_servers()
local Optional = require "mason-core.optional"
local registry = require "mason-registry"
local server_mapping = require "mason-lspconfig.mappings.server"

return _.filter_map(function(pkg_name)
return Optional.of_nilable(server_mapping.package_to_lspconfig[pkg_name])
end, registry.get_installed_package_names())
Expand Down
83 changes: 83 additions & 0 deletions lua/mason-lspconfig/lspconfig_hook.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
local log = require "mason-core.log"
local _ = require "mason-core.functional"
local path = require "mason-core.path"
local platform = require "mason-core.platform"

local memoized_set = _.memoize(_.set_of)

---@param server_name string
local function should_auto_install(server_name)
local settings = require "mason-lspconfig.settings"

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

---@param lspconfig_server_name string
local function resolve_server_config_factory(lspconfig_server_name)
local Optional = require "mason-core.optional"

local ok, server_config = pcall(require, ("mason-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

return function()
local util = require "lspconfig.util"
local win_exepath_compat = platform.is.win and require "mason-lspconfig.win-exepath-compat"
local server_mapping = require "mason-lspconfig.mappings.server"
local registry = require "mason-registry"

util.on_setup = util.add_hook_before(util.on_setup, function(config)
local pkg_name = server_mapping.lspconfig_to_package[config.name]
if not pkg_name then
return
end

if registry.is_installed(pkg_name) then
resolve_server_config_factory(config.name):if_present(function(config_factory)
merge_in_place(config, config_factory(path.package_prefix(pkg_name), config))
if win_exepath_compat and win_exepath_compat[config.name] and config.cmd and config.cmd[1] then
local exepath = vim.fn.exepath(config.cmd[1])
if exepath ~= "" then
config.cmd[1] = exepath
else
log.error("Failed to expand cmd path", config.name, config.cmd)
end
end
end)
elseif should_auto_install(config.name) then
local pkg = registry.get_package(pkg_name)
pkg:install():once("closed", function()
if pkg:is_installed() then
-- reload config
require("lspconfig")[config.name].setup(config)
end
end)
end
end)
end

0 comments on commit 6a948db

Please sign in to comment.