mfussenegger / nvim-jdtls

Extensions for the built-in LSP support in Neovim for eclipse.jdt.ls
GNU General Public License v3.0
1.04k stars 61 forks source link

Go to definition emits errors and start another jdt instance upon keypress of a third party dependency and then open the definition #421

Closed juhaku closed 1 year ago

juhaku commented 1 year ago

LSP client configuration

    on_attach = function(client, bufnr)
        require("jdtls").setup_dap({ hotcodereplace = "auto" })
        require("jdtls.dap").setup_dap_main_class_configs()
        require("jdtls.setup").add_commands()

        lsp_config.on_attach(client, bufnr)
    end,
```lua

```lua
-- lsp_config .....
local on_attach = function(client, bufnr)
    if client.server_capabilities.documentSymbolProvider then
        navic.attach(client, bufnr)
    end

    require("illuminate").on_attach(client)

    vim.api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc")

    local bufopts = { noremap = true, silent = true, buffer = bufnr }
    vim.keymap.set("n", "gD", vim.lsp.buf.declaration, bufopts)
    vim.keymap.set("n", "gd", vim.lsp.buf.definition, bufopts)

    vim.keymap.set("n", "K", vim.lsp.buf.hover, bufopts)
    vim.keymap.set("n", "gi", vim.lsp.buf.implementation, bufopts)

    vim.keymap.set({ "n", "i" }, "<C-k>", vim.lsp.buf.signature_help, bufopts)
    vim.keymap.set("n", "<leader>wa", vim.lsp.buf.add_workspace_folder, bufopts)
    vim.keymap.set("n", "<leader>wr", vim.lsp.buf.remove_workspace_folder, bufopts)
    vim.keymap.set("n", "<leader>wl", function()
        print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
    end, bufopts)
    vim.keymap.set("n", "td", vim.lsp.buf.type_definition, bufopts)

    vim.keymap.set("n", "gs", vim.lsp.buf.document_symbol, bufopts)

    vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, bufopts)
    vim.keymap.set("n", "<A-CR>", vim.lsp.buf.code_action, bufopts)
    vim.keymap.set("v", "<A-CR>", vim.lsp.buf.code_action, bufopts)
    vim.keymap.set("n", "gr", vim.lsp.buf.references, bufopts)

    vim.keymap.set("n", "<leader>f", function()
        vim.lsp.buf.format({
            filter = function(c)
                return c.name ~= "tsserver" or c.name ~= "gopls" or c.name ~= "sumneko_lua" or c.name ~= "eslint"
            end,
            async = true,
        })
    end, bufopts)
end

Eclipse.jdt.ls version

1.19.0

Steps to Reproduce

Press go to definition on third party class. E.g. any class that is coming from another maven dependency.

Expected Result

Would directly go to the definition of a dependency.

Actual Result

It will emit errors and start another jdt language server and then go to the definition.

No active LSP client found to use for jdt:// document
Error executing vim.schedule lua callback: ...acker/start/lualine.nvim/lua/lualine/utils/nvim_opts.lua:77: E539: Illegal character <C>
stack traceback:
        [C]: in function 'nvim_win_set_option'
        ...acker/start/lualine.nvim/lua/lualine/utils/nvim_opts.lua:77: in function 'setter_fn'
        ...acker/start/lualine.nvim/lua/lualine/utils/nvim_opts.lua:50: in function 'set_opt'
        ...acker/start/lualine.nvim/lua/lualine/utils/nvim_opts.lua:74: in function 'set'
        ...nvim/site/pack/packer/start/lualine.nvim/lua/lualine.lua:433: in function 'refresh'
        ...nvim/site/pack/packer/start/lualine.nvim/lua/lualine.lua:343: in function <...nvim/site/pack/packer/start/lualine.nvim/lua/lualine.lua:342>
Error executing vim.schedule lua callback: ...acker/start/lualine.nvim/lua/lualine/utils/nvim_opts.lua:77: E539: Illegal character <C>
mfussenegger commented 1 year ago

The errors are from lualine, not from jdtls?

juhaku commented 1 year ago

Oh yes, indeed. it seems to be related to this: https://github.com/nvim-lualine/lualine.nvim/issues/872 which itself is an upstream bug in neovim https://github.com/neovim/neovim/issues/19464.

But there is a weird issue, when I press the go to definition on a third party dependency it will start another jdt language server and then the diagnostics will get messed up in the buffer.

mfussenegger commented 1 year ago

The start_or_attach function should ensure that it attaches the existing client to jdt:// buffers instead of staring a new one.

It's not part of your pasted configuration so maybe you're missing that

juhaku commented 1 year ago

It is actually here:

-- This starts a new client & server,
-- or attaches to an existing client & server depending on the `root_dir`.
jdtls.start_or_attach(config)

I was just testing it with another computer, and there it seems working fine. But there I just have a repository with single project layout.

Then I went on to test it again in another computer, where I have a monorepo of multiproject layout. Then I thought that because I opened monorepo instead of opening a single project that whether that makes a difference. But unexpected I dont seem to get the jdt even running, anymore :exploding_head:

Only thing I am getting now is:

Client 2 quit with exit code 13 and signal 0
juhaku commented 1 year ago

If you have a monorepo with multiple projects, should it start a single jdt client per repo or for each an every sub project as seen below?

 Client: jdtls (id: 4, bufnr: [160])
    filetypes:       
    autostart:       false
    root directory:  /home/user/dev/repos/api/maintenance
    cmd:             /usr/lib/jvm/java-17-jdk/bin/java -Declipse.application=org.eclipse.jdt.ls.core.id1 -Dosgi.bundles.defaultStartLevel=4 -Declipse.product=org.eclipse.jdt.ls.core.product -Dlog.level=ALL -Xms4G -javaagent:/home/user/.config/nvim/lib/lombok.jar --add-modules=ALL-SYSTEM --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/user/.local/share/nvim/mason/packages/jdtls/plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar -configuration /home/user/.local/share/nvim/mason/packages/jdtls/config_linux -data /home/user/.config/jdtls/liitepalvelu

 Client: jdtls (id: 3, bufnr: [15, 107])
    filetypes:       
    autostart:       false
    root directory:  Running in single file mode.
    cmd:             /usr/lib/jvm/java-17-jdk/bin/java -Declipse.application=org.eclipse.jdt.ls.core.id1 -Dosgi.bundles.defaultStartLevel=4 -Declipse.product=org.eclipse.jdt.ls.core.product -Dlog.level=ALL -Xms4G -javaagent:/home/user/.config/nvim/lib/lombok.jar --add-modules=ALL-SYSTEM --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/user/.local/share/nvim/mason/packages/jdtls/plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar -configuration /home/user/.local/share/nvim/mason/packages/jdtls/config_linux -data /home/user/.config/jdtls/liitepalvelu

 Client: jdtls (id: 5, bufnr: [169])
    filetypes:       
    autostart:       false
    root directory:  /home/user/dev/repos/liitepalvelu
    cmd:             /usr/lib/jvm/java-17-jdk/bin/java -Declipse.application=org.eclipse.jdt.ls.core.id1 -Dosgi.bundles.defaultStartLevel=4 -Declipse.product=org.eclipse.jdt.ls.core.product -Dlog.level=ALL -Xms4G -javaagent:/home/user/.config/nvim/lib/lombok.jar --add-modules=ALL-SYSTEM --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/user/.local/share/nvim/mason/packages/jdtls/plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar -configuration /home/user/.local/share/nvim/mason/packages/jdtls/config_linux -data /home/user/.config/jdtls/liitepalvelu

I have Java 17 and 11 installed, but it seems that it only works with java 11 or somehow does not launch for project with java 17. How does it select the runtime for the project? In config you can define the as many runetimes as one has available.

mfussenegger commented 1 year ago

That depends on how you set the root_dir. It will start one language server per unique root_dir.

juhaku commented 1 year ago

Yeah,

I seemed to get this actually working with help of a troubleshooting tip for removing the jdtls data and restart. Though I needed to remove the folder manually, because from nvim it said that there was no attached jdt clients so cannot proceed with the :JdtWipeDataAndRestart

Though it seems bit fragile. If I change between branches and they have different set of files available and I have a buffer open for a file that exists in another branch but not in the first one. It easily get's to the corrupt state and I need to wipe data, and restart if not then reopen nvim again, which seems bit counter intuitive. Do you have any insight regarding this?

Also the jdt quiting immediately, in one repository was caused because it was first run with java 11 and then in between I changed it to java 17. And then the outcome was that it was never fully changed. But when I removed the data dir and the configs the jdt adds (eclipse files .classpaht, .project, .settings) it started working upon next nvim restart.

I believe this issue can be closed.

mfussenegger commented 1 year ago

Though it seems bit fragile. If I change between branches and they have different set of files available and I have a buffer open for a file that exists in another branch but not in the first one. It easily get's to the corrupt state and I need to wipe data, and restart if not then reopen nvim again, which seems bit counter intuitive. Do you have any insight regarding this?

It shouldn't corrupt the state, usually restart should be enough. The reason is that the server isn't informed about the file changes by the client, because the client doesn't detect them. This should improve once https://github.com/neovim/neovim/pull/21293 is finished.