Neovim Rust-Analyzer Настройка стиля rustfmt

Вопрос или проблема

Как мне настроить конфигурацию lsp в neovim для форматирования моего кода на Rust в желаемом стиле? Как заставить его следовать тому, что указано в ~/.config/rustfmt/rustfmt.toml? Мой глобальный rustfmt.toml неверен или моя конфигурация LSP не использует его так, как должна?

У меня установлена последняя версия rust-analyzer с Mason.

Вот мой none-ls.lua:

return {
    "nvimtools/none-ls.nvim",
    config = function()
        local null_ls = require("null-ls")

        local eslint_d_path = vim.fn.stdpath("data") .. "/mason/bin/eslint_d"

        null_ls.setup({
            sources = {
                null_ls.builtins.formatting.stylua,
                null_ls.builtins.formatting.prettier,
                null_ls.builtins.diagnostics.eslint_d.with({
                    command = eslint_d_path,
                    extra_args = { "--config", vim.fn.expand(vim.loop.cwd() .. "/eslint.config.mjs") },
                    condition = function(utils)
                        return utils.root_has_file("eslint.config.mjs")
                    end,
                }),
                null_ls.builtins.formatting.shfmt,
            },
        })

        vim.keymap.set("n", "gf", vim.lsp.buf.format, {})
    end,
}

Мне нравится этот стиль форматирования:

pub fn run(address: &str) -> Result<Server, std::io::Error> {
    let server = HttpServer::new(|| {
        App::new()
            .route("/health_check", web::get().to(health_check))
    })
    .bind(address)?
    .run();

    Ok(server)
}

но в моем буфере vim, если я нажимаю gf (то есть vim.keymap.set("n", "gf", vim.lsp.buf.format, {}), определенный в none-ls.lua). Он переформатируется в:

pub fn run(address: &str) -> Result<Server, std::io::Error> {
    let server = HttpServer::new(|| App::new().route("/health_check", web::get().to(health_check)))
        .bind(address)?
        .run();

    Ok(server)
}

в lsp-config.lua (я добавлю весь файл внизу тоже):

lspconfig.rust_analyzer.setup({
  capabilities = capabilities,
  settings = {
    ["rust-analyzer"] = {
      cargo = {
        allFeatures = true,
        features = { "ssr" },
      },
      procMacro = {
        ignored = {
          leptos_macro = {
            -- "component", -- Раскомментируйте, если нужно
            "server",
          },
        },
      },
      rustfmt = {
        overrideCommand = { "rustfmt", "--edition", "2018" },
        config = "~/.config/rustfmt/rustfmt.toml",
      },
    },
  },
})

и у меня есть ~/.config/rustfmt/rustfmt.toml:

[general]
# Убедитесь, что функции форматируются с новой строкой перед открывающей фигурной скобкой
fn_brace_style = "SameLineWhere"

[style]
# Используйте компактный стиль для замыканий
fn_call_style = "Visual"

lsp-config.lua

return {
    {
        "williamboman/mason.nvim",
        lazy = false,
        config = function()
            require("mason").setup()
        end,
    },
    {
        "williamboman/mason-lspconfig.nvim",
        lazy = false,
        opts = {
            auto_install = true,
        },
    },
    {
        "neovim/nvim-lspconfig",
        lazy = false,
        config = function()
            local capabilities = require("cmp_nvim_lsp").default_capabilities()

            local lspconfig = require("lspconfig")

            -- Убедитесь, что ESLint настроен
            lspconfig.eslint.setup({
                capabilities = capabilities,
                root_dir = lspconfig.util.root_pattern(
                    ".eslintrc",
                    ".eslintrc.js",
                    ".eslintrc.json",
                    ".eslintrc.yaml",
                    "eslint.config.mjs",
                    ".git"
                ),
                settings = {
                    workingDirectory = { mode = "auto" },
                },
            })

            lspconfig.tsserver.setup({
                capabilities = capabilities,
            })
            lspconfig.html.setup({
                capabilities = capabilities,
            })
            lspconfig.lua_ls.setup({
                capabilities = capabilities,
            })
            lspconfig.rust_analyzer.setup({
                capabilities = capabilities,
                settings = {
                    ["rust-analyzer"] = {
                        cargo = {
                            allFeatures = true,
                            features = { "ssr" },
                        },
                        procMacro = {
                            ignored = {
                                leptos_macro = {
                                    -- "component", -- Раскомментируйте, если нужно
                                    "server",
                                },
                            },
                        },
                        rustfmt = {
                            overrideCommand = { "rustfmt", "--edition", "2018" },
                            config = "~/.config/rustfmt/rustfmt.toml",
                        },
                    },
                },
            })
            lspconfig.sqlls.setup({
                root_dir = function(fname)
                    return vim.fn.getcwd()
                end,
                capabilities = capabilities,
            })
            lspconfig.taplo.setup({
                capabilities = capabilities,
            })
            lspconfig.emmet_language_server.setup({
                capabilities = capabilities,
                filetypes = {
                    "html",
                    "css",
                    "javascriptreact",
                    "typescriptreact",
                    "javascript",
                    "typescript",
                    "jsx",
                    "tsx",
                },
            })
            -- lspconfig.prisma_language_server.setup({
            --   capabilities = capabilities,
            -- })

            vim.keymap.set("n", "K", vim.lsp.buf.hover, {})
            vim.keymap.set("n", "e", vim.diagnostic.open_float)
            vim.keymap.set("n", "E", vim.diagnostic.setloclist)
            vim.keymap.set("n", "gd", vim.lsp.buf.definition, {})
            vim.keymap.set("n", "gr", vim.lsp.buf.references, {})
            -- vim.keymap.set("n", "ca", vim.lsp.buf.code_action, {})
            -- vim.keymap.set("v", "ca", vim.lsp.buf.code_action, {})
            vim.keymap.set({ "n", "v" }, "ca", vim.lsp.buf.code_action, {})

            vim.keymap.set("n", "[d", vim.diagnostic.goto_prev)
            vim.keymap.set("n", "]d", vim.diagnostic.goto_next)
        end,
    },
}

Ответ или решение

Настройка формата кода Rust в Neovim с использованием rust-analyzer и rustfmt

Если вы хотите отформатировать ваш код на Rust в соответствии с установленным стилем, указанным в файле ~/.config/rustfmt/rustfmt.toml, вам нужно убедиться, что ваша LSP (Language Server Protocol) конфигурация правильно настроена для использования rustfmt и что ваши настройки корректны. Давайте разберем необходимые шаги для решения этой проблемы.

Шаг 1: Проверка конфигурации rustfmt

Сначала убедитесь, что ваш файл конфигурации Rustfmt (~/.config/rustfmt/rustfmt.toml) корректен. Ваш текущий файл имеет следующий вид:

[general]
# Ensure that functions are formatted with a newline before the opening brace
fn_brace_style = "SameLineWhere"

[style]
# Use a compact style for closures
fn_call_style = "Visual"

В целом, настройки выглядят приемлемо. Однако вы можете проверить актуальность выбранных параметров через документацию Rustfmt, чтобы увидеть, подходят ли они под ваши критерии форматирования.

Шаг 2: Настройка rust-analyzer

В вашей конфигурации LSP rust-analyzer убедитесь, что параметр для конфигурации rustfmt правильно настроен. Ваш текущий код выглядит следующим образом:

lspconfig.rust_analyzer.setup({
    capabilities = capabilities,
    settings = {
        ["rust-analyzer"] = {
            cargo = {
                allFeatures = true,
                features = { "ssr" },
            },
            rustfmt = {
                overrideCommand = { "rustfmt", "--edition", "2018" },
                config = "~/.config/rustfmt/rustfmt.toml",
            },
        },
    },
})

Основные аспекты тут:

  • Ви можете попробовать изменить overrideCommand на {"rustfmt", "--config-path", "~/.config/rustfmt/rustfmt.toml"} для явной передачи пути к конфигу, если это требуется.
  • Убедитесь, что путь указан правильно, а rustfmt действительно использует этот файл.

Шаг 3: Проверка интеграции с null-ls

Код в вашем none-ls.lua указывает, что вы используете null-ls вместе с rust-analyzer для форматирования:

null_ls.setup({
    sources = {
        -- ...
        null_ls.builtins.formatting.shfmt,
    },
})

Если вы хотите, чтобы rustfmt использовался вместе с null-ls, добавьте следующий источник перед другими элементами в sources:

null_ls.builtins.formatting.rustfmt.with({
    extra_args = { "--config-path", "~/.config/rustfmt/rustfmt.toml" }
}),

Шаг 4: Отладка

  1. Проверка консоли: Включите отладку для rust-analyzer, чтобы увидеть, какие конфигурации он использует и какие ошибки могут возникать.

  2. Команда формата: Запустите команду форматирования напрямую из вашего терминала, чтобы убедиться, что rustfmt применяет ваши настройки. Попробуйте:

    rustfmt --config-path ~/.config/rustfmt/rustfmt.toml path/to/your/file.rs
  3. Убедитесь: Если после всех настроек и тестов проблема сохраняется, убедитесь, что у вас актуальная версия rust-analyzer и rustfmt.

Заключение

Правильно настроенная конфигурация LSP и rustfmt позволит вам пользоваться желаемым стилем форматирования в Neovim. Следуйте предложенным шагам, чтобы устранить возможные недоработки и интегрировать форматирование по вашим предпочтениям.

Оцените материал
Добавить комментарий

Капча загружается...