summaryrefslogtreecommitdiff
path: root/nvim
diff options
context:
space:
mode:
Diffstat (limited to 'nvim')
-rw-r--r--nvim/lua/plugins/rust.lua90
1 files changed, 90 insertions, 0 deletions
diff --git a/nvim/lua/plugins/rust.lua b/nvim/lua/plugins/rust.lua
new file mode 100644
index 0000000..8813700
--- /dev/null
+++ b/nvim/lua/plugins/rust.lua
@@ -0,0 +1,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,
+ },
+}