mfussenegger / nvim-jdtls

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

java-debug, java-test and custom lsp configuration no longer working since JDTLS update #629

Closed RononDex closed 3 months ago

RononDex commented 4 months ago

LSP client configuration

local home = os.getenv("HOME")
local java_cmds = vim.api.nvim_create_augroup('java_cmds', { clear = true })
local cache_vars = {}

local root_files = {
    '.git',
    'mvnw',
    'gradlew',
    'build.gradle',
}

local features = {
    -- change this to `true` to enable codelens
    codelens = true,

    -- change this to `true` if you have `nvim-dap`,
    -- `java-test` and `java-debug-adapter` installed
    debugger = true,
}

local function get_jdtls_paths()
    if cache_vars.paths then
        return cache_vars.paths
    end

    local path = {}

    path.data_dir = vim.fn.stdpath('cache') .. '/nvim-jdtls'

    local jdtls_install = require('mason-registry')
        .get_package('jdtls')
        :get_install_path()

    path.java_agent = jdtls_install .. '/lombok.jar'
    path.launcher_jar = vim.fn.glob(jdtls_install .. '/plugins/org.eclipse.equinox.launcher_*.jar')

    if vim.fn.has('mac') == 1 then
        path.platform_config = jdtls_install .. '/config_mac'
    elseif vim.fn.has('unix') == 1 then
        path.platform_config = jdtls_install .. '/config_linux'
    elseif vim.fn.has('win32') == 1 then
        path.platform_config = jdtls_install .. '/config_win'
    end

    path.bundles = {}

    ---
    -- Include java-test bundle if present
    ---
    local java_test_path = require('mason-registry')
        .get_package('java-test')
        :get_install_path()

    local java_test_bundle = vim.split(
        vim.fn.glob(java_test_path .. '/extension/server/*.jar'),
        '\n'
    )

    if java_test_bundle[1] ~= '' then
        vim.list_extend(path.bundles, java_test_bundle)
    end

    ---
    -- Include java-debug-adapter bundle if present
    ---
    local java_debug_path = require('mason-registry')
        .get_package('java-debug-adapter')
        :get_install_path()

    local java_debug_bundle = vim.split(
        vim.fn.glob(java_debug_path .. '/extension/server/com.microsoft.java.debug.plugin-*.jar'),
        '\n'
    )

    if java_debug_bundle[1] ~= '' then
        vim.list_extend(path.bundles, java_debug_bundle)
    end

    ---
    -- Useful if you're starting jdtls with a Java version that's
    -- different from the one the project uses.
    ---
    path.runtimes = {
        -- Note: the field `name` must be a valid `ExecutionEnvironment`,
        -- you can find the list here:
        -- https://github.com/eclipse/eclipse.jdt.ls/wiki/Running-the-JAVA-LS-server-from-the-command-line#initialize-request
        {
            name = "JavaSE-1.8",
            path = "/usr/lib/jvm/java-8-openjdk"
        },
        {
            name = "JavaSE-11",
            path = "/usr/lib/jvm/java-11-openjdk"
        },
        {
            name = "JavaSE-17",
            path = "/usr/lib/jvm/java-17-openjdk",
        },
        {
            name = "JavaSE-21",
            path = "/usr/lib/jvm/java-21-openjdk",
            default = true
        }
    }

    cache_vars.paths = path

    return path
end

local function enable_codelens(bufnr)
    pcall(vim.lsp.codelens.refresh)

    vim.api.nvim_create_autocmd('BufWritePost', {
        buffer = bufnr,
        group = java_cmds,
        desc = 'refresh codelens',
        callback = function()
            pcall(vim.lsp.codelens.refresh)
        end,
    })
end

local function enable_debugger(bufnr)
    require('jdtls').setup_dap({ hotcodereplace = 'auto' })

    local opts = { buffer = bufnr }
    vim.keymap.set('n', '<leader>df', "<cmd>lua require('jdtls').test_class()<cr>", opts)
    vim.keymap.set('n', '<leader>dn', "<cmd>lua require('jdtls').test_nearest_method()<cr>", opts)
end

local function jdtls_on_attach(client, bufnr)
    if features.debugger then
        enable_debugger(bufnr)
    end

    if features.codelens then
        enable_codelens(bufnr)
    end

    -- The following mappings are based on the suggested usage of nvim-jdtls
    -- https://github.com/mfussenegger/nvim-jdtls#usage

    local opts = { buffer = bufnr }
    vim.keymap.set('n', '<leader>rt', "<cmd>lua require('jdtls').test_nearest_method()<cr>", opts)
end

local function jdtls_setup(event)
    local jdtls = require('jdtls')

    local path = get_jdtls_paths()
    local data_dir = path.data_dir .. '/' .. vim.fn.fnamemodify(vim.fn.getcwd(), ':p:h:t')

    if cache_vars.capabilities == nil then
        jdtls.extendedClientCapabilities.resolveAdditionalTextEditsSupport = true

        local ok_cmp, cmp_lsp = pcall(require, 'cmp_nvim_lsp')
        cache_vars.capabilities = vim.tbl_deep_extend(
            'force',
            vim.lsp.protocol.make_client_capabilities(),
            ok_cmp and cmp_lsp.default_capabilities() or {}
        )
    end

    -- The command that starts the language server
    -- See: https://github.com/eclipse/eclipse.jdt.ls#running-from-the-command-line
    local cmd = {
        'java',
        '-Declipse.application=org.eclipse.jdt.ls.core.id1',
        '-Dosgi.bundles.defaultStartLevel=4',
        '-Declipse.product=org.eclipse.jdt.ls.core.product',
        '-Dlog.protocol=true',
        '-Dlog.level=ALL',
        '-javaagent:' .. path.java_agent,
        '-Xmx1g',
        '--add-modules=ALL-SYSTEM',
        '--add-opens',
        'java.base/java.util=ALL-UNNAMED',
        '--add-opens',
        'java.base/java.lang=ALL-UNNAMED',
        '-jar',
        path.launcher_jar,
        '-configuration',
        path.platform_config,
        '-data',
        data_dir,
    }

    local lsp_settings = {
        java = {
            -- jdt = {
            --   ls = {
            --     vmargs = "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx1G -Xms100m"
            --   }
            -- },
            eclipse = {
                downloadSources = true,
            },
            configuration = {
                updateBuildConfiguration = 'interactive',
                runtimes = path.runtimes,
                saveActions = {
                    organizeImports = true,
                }
            },
            maven = {
                downloadSources = true,
            },
            implementationsCodeLens = {
                enabled = true,
            },
            referencesCodeLens = {
                enabled = true,
            },
            inlayHints = {
                parameterNames = {
                    enabled = 'all' -- literals, all, none
                }
            },
            format = {
                enabled = true,
                settings = {
                    --   profile = 'asdf'
                    url = home .. "/.config/nvim/eclipse-java-style.xml",
                },
            }
        },
        signatureHelp = {
            enabled = true,
        },
        completion = {
            favoriteStaticMembers = {
                'org.hamcrest.MatcherAssert.assertThat',
                'org.hamcrest.Matchers.*',
                'org.hamcrest.CoreMatchers.*',
                'org.junit.jupiter.api.Assertions.*',
                'java.util.Objects.requireNonNull',
                'java.util.Objects.requireNonNullElse',
                'org.mockito.Mockito.*',
            },
        },
        contentProvider = {
            preferred = 'fernflower',
        },
        extendedClientCapabilities = jdtls.extendedClientCapabilities,
        sources = {
            organizeImports = {
                starThreshold = 9999,
                staticStarThreshold = 9999,
            }
        },
        codeGeneration = {
            toString = {
                template = '${object.className}{${member.name()}=${member.value}, ${otherMembers}}',
            },
            useBlocks = true,
        },
    }

    -- This starts a new client & server,
    -- or attaches to an existing client & server depending on the `root_dir`.
    jdtls.start_or_attach({
        cmd = cmd,
        settings = lsp_settings,
        on_attach = jdtls_on_attach,
        capabilities = cache_vars.capabilities,
        root_dir = jdtls.setup.find_root(root_files),
        flags = {
            allow_incremental_sync = true,
        },
        init_options = {
            bundles = path.bundles,
        },
    })
end

vim.api.nvim_create_autocmd('FileType', {
    group = java_cmds,
    pattern = { 'java' },
    desc = 'Setup jdtls',
    callback = jdtls_setup,
})

Eclipse.jdt.ls version

1.33.0

Steps to Reproduce

Using my config, open any java file and check LspInfo to see if debug and test bundles are loaded and custom config is applied (codelense should be working)

Expected Result

Java-Test and Java-Debug-Adapter should be loaded and codelense along with custom lsp config should work

Actual Result

Following is what I found in LspLog:

[START][2024-03-02 09:07:57] LSP logging initiated
[WARN][2024-03-02 09:07:57] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"
[WARN][2024-03-02 09:07:58] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"
[ERROR][2024-03-02 09:07:59] .../vim/lsp/rpc.lua:734    "rpc"   "java"  "stderr"    "WARNING: Using incubator modules: jdk.incubator.vector, jdk.incubator.foreign\n"
[ERROR][2024-03-02 09:07:59] .../vim/lsp/rpc.lua:734    "rpc"   "java"  "stderr"    "Mar 02, 2024 9:07:59 AM org.apache.aries.spifly.BaseActivator log\nINFO: Registered provider ch.qos.logback.classic.servlet.LogbackServletContainerInitializer of service jakarta.servlet.ServletContainerInitializer in bundle ch.qos.logback.classic\n"
[ERROR][2024-03-02 09:07:59] .../vim/lsp/rpc.lua:734    "rpc"   "java"  "stderr"    "Mar 02, 2024 9:07:59 AM org.apache.aries.spifly.BaseActivator log\nINFO: Registered provider ch.qos.logback.classic.spi.LogbackServiceProvider of service org.slf4j.spi.SLF4JServiceProvider in bundle ch.qos.logback.classic\n"
[ERROR][2024-03-02 09:08:01] ...lsp/handlers.lua:535    "Mar 2, 2024, 9:08:01 AM Failed to load extension bundles \nLoad bundle list\norg.eclipse.core.runtime.CoreException: Load bundle list\n\tat org.eclipse.jdt.ls.core.internal.handlers.BundleUtils.loadBundles(BundleUtils.java:173)\n\tat org.eclipse.jdt.ls.core.internal.handlers.InitHandler.handleInitializationOptions(InitHandler.java:109)\n\tat org.eclipse.jdt.ls.core.internal.handlers.BaseInitHandler.initialize(BaseInitHandler.java:64)\n\tat org.eclipse.jdt.ls.core.internal.handlers.JDTLanguageServer.initialize(JDTLanguageServer.java:284)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:568)\n\tat org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$recursiveFindRpcMethods$0(GenericEndpoint.java:65)\n\tat org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.request(GenericEndpoint.java:120)\n\tat org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleRequest(RemoteEndpoint.java:261)\n\tat org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:190)\n\tat org.eclipse.jdt.ls.core.internal.ParentProcessWatcher.lambda$1(ParentProcessWatcher.java:144)\n\tat org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:194)\n\tat org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:94)\n\tat org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)\n\tat java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)\n\tat java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)\n\tat java.base/java.lang.Thread.run(Thread.java:840)\nContains: Failed to get bundleInfo for bundle from /home/cobra/.local/share/nvim/mason/packages/java-test/extension/server/com.microsoft.java.test.runner-jar-with-dependencies.jar\n"
[WARN][2024-03-02 09:08:05] ...lsp/handlers.lua:137 "The language server jdtls triggers a registerCapability handler despite dynamicRegistration set to false. Report upstream, this warning is harmless"
[ERROR][2024-03-02 09:08:05] ...lsp/handlers.lua:535    "Mar 2, 2024, 9:08:05 AM Command _java.reloadBundles.command not supported on client"
[WARN][2024-03-02 09:08:17] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"
[WARN][2024-03-02 09:09:39] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"
[WARN][2024-03-02 09:11:46] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"
[WARN][2024-03-02 09:12:04] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"
[WARN][2024-03-02 09:12:12] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"
[WARN][2024-03-02 09:12:40] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"
[WARN][2024-03-02 09:12:54] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"
[WARN][2024-03-02 09:14:32] .../lua/vim/lsp.lua:101 "method textDocument/codeLens is not supported by any of the servers registered for the current buffer"

packages are installed in mason: image

mfussenegger commented 4 months ago

Please check the troubleshooting section.

Could be that jdtls can no longer load your project. After an eclipse.jdt.ls update you sometimes have to delete the data directory.

RononDex commented 4 months ago

Thank you, I have tried JdtWipeDataAndRestart already multiple times, sadly it didnt help

mfussenegger commented 3 months ago

The log entries sound a bit suspicious:

[ERROR][2024-03-02 09:07:59] .../vim/lsp/rpc.lua:734    "rpc"   "java"  "stderr"    "Mar 02, 2024 9:07:59 AM org.apache.aries.spifly.BaseActivator log\nINFO: Registered provider ch.qos.logback.classic.servlet.LogbackServletContainerInitializer of service jakarta.servlet.ServletContainerInitializer in bundle ch.qos.logback.classic\n"
[ERROR][2024-03-02 09:07:59] .../vim/lsp/rpc.lua:734    "rpc"   "java"  "stderr"    "Mar 02, 2024 9:07:59 AM org.apache.aries.spifly.BaseActivator log\nINFO: Registered provider ch.qos.logback.classic.spi.LogbackServiceProvider of service org.slf4j.spi.SLF4JServiceProvider in bundle ch.qos.logback.classic\n"

Maybe try with a clean install, check the mason issues or install from tarball or source. Nothing in nvim-jdtls changed that would break it that way and for me the latest jdtls release works fine.

The issue tracker is mainly for feature requests or bugs. I can't help troubleshooting system specific installation issues.