simrat39 / rust-tools.nvim

Tools for better development in rust using neovim's builtin lsp
MIT License
2.16k stars 157 forks source link

How to use rust-tools with mason-lspconfig? #384

Open Gremious opened 1 year ago

Gremious commented 1 year ago

Is there a minimal configuration example of setting up mason-lspconfig and rust-tools together anywhere? I checked both this repo and mason but I did not find it?

I just want to know the 'correct' way to setup a vim config with mason, where mason loads not exclusively just rust_analyzer, and rust_analyzer itself has a few custom settings + rust-tools. Codelldb/debugging optional but welcome, as I believe you can set it up pretty nicely?

Would love to see this actually written out somewhere, e.g. a readme or wiki.

utkarshgupta137 commented 1 year ago

If you're fine with using nvim-lspconfig, you can refer to my setup: https://github.com/utkarshgupta137/nvim-lazy/blob/73a2a2f/lua/lvim/lsp.lua#L20 + https://github.com/utkarshgupta137/nvim-lazy/blob/73a2a2f/lua/lvim/lsp/rust-tools.lua

AFAIK, there is no benefit of setting up LSP using mason-lspconfig over nvim-lspconfig.

snaggen commented 1 year ago

The trick I found was to avoid setting up anyting rust related in mason-lspconfig

            require("mason-lspconfig").setup_handlers {
                function(server_name)
                    require("lspconfig")[server_name].setup {}
                end,

                ["rust_analyzer"] = function() end
            }

I then have rust-tools setup everything using mason paths by it self

            local install_root_dir = vim.fn.stdpath "data" .. "/mason"
            local extension_path = install_root_dir .. "/packages/codelldb/extension/"
            local codelldb_path = extension_path .. "adapter/codelldb"
            local liblldb_path = extension_path .. "lldb/lib/liblldb.so"
            local rt = require("rust-tools")
            rt.setup({
                tools = {
                    hover_actions = {
                        -- whether the hover action window gets automatically focused
                        auto_focus = false,
                    },
                },
                server = {
                    on_attach = function(_, bufnr)
                        require("dap")
                        require("dapui")
                        -- Hover actions
                        vim.keymap.set("n", "K", rt.hover_actions.hover_actions, { buffer = bufnr })
                        -- Code action groups
                        -- vim.keymap.set("n", "<Space>a", rt.code_action_group.code_action_group, { buffer = bufnr })
                    end,
                    flags = {
                        debounce_text_changes = 150,
                    },
                    settings = {
                        ["rust-analyzer"] = {
                            checkOnSave = {
                                enable = true,
                                command = "clippy",
                            },
                            cargo = {
                                allFeatures = true,
                            },
                        },
                    },
                },
                dap = {
                    adapter = require("rust-tools.dap").get_codelldb_adapter(codelldb_path, liblldb_path),
                },
            })

I setup the keybindings on the LspAttach event (in the nvim-lspconifg in my lazy config), so they are common for all LSP

Gremious commented 1 year ago

@snaggen Thank you very much, that is nice!

After reading what that setup_handlers does in the mason lsp config docs, I noticed it actually explicitly mentions rust-tools as a handler itself: https://github.com/williamboman/mason-lspconfig.nvim/blob/main/doc/mason-lspconfig.txt#L163

So I guess that is the intended way, I will try that approach.

Would still like a mention of that at least in this repo perhaps, so I'm gonna keep the issue open. That or maybe this repo should have a disscussion board for questions like these.

Gremious commented 1 year ago

For anyone stumbling upon this in the future, this is the setup I went with:

local rust_tools_config = {
    -- rust-tools settings, etc.
    dap = function()
        local install_root_dir = vim.fn.stdpath "data" .. "/mason"
        local extension_path = install_root_dir .. "/packages/codelldb/extension/"
        local codelldb_path = extension_path .. "adapter/codelldb"
        local liblldb_path = extension_path .. "lldb/lib/liblldb.so"

        return {
            adapter = require("rust-tools.dap").get_codelldb_adapter(codelldb_path, liblldb_path)
        }
    end,
}

mason_lspconfig.setup_handlers({
    -- The first entry (without a key) will be the default handler
    -- and will be called for each installed server that doesn't have a dedicated handler.
    function(server_name)
        -- I use lsp-status which adds itself to the capabilities table
        require("lspconfig")[server_name].setup({ on_attach = on_attach, capabilities = capabilities })
    end,

    ["lua_ls"] = function()
        require("lspconfig").lua_ls.setup({
            on_attach = on_attach,
            capabilities = capabilities,
            settings = {
                Lua = {
                    diagnostics = {
                        -- Get the language server to recognize the `vim` global
                        globals = { "vim" },
                    },
                },
            },
        })
    end,

    ["rust_analyzer"] = function()
        require("rust-tools").setup({
            -- rust_tools specific settings
            tools = rust_tools_config,
            -- on_attach is actually bound in server for rust-tools
            server = rust_tools_rust_server,
            capabilities = capabilities,
        })
    end,
})

(full config here: https://github.com/Gremious/configs, though it's still a mess)

TheButlah commented 1 year ago

(full config here: https://github.com/Gremious/configs, though it's still a mess)

It looks like that is a private repo or deleted

-- I use lsp-status which adds itself to the capabilities table

It looks like the capabilities variable doesn't exist, can you elaborate?

Gremious commented 1 year ago

It looks like that is a private repo or deleted

Oops, my bad! Public now.

It looks like the capabilities variable doesn't exist, can you elaborate?

If you mean variable doesn't exit in my little snippet - yeah, sorry. I believe you can ommit it if you're not doing anything special. But you can now see how I use it here: https://github.com/Gremious/configs/blob/main/lua/config/lsp.lua#L110 I create cmp_nvim_lsp ones from the lsp default ones, with the function cmp_nvim_lsp provides. Then, I extend the table with lsp_status ones as well.

If you mean Mason doesn't mention the capabilities table, then yeah, mason-lspconfig doesn't mention on_attach/capabilities anywhere at all, so I assume those are just the actual nvim-lspconfig tables, since nvim-lspconfig notes "You must pass on_attach and capabilities for each setup {} if you want these to take effect." in their readme https://github.com/neovim/nvim-lspconfig

eikopf commented 1 year ago

For anyone on macOS, you need to do two things:

  1. Use these instructions to symlink lldb-vscode onto your path without conflicting with the default lldb installation.
  2. Change the end of the liblldb_path to .dylib.
newtoallofthis123 commented 1 year ago

Thanks a lot for the help!

This is what I decided to go with after getting the same error

require('mason-lspconfig').setup_handlers({
  function(server_name)
      require("lspconfig")[server_name].setup({ on_attach = on_attach, capabilities = capabilities })
    end,

    ["rust_analyzer"] = function ()
        require("rust-tools").setup()
    end
})

works well enough 😅

snaggen commented 1 year ago

Thanks a lot for the help!

This is what I decided to go with after getting the same error

require('mason-lspconfig').setup_handlers({
  function(server_name)
      require("lspconfig")[server_name].setup({ on_attach = on_attach, capabilities = capabilities })
    end,

    ["rust_analyzer"] = function ()
        require("rust-tools").setup()
    end
})

works well enough 😅

This have the downside of always loading rust-tools, so to get it lazy loaded I instead uses

                ["rust_analyzer"] = function() end

in the mason-lspconfig. And then I just load it using a file type trigger in my Lazy config

 {
        -- Rust Programming Enhancements
        "simrat39/rust-tools.nvim",
        ft = "rust",

        ...
}
newtoallofthis123 commented 1 year ago

that's actually quite smart 😄

TheButlah commented 1 year ago

Could someone add this to the README? Maybe in a spoilered/collapsible section