1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
-- rustaceanvim / rust-analyzer, matched to the VSCodium setup in ../../vscode/settings.json:
-- clippy instead of cargo check, rustfmt on save, source.fixAll on save, hard tabs.
--
-- Drop at: ~/.config/nvim/lua/plugins/rust.lua, and delete the rustaceanvim block
-- from lua/plugins/init.lua — two lazy.nvim specs for the same plugin will fight.
local timeout_ms = 2000
-- Equivalent of VS Code's "editor.codeActionsOnSave": { "source.fixAll.rust-analyzer" }.
--
-- vim.lsp.buf.code_action{apply=true} is asynchronous, so from a BufWritePre autocmd
-- the buffer is usually written before the edit arrives. buf_request_sync blocks,
-- which is what makes this actually run before the write.
--
-- Same caveat as in VS Code: this applies rust-analyzer's own fixes only. Lints that
-- come from cargo check or clippy are not included — those still need `cargo fix` or
-- `cargo clippy --fix` on the command line.
local function apply_fix_all(bufnr)
local client = vim.lsp.get_clients({ bufnr = bufnr, name = "rust-analyzer" })[1]
if not client then
return
end
local params = vim.lsp.util.make_range_params(0, client.offset_encoding)
params.context = { only = { "source.fixAll" }, diagnostics = {} }
local responses = vim.lsp.buf_request_sync(bufnr, "textDocument/codeAction", params, timeout_ms)
if not responses then
return
end
for _, response in pairs(responses) do
for _, action in ipairs(response.result or {}) do
-- A server may return the action unresolved, carrying only `data`;
-- the edit then has to be fetched with a second request.
if not action.edit and action.data then
local resolved =
client:request_sync("codeAction/resolve", action, timeout_ms, bufnr)
action = (resolved and resolved.result) or action
end
if action.edit then
vim.lsp.util.apply_workspace_edit(action.edit, client.offset_encoding)
end
end
end
end
vim.api.nvim_create_autocmd("BufWritePre", {
group = vim.api.nvim_create_augroup("rust_on_save", { clear = true }),
pattern = "*.rs",
callback = function(args)
apply_fix_all(args.buf)
-- VS Code's "editor.formatOnSave" for [rust]: rustfmt, driven by rust-analyzer.
vim.lsp.buf.format({
bufnr = args.buf,
timeout_ms = timeout_ms,
filter = function(client)
return client.name == "rust-analyzer"
end,
})
end,
})
return {
{
"mrcjkb/rustaceanvim",
version = "^6",
-- No `ft = { "rust" }` here. It is dead weight next to lazy = false, and
-- rustaceanvim's own docs advise against lazy-loading it by filetype:
-- it installs the FileType handler that starts the LSP itself.
lazy = false,
config = function()
vim.g.rustaceanvim = {
server = {
on_attach = function(client, bufnr)
require("nvchad.configs.lspconfig").on_attach(client, bufnr)
end,
default_settings = {
["rust-analyzer"] = {
cargo = { allFeatures = true },
checkOnSave = true,
-- Matches "rust-analyzer.check.command": "clippy".
check = { command = "clippy" },
},
},
},
}
end,
},
}
|