Skip to content

Commit aa2c440

Browse files
committed
feat(mason)!: migrate to v2.x
Just wrapped up going thru all the changes in mason 2.x (and nvim 0.11 too)! This should be a follow up to #1466 and (hopefully) fix all the issues related to the updated LSP API (like servers not spawning and other weirdness) and works together w #1496. Acc the main issue was that some mason package names don't match their names in lspconfig, so just using `lsp_deps` directly works for most, but breaks a bunch of others (tldr: that mismatch is what was causing all the edge cases and broken behavior). I also went ahead and enabled `automatic_installation` because why not lol means we don't have to manually call `vim.lsp.enable()` for everything, which might save a tiny bit of perf too. Didn't test this super thoroughly yet so pls lmk if anything's still broken! Signed-off-by: Jint-lzxy <50296129+Jint-lzxy@users.noreply.github.com>
1 parent 7777eff commit aa2c440

6 files changed

Lines changed: 107 additions & 79 deletions

File tree

lua/modules/configs/completion/lsp.lua

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ return function()
77
local opts = {
88
capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()),
99
}
10-
-- Setup lsps that are not supported by `mason.nvim` but supported by `nvim-lspconfig` here.
10+
-- Configure LSPs that are not supported by `mason.nvim` but are available in `nvim-lspconfig` here.
11+
-- Call |vim.lsp.config()| FOLLOWED BY |vim.lsp.enable()| to ensure the server starts automatically.
1112
if vim.fn.executable("dart") == 1 then
1213
local ok, _opts = pcall(require, "user.configs.lsp-servers.dartls")
1314
if not ok then
1415
_opts = require("completion.servers.dartls")
1516
end
1617
local final_opts = vim.tbl_deep_extend("keep", _opts, opts)
17-
nvim_lsp.dartls.setup(final_opts)
18+
vim.lsp.config("dartls", final_opts)
19+
vim.lsp.enable("dartls")
1820
end
1921

2022
pcall(require, "user.configs.lsp")

lua/modules/configs/completion/mason-lspconfig.lua

Lines changed: 100 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
local M = {}
22

33
M.setup = function()
4+
local is_windows = require("core.global").is_windows
5+
46
local lsp_deps = require("core.settings").lsp_deps
7+
local mason_registry = require("mason-registry")
8+
local mason_lspconfig = require("mason-lspconfig")
59

610
require("lspconfig.ui.windows").default_options.border = "rounded"
711
require("modules.utils").load_plugin("mason-lspconfig", {
812
ensure_installed = lsp_deps,
13+
automatic_enable = true,
914
})
1015

1116
vim.diagnostic.config({
@@ -52,13 +57,12 @@ please REMOVE your LSP configuration (rust_analyzer.lua) from the `servers` dire
5257
if not ok then
5358
-- Default to use factory config for server(s) that doesn't include a spec
5459
vim.lsp.config(lsp_name, opts)
55-
vim.lsp.enable(lsp_name)
5660
elseif type(custom_handler) == "function" then
57-
--- Case where language server requires its own setup
58-
--- Make sure to call require("lspconfig")[lsp_name].setup() in the function
59-
--- See `clangd.lua` for example.
61+
-- Case where language server requires its own setup
62+
-- Be sure to call `vim.lsp.config()` within the setup function.
63+
-- Refer to |vim.lsp.config()| for documentation.
64+
-- For an example, see `clangd.lua`.
6065
custom_handler(opts)
61-
vim.lsp.enable(lsp_name)
6266
elseif type(custom_handler) == "table" then
6367
vim.lsp.config(
6468
lsp_name,
@@ -69,7 +73,6 @@ please REMOVE your LSP configuration (rust_analyzer.lua) from the `servers` dire
6973
custom_handler
7074
)
7175
)
72-
vim.lsp.enable(lsp_name)
7376
else
7477
vim.notify(
7578
string.format(
@@ -83,9 +86,98 @@ please REMOVE your LSP configuration (rust_analyzer.lua) from the `servers` dire
8386
end
8487
end
8588

86-
for _, lsp in ipairs(lsp_deps) do
87-
mason_lsp_handler(lsp)
89+
---A simplified mimic of <mason-lspconfig 1.x>'s `setup_handlers` callback.
90+
---Invoked for each Mason package (name or `Package` object) to configure its language server.
91+
---@param pkg string|{name: string} Either the package name (string) or a Package object
92+
local function setup_lsp_for_package(pkg)
93+
-- First try to grab the builtin mappings
94+
local mappings = mason_lspconfig.get_mappings().package_to_lspconfig
95+
-- If empty or nil, build it by hand
96+
if not mappings or vim.tbl_isempty(mappings) then
97+
mappings = {}
98+
for _, spec in ipairs(mason_registry.get_all_package_specs()) do
99+
local lspconfig = vim.tbl_get(spec, "neovim", "lspconfig")
100+
if lspconfig then
101+
mappings[spec.name] = lspconfig
102+
end
103+
end
104+
end
105+
106+
-- Figure out the package name and lookup
107+
local name = type(pkg) == "string" and pkg or pkg.name
108+
local srv = mappings[name]
109+
if not srv then
110+
return
111+
end
112+
113+
-- Invoke the handler
114+
mason_lsp_handler(srv)
88115
end
116+
117+
for _, pkg in ipairs(mason_registry.get_installed_package_names()) do
118+
setup_lsp_for_package(pkg)
119+
end
120+
121+
-- Hook into Mason's package install event to install extra plugins for pylsp (black, ruff, rope),
122+
-- then configure the installed package's LSP using setup_lsp_for_package.
123+
mason_registry:on(
124+
"package:install:success",
125+
vim.schedule_wrap(function(pkg)
126+
if pkg.name == "python-lsp-server" then
127+
local venv = vim.fn.stdpath("data") .. "/mason/packages/python-lsp-server/venv"
128+
local python = is_windows and venv .. "/Scripts/python.exe" or venv .. "/bin/python"
129+
local black = is_windows and venv .. "/Scripts/black.exe" or venv .. "/bin/black"
130+
local ruff = is_windows and venv .. "/Scripts/ruff.exe" or venv .. "/bin/ruff"
131+
132+
require("plenary.job")
133+
:new({
134+
command = python,
135+
args = {
136+
"-m",
137+
"pip",
138+
"install",
139+
"-U",
140+
"--disable-pip-version-check",
141+
"python-lsp-black",
142+
"python-lsp-ruff",
143+
"pylsp-rope",
144+
},
145+
cwd = venv,
146+
env = { VIRTUAL_ENV = venv },
147+
on_exit = function()
148+
if vim.fn.executable(black) == 1 and vim.fn.executable(ruff) == 1 then
149+
vim.notify(
150+
"Finished installing pylsp plugins",
151+
vim.log.levels.INFO,
152+
{ title = "[lsp] Install Status" }
153+
)
154+
else
155+
vim.notify(
156+
"Failed to install pylsp plugins. [Executable not found]",
157+
vim.log.levels.ERROR,
158+
{ title = "[lsp] Install Failure" }
159+
)
160+
end
161+
end,
162+
on_start = function()
163+
vim.notify(
164+
"Now installing pylsp plugins...",
165+
vim.log.levels.INFO,
166+
{ title = "[lsp] Install Status", timeout = 6000 }
167+
)
168+
end,
169+
on_stderr = function(_, msg_stream)
170+
if msg_stream then
171+
vim.notify(msg_stream, vim.log.levels.ERROR, { title = "[lsp] Install Failure" })
172+
end
173+
end,
174+
})
175+
:start()
176+
end
177+
178+
vim.schedule_wrap(setup_lsp_for_package)
179+
end)
180+
)
89181
end
90182

91183
return M
Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
local M = {}
22

33
M.setup = function()
4-
local is_windows = require("core.global").is_windows
5-
6-
local mason_registry = require("mason-registry")
74
require("lspconfig.ui.windows").default_options.border = "rounded"
85

96
local icons = {
@@ -31,66 +28,6 @@ M.setup = function()
3128
},
3229
},
3330
})
34-
35-
-- Additional plugins for pylsp
36-
mason_registry:on(
37-
"package:install:success",
38-
vim.schedule_wrap(function(pkg)
39-
if pkg.name ~= "python-lsp-server" then
40-
return
41-
end
42-
43-
local venv = vim.fn.stdpath("data") .. "/mason/packages/python-lsp-server/venv"
44-
local python = is_windows and venv .. "/Scripts/python.exe" or venv .. "/bin/python"
45-
local black = is_windows and venv .. "/Scripts/black.exe" or venv .. "/bin/black"
46-
local ruff = is_windows and venv .. "/Scripts/ruff.exe" or venv .. "/bin/ruff"
47-
48-
require("plenary.job")
49-
:new({
50-
command = python,
51-
args = {
52-
"-m",
53-
"pip",
54-
"install",
55-
"-U",
56-
"--disable-pip-version-check",
57-
"python-lsp-black",
58-
"python-lsp-ruff",
59-
"pylsp-rope",
60-
},
61-
cwd = venv,
62-
env = { VIRTUAL_ENV = venv },
63-
on_exit = function()
64-
if vim.fn.executable(black) == 1 and vim.fn.executable(ruff) == 1 then
65-
vim.notify(
66-
"Finished installing pylsp plugins",
67-
vim.log.levels.INFO,
68-
{ title = "[lsp] Install Status" }
69-
)
70-
else
71-
vim.notify(
72-
"Failed to install pylsp plugins. [Executable not found]",
73-
vim.log.levels.ERROR,
74-
{ title = "[lsp] Install Failure" }
75-
)
76-
end
77-
end,
78-
on_start = function()
79-
vim.notify(
80-
"Now installing pylsp plugins...",
81-
vim.log.levels.INFO,
82-
{ title = "[lsp] Install Status", timeout = 6000 }
83-
)
84-
end,
85-
on_stderr = function(_, msg_stream)
86-
if msg_stream then
87-
vim.notify(msg_stream, vim.log.levels.ERROR, { title = "[lsp] Install Failure" })
88-
end
89-
end,
90-
})
91-
:start()
92-
end)
93-
)
9431
end
9532

9633
return M

lua/modules/configs/completion/servers/clangd.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ end
3535

3636
-- https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/configs/clangd.lua
3737
return function(defaults)
38-
require("lspconfig").clangd.setup({
38+
vim.lsp.config("clangd", {
3939
on_attach = defaults.on_attach,
4040
capabilities = vim.tbl_deep_extend("keep", { offsetEncoding = { "utf-16", "utf-8" } }, defaults.capabilities),
4141
single_file_support = true,

lua/modules/configs/tool/dap/clients/delve.lua

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ return function()
2424

2525
dap.adapters.go = {
2626
type = "executable",
27-
command = "node",
28-
args = {
29-
vim.fn.expand("$MASON") .. "/packages/go-debug-adapter" .. "/extension/dist/debugAdapter.js",
30-
},
27+
command = vim.fn.exepath("go-debug-adapter"), -- Find go-debug-adapter on $PATH
3128
}
3229
dap.configurations.go = {
3330
{

lua/modules/configs/tool/dap/clients/python.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ return function()
44
local dap = require("dap")
55
local utils = require("modules.utils.dap")
66
local is_windows = require("core.global").is_windows
7-
local debugpy_root = vim.fn.expand("$MASON") .. "/packages/debugpy"
7+
local debugpy_root = vim.fn.expand("$MASON/packages/debugpy")
88

99
dap.adapters.python = function(callback, config)
1010
if config.request == "attach" then

0 commit comments

Comments
 (0)