Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Usage with nvim-lsp-installer #89

Closed
nagua opened this issue Oct 31, 2021 · 26 comments
Closed

Usage with nvim-lsp-installer #89

nagua opened this issue Oct 31, 2021 · 26 comments

Comments

@nagua
Copy link

nagua commented Oct 31, 2021

Hello everyone,

I'm currently trying to integrate this plugin together with https://github.com/williamboman/nvim-lsp-installer.

I want to use nvim-lsp-installer to manage the installation of rust-analyzer
and use this plugin for extended capabilities. But both api's are pretty incompatible.

nvim-lsp-installer wants me to call its setup function in a callback provided by it and rust-tools.nvim also
wants me to run their setup function to set everything up.

It seems like that it would be much more natural if rust-tools.nvim would provide a public function to inject
(extend) the lsp server settings configuration instead of internalizing everything. (At least it should provide
the option for extended use cases.)

What do you think? Is this a good idea? Do you have other ideas on how to integrate these two plugins?

@simrat39
Copy link
Owner

simrat39 commented Oct 31, 2021

local lsp_installer = require("nvim-lsp-installer")

lsp_installer.on_server_ready(function(server)
	local opts = {}

	-- (optional) Customize the options passed to the server
	-- if server.name == "tsserver" then
	--     opts.root_dir = function() ... end
	-- end

	if server.name == "rust_analyzer" then
		require("rust-tools").setup({
			dap = {
				adapter = require("rust-tools.dap").get_codelldb_adapter(
					"/home/simrat39/.vscode/extensions/vadimcn.vscode-lldb-1.6.7/adapter/codelldb",
					"/home/simrat39/.vscode/extensions/vadimcn.vscode-lldb-1.6.7/lldb/lib/liblldb.so"
				),
			},
			server = { cmd = server._default_options.cmd },
		})
		return
	end
	-- This setup() function is exactly the same as lspconfig's setup function.
	-- Refer to https://github.com/neovim/nvim-lspconfig/blob/master/ADVANCED_README.md
	server:setup(opts)
end)

This works, please ignore the dap stuff
Make sure the return is present else it'll mess things up

@mkadit
Copy link

mkadit commented Nov 1, 2021

Hello,

Same problem here and fortunately I was able to have rust-tools running thanks to the setup above with the exception of the better debugging features. I have properly setup the path and everything but variables like string wouldn't show the values at all.

image

Here are my configuration for the rust_analyzer server

    elseif server.name == "rust_analyzer" then
        local extension_path = os.getenv("HOME") .. '/.vscode-oss/extensions/vadimcn.vscode-lldb-1.6.9/'
        local codelldb_path = extension_path .. 'adapter/codelldb'
        local liblldb_path = extension_path .. 'lldb/lib/liblldb.so'
        require("rust-tools").setup({
            server = {
                dap = {
                    adapter = require('rust-tools.dap').get_codelldb_adapter(
                        codelldb_path, liblldb_path)
                },
                server= {cmd = server._default_options.cmd}
            }
        })
        return
    end

@simrat39
Copy link
Owner

simrat39 commented Nov 1, 2021

@mkadit the dap key isn't inside the server key. It should be like this ->

{
dap = ...,
server =...,
}

@mkadit
Copy link

mkadit commented Nov 1, 2021

Ah my mistake, thank you for that!

@nagua
Copy link
Author

nagua commented Nov 2, 2021

local lsp_installer = require("nvim-lsp-installer")

lsp_installer.on_server_ready(function(server)
	local opts = {}

	-- (optional) Customize the options passed to the server
	-- if server.name == "tsserver" then
	--     opts.root_dir = function() ... end
	-- end

	if server.name == "rust_analyzer" then
		require("rust-tools").setup({
			dap = {
				adapter = require("rust-tools.dap").get_codelldb_adapter(
					"/home/simrat39/.vscode/extensions/vadimcn.vscode-lldb-1.6.7/adapter/codelldb",
					"/home/simrat39/.vscode/extensions/vadimcn.vscode-lldb-1.6.7/lldb/lib/liblldb.so"
				),
			},
			server = { cmd = server._default_options.cmd },
		})
		return
	end
	-- This setup() function is exactly the same as lspconfig's setup function.
	-- Refer to https://github.com/neovim/nvim-lspconfig/blob/master/ADVANCED_README.md
	server:setup(opts)
end)

This works, please ignore the dap stuff Make sure the return is present else it'll mess things up

Hey @simrat39,

thanks for your reply. I could verify that this is working.
The only thing that I dislike about it, is that nvim-lsp-installer
can do a few additional things inside its setup function (like executing
the pre/post hook, see here: https://github.com/williamboman/nvim-lsp-installer/blob/main/lua/nvim-lsp-installer/server.lua#L53).

I don't think that it is a problem in this case, but it is also not that perfect.

But at least I have a working version for now.

@simrat39
Copy link
Owner

simrat39 commented Nov 2, 2021

@nagua can't you just...call them before and after calling rust-tools' setup lol

@GBeauregard
Copy link

GBeauregard commented Nov 3, 2021

I'm having a problem using this with nvim-lsp-installer where I get an error when opening a .rs file outside the context of a project. I get a Error detected while processing VimEnter Autocommands for "*.rs": E5108: Error executing lua ...im/plugged/rust-tools.nvim/lua/rust-tools/s tandalone.lua:8: attempt to index field 'server' (a nil value) error on startup.

I'm doing the similar as recommended by lsp_installer upstream:

local lsp_installer = require("nvim-lsp-installer")

lsp_installer.on_server_ready(function(server)
  if server.name == "rust_analyzer" then
    local opts = {
      server = vim.tbl_deep_extend("force", server:get_default_options(), {
        on_attach = on_attach,
        flags = {
          debounce_text_changes = 150,
        },
      }),
    }
    require("rust-tools").setup(coq.lsp_ensure_capabilities(opts))
    server:attach_buffers()
  else
    local opts = {
      on_attach = on_attach,
      flags = {
        debounce_text_changes = 150,
      },
    }
    server:setup(coq.lsp_ensure_capabilities(opts))
  end
  -- vim.cmd [[ do User LspAttachBuffers ]]
end)

@simrat39
Copy link
Owner

simrat39 commented Nov 3, 2021

@GBeauregard could you try without the Coq ensure capabilities stuff? And you shouldnt need to call server:attach_buffers as well

@GBeauregard
Copy link

GBeauregard commented Nov 3, 2021

@GBeauregard could you try without the Coq ensure capabilities stuff?

Ah yeah that was it since I had it in the wrong spot...oops 🤦 ; now without it, it just throws an error that it can't find the workplace (correctly). I don't mind the error but it'd be nice to silence it if possible i guess. I think this is on the LSP side and not your side though.

And you shouldnt need to call server:attach_buffers as well

This is required and removing it breaks the server (auto)starting. This is only required with nvim-lsp-installer since 2 days ago because of new changes that were made; the lsp-installer maintainer directed me to add it to get things working again.

@GBeauregard
Copy link

GBeauregard commented Nov 3, 2021

@GBeauregard could you try without the Coq ensure capabilities stuff? And you shouldnt need to call server:attach_buffers as well

I have no idea how I had it working earlier, but now I'm getting the error again (with or w/o the coq line). My computer was at full load compiling something when it was working earlier so it may be indicative of some sort of lazy loading issue. But anyway this problem is back.

@simrat39
Copy link
Owner

simrat39 commented Nov 4, 2021

So looks like this happens because the setup finishes after the autocommand is triggered:
image

simrat39 added a commit that referenced this issue Nov 4, 2021
@simrat39
Copy link
Owner

simrat39 commented Nov 4, 2021

local lsp_installer = require("nvim-lsp-installer")
local lsp_installer_servers = require("nvim-lsp-installer/servers")

local server_available, requested_server = lsp_installer_servers.get_server("rust_analyzer")

if server_available then
    require("rust-tools").setup({
        dap = {
            adapter = require("rust-tools.dap").get_codelldb_adapter(
                "/home/simrat39/.vscode/extensions/vadimcn.vscode-lldb-1.6.7/adapter/codelldb",
                "/home/simrat39/.vscode/extensions/vadimcn.vscode-lldb-1.6.7/lldb/lib/liblldb.so"
            ),
        },
        server = { cmd = requested_server._default_options.cmd },
    })
end

lsp_installer.on_server_ready(function(server)
    local opts = {}

    if server.name == "rust_analyzer" then
        return
    end

    server:setup(opts)
end)

@GBeauregard it works with this setup. @nagua @mkadit consider updating to this

@simrat39 simrat39 closed this as completed Nov 4, 2021
@simrat39 simrat39 pinned this issue Nov 4, 2021
@simrat39 simrat39 changed the title Using this extension with a rust-analyzer provided by nvim-lsp-installer Usage with nvim-lsp-installer Nov 4, 2021
@williamboman
Copy link
Contributor

I'd recommend the following change, to avoid reaching into private fields (also to make sure any other server options other than just cmd are included should they be introduced in the future):

diff --git a/a b/b
index ce46eb9..35a5872 100644
--- a/a
+++ b/b
@@ -11,7 +11,7 @@ if server_available then
                 "/home/simrat39/.vscode/extensions/vadimcn.vscode-lldb-1.6.7/lldb/lib/liblldb.so"
             ),
         },
-        server = { cmd = requested_server._default_options.cmd },
+        server = server:get_default_options()
     })
 end

I would also put this inside the lsp_installer.on_server_ready() callback, in the if server.name == "rust_analyzer" block. Would provide a nicer interop with nvim-lsp-installer imo

@norbertkeri
Copy link

norbertkeri commented Dec 7, 2021

@williamboman Can you please post a full config of how you suggest initializing both plugins? I'm trying to follow your suggestion of moving the opts into the on_server_ready block, but depending on what I pass as the top level key, I either get nothing (lsp doesn't seem to be active), or I get an error from LspInstall about rust-analyzer not being on the path BUT it still works.

Things do work fine with the code provided by simrat39, but I'd like to future proof it.

@williamboman
Copy link
Contributor

williamboman commented Dec 7, 2021

Have you tried something like the following? Just from reading the docs, I believe this should work

lsp_installer.on_server_ready(function(server)
    local opts = {}

    if server.name == "rust_analyzer" then
        -- Initialize the LSP via rust-tools instead
        require("rust-tools").setup({
            -- The "server" property provided in rust-tools setup function are the settings rust-tools will provide to
            -- lspconfig during init.
            -- We merge the necessary settings from nvim-lsp-installer (server:get_default_options()) with
            -- the user's own settings (opts).
            server = vim.tbl_deep_extend("force", server:get_default_options(), opts),
        })
    else
        server:setup(opts)
    end
end)

@williamboman
Copy link
Contributor

Also a heads up to those who currently read the cmd property from nvim-lsp-installer: this cmd property will soon be removed from virtually all servers in nvim-lsp-installer. Instead, we'll extend the user's PATH before starting the server - allowing the neovim LSP client to locate the server executables by itself instead (williamboman/nvim-lsp-installer#283). This means servers will start using the default cmd provided by nvim-lspconfig, so if you'd like to access it for some reason you'll need to do so via lspconfig (e.g., require("lspconfig.server_configurations.rust_analyzer").default_config.cmd)

@norbertkeri
Copy link

I can't seem to get it working. This code snippet works:

local lsp_installer = require("nvim-lsp-installer")
local lsp_installer_servers = require("nvim-lsp-installer/servers")

local server_available, requested_server = lsp_installer_servers.get_server("rust_analyzer")

if server_available then
    local opts = {
        tools = {
            autoSetHints = true,
            hover_with_actions = false,
            inlay_hints = {
                show_parameter_hints = true,
                parameter_hints_prefix = "",
                other_hints_prefix = "",
            },
        },
        server = {
            cmd = requested_server._default_options.cmd,
            settings = {
                ["rust-analyzer"] = {
                    completion = {
                        postfix = {
                            enable = false
                        }
                    },
                    checkOnSave = {
                        command = "clippy"
                    },
                }
            }
        },
    }
    require("rust-tools").setup(opts)
end

lsp_installer.on_server_ready(function(server)
    local opts = {}

    if server.name == "rust_analyzer" then
        return
    end

    server:setup(opts)
end)

While this one doesn't, no error messages shown:

lsp_installer.on_server_ready(function(server)
    local opts = {}

    if server.name == "rust_analyzer" then
        local rustopts = {
            tools = {
                autoSetHints = true,
                hover_with_actions = false,
                inlay_hints = {
                    show_parameter_hints = true,
                    parameter_hints_prefix = "",
                    other_hints_prefix = "",
                },
            },
            server = vim.tbl_deep_extend("force", server:get_default_options(), opts, {
                settings = {
                    ["rust-analyzer"] = {
                        completion = {
                            postfix = {
                                enable = false
                            }
                        },
                        checkOnSave = {
                            command = "clippy"
                        },
                    }
                }
            }),
        }
        require("rust-tools").setup(rustops)
    else
        server:setup(opts)
    end
end)

@williamboman
Copy link
Contributor

williamboman commented Dec 7, 2021

Minor and unrelated but convention re: / vs . is to use . (I believe using different delimiters has an impact on Lua module cache, and . is more OS-agnostic).

- local lsp_installer_servers = require("nvim-lsp-installer/servers")
+ local lsp_installer_servers = require("nvim-lsp-installer.servers")

Hmm, the snippet I suggested assumes you manage the installation of rust-analyzer via nvim-lsp-installer. Is it currently listed as installed (:LspInstallInfo)?

@norbertkeri
Copy link

norbertkeri commented Dec 7, 2021

Yes it is listed as installed (and I have removed it from my system altogether), the first snippet I posted actually uses that through requested_server._default_options.cmd.

@williamboman
Copy link
Contributor

Hmm weird, will have to tinker with it locally to understand more.

@williamboman
Copy link
Contributor

So this seems to work just fine for me. The only problem is that it doesn't attach the very first buffer(s) that happen to be open when rust-tools is initialized. The reason for this is that nvim-lsp-installer schedules the "server ready" dispatches, so if you open a buffer like nvim src/main.rs or :e src/main.rs the FileType event will already have fired (lspconfig uses this to check whether it should start and attach any LSP servers).

There's a convenience server:attach_buffers() method provided by nvim-lsp-installer to remedy this.

lsp_installer.on_server_ready(function(server)
    local opts = {}

    if server.name == "rust_analyzer" then
        -- Initialize the LSP via rust-tools instead
        require("rust-tools").setup({
            -- The "server" property provided in rust-tools setup function are the settings rust-tools will provide to
            -- lspconfig during init.
            -- We merge the necessary settings from nvim-lsp-installer (server:get_default_options()) with
            -- the user's own settings (opts).
            server = vim.tbl_deep_extend("force", server:get_default_options(), opts),
        })
+       server:attach_buffers()
    else
        server:setup(opts)
    end
end)

@williamboman
Copy link
Contributor

@GBeauregard
Copy link

https://asciinema.org/a/30RQSRdiLXdP6SISvJeBslC6h

This doesn't appear to be working correctly; we should be getting inlayed type hints by default. You do appear to have coincidentally made a testfile that wouldn't have them despite them being fairly ubiquitous. Try the config here to see them: #89 (comment)

@williamboman
Copy link
Contributor

williamboman commented Dec 8, 2021

That's probably because I've not set up either the Rust project or rust-tools properly. It does end up using nvim-lsp-installer's installation of rust_analyzer for starting the LSP server - anything further than that I feel like have nothing to do with rust-tools <-> nvim-lsp-installer interop, or am I missing something?

If I run :RustSetInlayHints manually it pops up:
Screenshot 2021-12-08 at 03 22 36

@norbertkeri
Copy link

@williamboman It seems the attach_buffers call does the trick, it works now, thank you very much for your help.

For everyone else looking for an example on how to specify some other options to pass along to rust analyzer, this is what I'm using:

local lsp_installer = require("nvim-lsp-installer")

lsp_installer.on_server_ready(function(server)
    local opts = {}

    if server.name == "rust_analyzer" then
        local rustopts = {
            tools = {
                autoSetHints = true,
                hover_with_actions = false,
                inlay_hints = {
                    show_parameter_hints = true,
                    parameter_hints_prefix = "",
                    other_hints_prefix = "",
                },
            },
            server = vim.tbl_deep_extend("force", server:get_default_options(), opts, {
                settings = {
                    ["rust-analyzer"] = {
                        completion = {
                            postfix = {
                                enable = false
                            }
                        },
                        checkOnSave = {
                            command = "clippy"
                        },
                    }
                }
            }),
        }
        require("rust-tools").setup(rustopts)
        server:attach_buffers()
    else
        server:setup(opts)
    end
end)

In the above example, I'm disabling postfix completions, and enabling clippy.

@williamboman
Copy link
Contributor

williamboman commented Dec 8, 2021

👍 I added this to nvim-lsp-installer's Wiki here yesterday, feel free to update it if you discover any problems/improvements

edit: This Wiki page has since been removed. With the new setup mechanism in nvim-lsp-installer there is no special interaction needed - just setup rust-tools as you would normally!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants