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

IllegalArgumentException in URI with neovim 0.10.0 #656

Closed zbaylin closed 1 month ago

zbaylin commented 1 month ago

LSP client configuration

jdtls.lua:

local jdtls = require("jdtls")
local jdtls_setup = require("jdtls.setup")
local lsp_helpers = require("lsp_helpers")
local cmp_nvim_lsp = require("cmp_nvim_lsp")
local utils = require("utils")

local on_attach_generic = lsp_helpers.on_attach_generic

local home = os.getenv("HOME")

local jdtls_config_file = io.open(home .. "/.jdtls.json")

local jdtls_config = nil

if jdtls_config_file ~= nil then
  local content = jdtls_config_file:read("*a")
  jdtls_config_file:close()
  jdtls_config = vim.json.decode(content)
end

if jdtls_config ~= nil then
  local jdtls_path = jdtls_config.jdtls_path
  local system = "mac" -- TODO:  make this configurable
  local config_path = vim.fn.glob(jdtls_path .. "/config_" .. system)
  local equinox_launcher_path = vim.fn.glob(jdtls_path .. "/plugins/org.eclipse.equinox.launcher_*.jar")

  local extendedClientCapabilities = jdtls.extendedClientCapabilities
  extendedClientCapabilities.resolveAdditionalTextEditsSupport = true

  local root_dir = jdtls_setup.find_root({ "gradlew", "build.gradle", "settings.gradle" })
  local project_name = vim.fn.fnamemodify(root_dir, ":p:h:t")
  local workspace_dir = vim.fn.stdpath("cache") .. "/jdtls/" .. project_name

  local config = {
    cmd = {
      vim.fn.expand(jdtls_config.java_home .. "/bin/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",
      "-Xmx1g",
      "--add-modules=ALL-SYSTEM",
      "--add-opens",
      "java.base/java.util=ALL-UNNAMED",
      "--add-opens",
      "java.base/java.lang=ALL-UNNAMED",

      "-javaagent:" .. jdtls_config.lombok_path,

      "-jar",
      equinox_launcher_path,

      "-configuration",
      config_path,

      "-data",
      workspace_dir
    },

    root_dir = root_dir,

    capabilities = cmp_nvim_lsp.default_capabilities(),

    settings = {
      java = {
        server = { launchMode = "Hybrid" },
        eclipse = { downloadSources = true },
        maven = { downloadSources = true },
        references = { includeDecompiledSources = true },
        implementationsCodeLens = { enabled = false },
        referenceCodeLens = { enabled = false },
        signatureHelp = {
          enabled = true,
          description = {
            enabled = true
          }
        },
        inlayHints = {
          parameterNames = {
            enabled = "all"
          }
        },
        sources = {
          organizeImports = {
            starThreshold = 9999,
            staticStarThreshold = 9999,
          }
        },
        configuration = {
          runtimes = jdtls_config.runtimes
        },
      },
    },
    init_options = {
      bundles = {},
      extendedClientCapabilities = capabilities
    },
    on_attach = on_attach_generic
  }

  vim.api.nvim_create_autocmd("FileType", {
    pattern = "java",
    callback = function()
      vim.cmd("set shiftwidth=4 tabstop=4")
      jdtls.start_or_attach(config)
    end
  })

end

.jdtls.json

{
  "jdtls_path": "/Users/zbaylin/Downloads/jdt-language-server-1.35.0-202404251256/",
  "java_home": "/Users/zbaylin/.asdf/installs/java/openjdk-20/",
  "lombok_path": "/Users/zbaylin/Downloads/lombok.jar",
  "runtimes": [
    {
      "name": "JavaSE-11",
      "path": "/Users/zbaylin/.asdf/installs/java/corretto-11.0.22.7.1/"
    }
  ]
}

Eclipse.jdt.ls version

1.35.0

Steps to Reproduce

This occurs with any Java file I open. I'm primarily working with gradle.

Expected Result

The LSP server to start.

Actual Result

There is a runtime exception in JDTLS:

May 23, 2024, 10:22:46 AM Expected scheme-specific part at index 5: file:
Expected scheme-specific part at index 5: file:
java.net.URISyntaxException: Expected scheme-specific part at index 5: file:
    at java.base/java.net.URI$Parser.fail(URI.java:2963)
    at java.base/java.net.URI$Parser.failExpecting(URI.java:2969)
    at java.base/java.net.URI$Parser.parse(URI.java:3169)
    at java.base/java.net.URI.<init>(URI.java:786)
    at org.eclipse.jdt.ls.core.internal.ResourceUtils.canonicalFilePathFromURI(ResourceUtils.java:226)
    at org.eclipse.jdt.ls.core.internal.handlers.BaseInitHandler.handleInitializationOptions(BaseInitHandler.java:100)
    at org.eclipse.jdt.ls.core.internal.handlers.InitHandler.handleInitializationOptions(InitHandler.java:110)
    at org.eclipse.jdt.ls.core.internal.handlers.BaseInitHandler.initialize(BaseInitHandler.java:64)
    at org.eclipse.jdt.ls.core.internal.handlers.JDTLanguageServer.initialize(JDTLanguageServer.java:284)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$recursiveFindRpcMethods$0(GenericEndpoint.java:65)
    at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.request(GenericEndpoint.java:120)
    at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleRequest(RemoteEndpoint.java:272)
    at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:201)
    at org.eclipse.jdt.ls.core.internal.ParentProcessWatcher.lambda$1(ParentProcessWatcher.java:144)
    at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:194)
    at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:94)
    at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:577)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1623)

May 23, 2024 10:22:46 AM org.eclipse.lsp4j.jsonrpc.RemoteEndpoint fallbackResponseError
SEVERE: Internal error: java.lang.reflect.InvocationTargetException
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$recursiveFindRpcMethods$0(GenericEndpoint.java:67)
    at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.request(GenericEndpoint.java:120)
    at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleRequest(RemoteEndpoint.java:272)
    at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:201)
    at org.eclipse.jdt.ls.core.internal.ParentProcessWatcher.lambda$1(ParentProcessWatcher.java:144)
    at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:194)
    at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:94)
    at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:577)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1623)
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$recursiveFindRpcMethods$0(GenericEndpoint.java:65)
    ... 12 more
Caused by: java.lang.IllegalArgumentException: URI has an authority component
    at java.base/sun.nio.fs.UnixUriUtils.fromUri(UnixUriUtils.java:54)
    at java.base/sun.nio.fs.UnixFileSystemProvider.getPath(UnixFileSystemProvider.java:125)
    at java.base/java.nio.file.Path.of(Path.java:204)
    at java.base/java.nio.file.Paths.get(Paths.java:98)
    at org.eclipse.jdt.ls.core.internal.ResourceUtils.canonicalFilePathFromURI(ResourceUtils.java:230)
    at org.eclipse.jdt.ls.core.internal.handlers.BaseInitHandler.handleInitializationOptions(BaseInitHandler.java:100)
    at org.eclipse.jdt.ls.core.internal.handlers.InitHandler.handleInitializationOptions(InitHandler.java:110)
    at org.eclipse.jdt.ls.core.internal.handlers.BaseInitHandler.initialize(BaseInitHandler.java:64)
    at org.eclipse.jdt.ls.core.internal.handlers.JDTLanguageServer.initialize(JDTLanguageServer.java:284)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    ... 14 more

It appears this comes from canonicalFilePathFromURI, which I imagine is being passed in from neovim.

zbaylin commented 1 month ago

After doing some more digging, it looks like this is a result of jdtls.setup's find_root returning a relative path (i.e. .) in neovim 0.10.0 vs an absolute one in previous versions. Replacing

local root_dir = jdtls_setup.find_root({ "gradlew", "build.gradle", "settings.gradle" })

with

local root_dir = vim.fn.fnamemodify(jdtls_setup.find_root({ "gradlew", "build.gradle", "settings.gradle" }), ":p")

fixes the issue.

However I still think this is a bug, I can try to make a PR to fix it.

mfussenegger commented 1 month ago

local root_dir = jdtls_setup.find_root({ "gradlew", "build.gradle", "settings.gradle" }) should be called within the FileType event, otherwise it gets executed the time you open nvim/source the file, which could be too early.

This change here is probably responsible - although I'm a bit surprised this worked before for you:

https://github.com/mfussenegger/nvim-jdtls/blob/29255ea26dfb51ef0213f7572bff410f1afb002d/lua/jdtls/setup.lua#L94-L100

My plan is actually to deprecate and remove the find_root helper at some point in the future and refer to vim.fs.root instead.

mfussenegger commented 1 month ago

Reverted the change for now, but you should probably still update your configuration.

There's also a PR on neovim to adapt the vim.fs.root behavior: https://github.com/neovim/neovim/pull/28964