Skip to content

Commit 6f5ceac

Browse files
committed
feat: add the ability to hotpatch mason-lspconfig.nvim with more lsp/package mappings
1 parent 5a297cf commit 6f5ceac

File tree

3 files changed

+109
-6
lines changed

3 files changed

+109
-6
lines changed

README.md

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,21 @@ local opts = {
195195
},
196196
},
197197
},
198+
-- Extra configuration for the `mason-lspconfig.nvim` plugin
199+
mason_lspconfig = {
200+
-- Allow registering more Mason packages as language servers for autodetection/setup
201+
servers = {
202+
-- The key is the lspconfig server name to register a package for
203+
nextflow_ls = {
204+
-- The Mason package name to register to the language server
205+
package = "nextflow-language-server",
206+
-- The filetypes that apply to the package and language server
207+
filetypes = { "nextflow" },
208+
-- (Optional) any default configuration changes that may need to happen (can be a table or a function that returns a table)
209+
config = { cmd = { "nextflow-language-server" } }
210+
}
211+
}
212+
}
198213
-- A list like table of servers that should be setup, useful for enabling language servers not installed with Mason.
199214
servers = { "dartls" },
200215
-- A custom `on_attach` function to be run after the default `on_attach` function, takes two parameters `client` and `bufnr` (`:h lspconfig-setup`)
@@ -231,12 +246,16 @@ local opts = {
231246
{
232247
"williamboman/mason-lspconfig.nvim", -- MUST be set up before `nvim-lspconfig`
233248
dependencies = { "williamboman/mason.nvim" },
234-
opts = function()
235-
return {
236-
-- use AstroLSP setup for mason-lspconfig
237-
handlers = { function(server) require("astrolsp").lsp_setup(server) end },
238-
}
239-
end,
249+
opts = {
250+
-- use AstroLSP setup for mason-lspconfig
251+
handlers = { function(server) require("astrolsp").lsp_setup(server) end },
252+
},
253+
config = function(_, opts)
254+
-- Optionally tell AstroLSP to register new language servers before calling the `setup` function
255+
-- this enables the `mason-lspconfig.servers` option in the AstroLSP configuration
256+
require("astrolsp.mason-lspconfig").register_servers()
257+
require("mason-lspconfig").setup(opts)
258+
end
240259
},
241260
},
242261
config = function()

lua/astrolsp/config.lua

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@
5959
---@field hover vim.lsp.buf.hover.Opts? control the default options for `vim.lsp.buf.hover()` (`:h vim.lsp.buf.hover.Opts`)
6060
---@field signature_help vim.lsp.buf.signature_help.Opts? control the default options for `vim.lsp.buf.signature_help()` (`:h vim.lsp.buf.signature_help.Opts`)
6161

62+
---@class AstroLSPMasonLspconfigServer
63+
---@field public package string the Mason package name
64+
---@field filetypes string|string[] the filetype(s) that the server applies to
65+
---@field config? table|(fun(): table) extensions tothe default language server configuration
66+
67+
---@alias AstroLSPMasonLspconfigServers { [string]: AstroLSPMasonLspconfigServer }
68+
69+
---@class AstroLSPMasonLspconfigOpts
70+
---@field servers AstroLSPMasonLspconfigServers? a table of servers to register with mason-lspconfig.nvim
71+
6272
---@class AstroLSPOpts
6373
---Configuration of auto commands
6474
---The key into the table is the group name for the auto commands (`:h augroup`) and the value
@@ -284,6 +294,21 @@
284294
---}
285295
---```
286296
---@field mappings AstroLSPMappings?
297+
---Extra options for the `mason-lspconfig.nvim` plugin such as registering new packages as language servers.
298+
---Example:
299+
--
300+
---```lua
301+
---mason_lspconfig = {
302+
--- servers = {
303+
--- nextflow_ls = {
304+
--- package = "nextflow-language-server",
305+
--- filetypes = "nextflow",
306+
--- config = { cmd = { "nextflow-language-server" } }
307+
--- }
308+
--- }
309+
---}
310+
---```
311+
---@field mason_lspconfig AstroLSPMasonLspconfigOpts?
287312
---A list like table of servers that should be setup, useful for enabling language servers not installed with Mason.
288313
---Example:
289314
--
@@ -324,6 +349,7 @@ local M = {
324349
handlers = {},
325350
lsp_handlers = {},
326351
mappings = {},
352+
mason_lspconfig = {},
327353
servers = {},
328354
on_attach = nil,
329355
}

lua/astrolsp/mason-lspconfig.lua

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---Utilities for working with mason-lspconfig.nvim
2+
---
3+
---This module can be loaded with `local astrolsp_mason_lspconfig = require "astrolsp.mason-lspconfig"`
4+
---
5+
---copyright 2025
6+
---license GNU General Public License v3.0
7+
---@class astrolsp.mason-lspconfig
8+
local M = {}
9+
10+
local function resolve_config() return require("astrolsp").config.mason_lspconfig or {} end
11+
12+
--- Register a new language server with mason-lspconfig
13+
---@param server string the server name in lspconfig
14+
---@param spec AstroLSPMasonLspconfigServer the details for registering the server
15+
function M.register_server(server, spec)
16+
local filetype_mappings_avail, filetype_mappings = pcall(require, "mason-lspconfig.mappings.filetype")
17+
local server_mappings_avail, server_mappings = pcall(require, "mason-lspconfig.mappings.server")
18+
19+
if not (filetype_mappings_avail and server_mappings_avail) then
20+
vim.notify("Unable to properly load required `mason-lspconfig` modules", vim.log.levels.ERROR)
21+
end
22+
23+
-- register server in the filetype maps
24+
local filetypes = spec.filetypes
25+
if type(filetypes) ~= "table" then filetypes = { filetypes } end
26+
for _, filetype in ipairs(filetypes) do
27+
if not filetype_mappings[filetype] then filetype_mappings[filetype] = {} end
28+
table.insert(filetype_mappings, server)
29+
end
30+
-- register the mappings between lspconfig server name and mason package name
31+
server_mappings.lspconfig_to_package[server] = spec.package
32+
server_mappings.package_to_lspconfig[spec.package] = server
33+
-- if a config is provided, set up a mason-lspconfig server configuration module
34+
if spec.config then
35+
local module = spec.config
36+
if type(module) == "table" then
37+
local orig_function = module
38+
module = function() return orig_function end
39+
end
40+
local module_name = "mason-lspconfig.server_configurations." .. server
41+
if package.loaded[module_name] == nil then
42+
package.preload[module_name] = function() return module end
43+
else
44+
package.loaded[module_name] = module
45+
end
46+
end
47+
end
48+
49+
--- Register multiple new language servers with mason-lspconfig
50+
---@param server_specs? AstroLSPMasonLspconfigServers
51+
function M.register_servers(server_specs)
52+
if not server_specs then server_specs = resolve_config().servers or {} end
53+
for server, spec in pairs(server_specs) do
54+
M.register_server(server, spec)
55+
end
56+
end
57+
58+
return M

0 commit comments

Comments
 (0)