mfussenegger / nvim-jdtls

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

The project was not built since its build path is incomplete #451

Closed ferranmarlet closed 1 year ago

ferranmarlet commented 1 year ago

LSP client configuration

First, thank you very much to anyone looking into this :bow:

local config = {
    flags = {
        debounce_text_changes = 80,
    },
    on_attach = on_attach,
    root_dir = root_dir,
    settings = {
        java = {
            format = {
                settings = {
                    url = "/.local/share/eclipse/eclipse-java-google-style.xml",
                    profile = "GoogleStyle",
                },
            },
            signatureHelp = { enabled = true },
            contentProvider = { preferred = 'fernflower' },
            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.*"
                },
                filteredTypes = {
                    "com.sun.*",
                    "io.micrometer.shaded.*",
                    "java.awt.*",
                    "jdk.*", "sun.*",
                },
            },
            sources = {
                organizeImports = {
                    starThreshold = 9999;
                    staticStarThreshold = 9999;
                },
            },
            codeGeneration = {
                toString = {
                    template = "${object.className}{${member.name()}=${member.value}, ${otherMembers}}"
                },
                hashCodeEquals = {
                    useJava7Objects = true,
                },
                useBlocks = true,
            },
            configuration = {
                runtimes = {
                    {
                        name = "JavaSE-19",
                        path = home .. "/.sdkman/candidates/java/current"
                    },
                }
            }
        }
    },
    cmd = {
        '/home/myuser/.sdkman/candidates/java/current/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',
        '-Xmx4g',
        '--add-modules=ALL-SYSTEM',
        '--add-opens', 'java.base/java.util=ALL-UNNAMED',
        '--add-opens', 'java.base/java.lang=ALL-UNNAMED',
        '-jar', '/home/myuser/apps/jdtls/plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar',
        '-configuration', '/home/myuser/apps/jdtls/config_linux',
        '-data', workspace_folder,
    },
}

Eclipse.jdt.ls version

No response

Steps to Reproduce

JDTLS works as expected in my system (Ubuntu 22.04), I installed the snapshot jdt-language-server-1.22.0-202303170534, and if I run LspInfo I see:

Detected filetype:   java
 1 client(s) attached to this buffer: 
 Client: jdtls (id: 1, bufnr: [151, 4, 6])
    filetypes:       
    autostart:       false
    root directory:  /home/myuser/projects/myproject
    cmd:             /home/myuser/.sdkman/candidates/java/current/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 -Xmx4g --add-modules=ALL-SYSTEM --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED -jar /home/myuser/apps/jdtls/plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar -configuration /home/myuser/apps/jdtls/config_linux -data /home/myuser/.local/share/eclipse/myproject

Which I think is correct, and it works on several simple projects I have tried. But in some projects fails to fins certain classes, maybe due the project and package structure.

In a project using gradle 7.5.1 that has the following directory structure:

source-code
    application
        src
            main/java/com/company/project
                ClassA
    domain
        src
            main/java/com/company/project
                ClassB
    infrastructure
        src
            main/java/com/company/project
                ClassC

Where ClassA, ClassB and ClassC belong to the same package, let's say that all of them start with:

package com.company.project;

And then, try to use one class inside another, for example in ClassA:

public void example() {
    ClassB b = new ClassB();
}

Expected Result

I expected to see no errors or warnings, and I expected autocompletion to work for ClassB methods.

Actual Result

I see a diagnostic that says: Java: ClassB cannot be resolved to a type. And completion for ClassB doesn't work.

Also, if I try to run:

:lua require('jdtls').compile('full')

I get the error:

The project was not built since its build path is incomplete.
Cannot find the class file for ClassB.
Fix the build path then try building this project

But all the information I found to fix the build path refers to the eclipse UI.

Also, in the LspLog I see lots of messages like:

[ERROR][2023-03-20 12:07:17] ...lsp/handlers.lua:485
"Mar 20, 2023, 12:07:17 PM Error occured while building workspace.
Details: message: The project was not built since its build path is incomplete.
Cannot find the class file for ClassB. Fix the build path then try building this project;
code: 0; resource: /home/myuser/projects/myproject/source-code/application
message: The type ClassB cannot be resolved. It is indirectly referenced from required type com.company.project.ClassA;
code: 16777563;

This message is repeated several times, for every class in the project including another class in the same package but in a folder outside of the /application folder.

Nothing changes if I restart the Lsp or if I delete the project's jdtls workspace folder.

Thank you very much to anyone who took the time to read this far :pray:

mfussenegger commented 1 year ago

You'll need some sort of gradle or maven configuration that sets up the dependencies accordingly.

ferranmarlet commented 1 year ago

I couldn't make it work, but I think that it is because I'm struggling to set up gadle dependencies correctly in a very large project. I think that If I cannot fix that by tomorrow, I will close the issue.

Thank you for taking your time to look into this.

ferranmarlet commented 1 year ago

I'm closing the issue, and I will keep trying to fix my gradle setup whenever I can. Thank you for the guidance :)

amplexus commented 1 year ago

For anyone else, I got the same error but wasn't using multi-modules. Purging the project-specific workspace directory (the one passed to the jdtls java command via the -data argument) made the error go away.

Just expanding on how I think it came about, I got some "import ... cannot be resolved" errors reported by JDTLS on my code the very first time I opened a JAVA file up in a freshly checked-out GIT project that I never built before (so the JAR dependencies weren't downloaded by maven yet).

Then I built the project and reopened the JAVA source in neovim and could still see the "import ... cannot be resolved" error . Snooping the LspLog I saw this error, and purging the workspace directory made it go away and also made the falsely reported "import ... cannot be resolved" errors go away too.

I'm using the AstroNvim JAVA pack (which uses the wonderful JDTLS) without modification.