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

Non project files caused setup_dap_main_class_configs to fail #603

Open lbrayner opened 6 months ago

lbrayner commented 6 months ago

vscode.java.resolveMainClass returns ResolutionItems without projectName for non project classes. Thus, calls to vscode.java.resolveJavaExecutable resulted in "Index 1 out of bounds for length 1". This cascaded into vscode.java.resolveClasspath failing with "Failed to resolve classpath: Referenced classpath provider does not exist: org.eclipse.m2e.launchconfig.classpathProvider".

mfussenegger commented 3 months ago

Can you share an example project that triggers this? I'm not sure this is the correct way to deal with this

lbrayner commented 3 months ago

Can you share an example project that triggers this? I'm not sure this is the correct way to deal with this

Any 2 projects will do, but here is the full context. Consider the following init.lua, with nvim-dap and vscode-java-test enabled:

vim.opt.runtimepath:append(vim.fs.normalize("~/.config/nvim/pack/bundle/start/nvim-dap"))
vim.opt.runtimepath:append(vim.fs.normalize("~/.config/nvim/pack/bundle/start/nvim-jdtls"))

local function get_config()
  local java_debug_jar_pattern = vim.fs.joinpath(vim.fn.stdpath("data"),
    "java-debug/com.microsoft.java.debug.plugin/target/com.microsoft.java.debug.plugin-*.jar")
  local vscode_java_test_jar_pattern = vim.fs.joinpath(vim.fn.stdpath("data"), "vscode-java-test/server/*.jar")

  return {
    cmd = {
      vim.fs.normalize("~/.local/lib/jdt-language-server/default/bin/jdtls"),
      "-configuration", vim.fs.normalize("~/.cache/jdtls/config"),
      "-data", vim.fs.normalize("~/.cache/jdtls/workspace"),
    },
    init_options = {
      bundles = (function()
        local bundles = {}

        local java_debug_jars = vim.fn.glob(java_debug_jar_pattern, 1, 1)
        if vim.tbl_count(java_debug_jars) == 1 then
          table.insert(bundles, java_debug_jars[1])
        end

        local vscode_java_test_jars = vim.tbl_filter(function(jar)
          -- https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/2761#issuecomment-1638311201.
          -- vscode-java-test's com.microsoft.java.test.runner-jar-with-dependencies.jar
          -- shouldn't be passed into the bundles setting.
          return not vim.endswith(jar, "com.microsoft.java.test.runner-jar-with-dependencies.jar")
        end, vim.fn.glob(vscode_java_test_jar_pattern, 1, 1))

        vim.list_extend(bundles, vscode_java_test_jars)

        if not vim.tbl_isempty(bundles) then
          return bundles
        end
      end)(),
    },
    root_dir = require("jdtls.setup").find_root({".git", "mvnw", "gradlew"}),
  }
end

local config = get_config()

vim.api.nvim_create_autocmd("FileType", {
  pattern = "java",
  callback = function()
    require("jdtls").start_or_attach(config)
  end,
})

Create file /var/tmp/nvim-jdtls-tests/init.lua with contents above.

Note: java-debug is in ~/.local/share/nvim/java-debug, and vscode-java-test is in ~/.local/share/nvim/vscode-java-test.

Start Neovim with the -u switch:

$ cd /var/tmp/jdtls-tests
[jdtls-tests]$ nvim -u /var/tmp/nvim-jdtls-tests/init.lua src/main/java/FinalExceptions.java

In Neovim, open a Java file outside the root directory:

:vsp /var/tmp/CompletionFailsBeforeDeclaration.java

Then run JdtUpdateDebugConfig. You'll get:

Could not resolve java executable: Index 1 out of bounds for length 1
/var/tmp/jdtls-tests/pom.xml ```xml 4.0.0 local jdtls-tests 0.0.1-SNAPSHOT 21 ${java.version} ${java.version} ```
/var/tmp/CompletionFailsBeforeDeclaration.java ```java import java.util.List; public class CompletionFailsBeforeDeclaration { public static void main(String[] args) { Object unknown = List.of(1, 2); if (unknown instanceof List things) { // things.is Object nothing = null; // things.isEmpty() } } } ```
/var/tmp/jdtls-tests/src/main/java/FinalExceptions.java ```java public class FinalExceptions { public static void main(String[] args) { final Object token = new Object(); try { token.wait(); } catch (InterruptedException e) { e.printStackTrace(); } try { token.wait(); } catch (IllegalMonitorStateException | InterruptedException e) { e.printStackTrace(); } } } ```