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

Formatting doesn't adhere to the provided formatter_settings.xml #672

Closed Rahmerh closed 1 month ago

Rahmerh commented 1 month ago

LSP client configuration

local bundles = {}

local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:t")
local workspace_dir = os.getenv("HOME") .. "/.local/share/nvim/jdtls/data/" .. project_name

vim.list_extend(
    bundles,
    vim.split(
        vim.fn.glob(os.getenv("HOME") .. "/.local/share/nvim/mason/packages/java-test/extension/server/*.jar"),
        "\n"
    )
)
vim.list_extend(
    bundles,
    vim.split(
        vim.fn.glob(
            os.getenv("HOME")
            ..
            "/.local/share/nvim/mason/packages/java-debug-adapter/extension/server/com.microsoft.java.debug.plugin-*.jar"
        ),
        "\n"
    )
)

local config = {
    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",
        "-Xms1g",
        "-javaagent:" .. os.getenv("HOME") .. "/.config/nvim/lombok/lombok.jar",
        "--add-modules=ALL-SYSTEM",
        "--add-opens",
        "java.base/java.util=ALL-UNNAMED",
        "--add-opens",
        "java.base/java.lang=ALL-UNNAMED",
        "-jar",
        os.getenv("HOME")
        .. "/.local/share/nvim/mason/packages/jdtls/plugins/org.eclipse.equinox.launcher_1.6.600.v20231106-1826.jar",
        "-configuration",
        os.getenv("HOME") .. "/.local/share/nvim/mason/packages/jdtls/config_linux",
        "-data",
        workspace_dir,
    },
    root_dir = require('jdtls.setup').find_root({ '.git' }),
    settings = {
        ['java.format.settings.url'] = vim.fn.getcwd() .. "/formatter-settings.xml",
        java = {
            eclipse = {
                downloadSources = true,
            },
            configuration = {
                updateBuildConfiguration = "interactive",
            },
            maven = {
                downloadSources = true,
                updateSnapshots = true
            },
            implementationsCodeLens = {
                enabled = true,
            },
            referencesCodeLens = {
                enabled = true,
            },
            references = {
                includeDecompiledSources = true,
            },
            format = {
                enabled = true
            },
            saveActions = {
                organizeImports = true
            },
            autobuild = {
                enabled = true
            },
            sources = {
                organizeImports = {
                    starThreshold = 9999,
                    staticStarThreshold = 9999,
                },
            },
            contentProvider = { preferred = "fernflower" },
            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.*",
                },
            },
        },
    },
    sources = {
        organizeImports = {
            starThreshold = 9999,
            staticStarThreshold = 9999,
        },
    },
    init_options = {
        bundles = bundles,
    },
}

vim.api.nvim_create_autocmd({ "BufWritePost" }, {
    pattern = { "*.java" },
    callback = function()
        vim.lsp.codelens.refresh()
    end,
})
require("jdtls").start_or_attach(config)

config['on_attach'] = function(client, bufnr)
    require('jdtls').setup_dap({ hotcodereplace = 'auto' })
end

require('jdtls.ui').pick_one_async = function(items, prompt, label_fn, cb)
    local opts = {}
    pickers.new(opts, {
        prompt_title    = prompt,
        finder          = finders.new_table {
            results = items,
            entry_maker = function(entry)
                return {
                    value = entry,
                    display = label_fn(entry),
                    ordinal = label_fn(entry),
                }
            end,
        },
        sorter          = sorters.get_generic_fuzzy_sorter(),
        attach_mappings = function(prompt_bufnr)
            actions.goto_file_selection_edit:replace(function()
                local selection = actions.get_selected_entry(prompt_bufnr)
                actions.close(prompt_bufnr)

                cb(selection.value)
            end)

            return true
        end,
    }):find()
end

vim.cmd(
    "command! -buffer -nargs=? -complete=custom,v:lua.require'jdtls'._complete_compile JdtCompile lua require('jdtls').compile(<f-args>)")
vim.cmd(
    "command! -buffer -nargs=? -complete=custom,v:lua.require'jdtls'._complete_set_runtime JdtSetRuntime lua require('jdtls').set_runtime(<f-args>)")
vim.cmd("command! -buffer JdtUpdateConfig lua require('jdtls').update_project_config()")
vim.cmd("command! -buffer JdtBytecode lua require('jdtls').javap()")

Eclipse.jdt.ls version

1.37.0

Steps to Reproduce

When I use this small code snippet:

public class test {
    public void methodWithParameters(
            String test,  
        String test2, 
        String test3
    ){

    }
}

And I use the following format settings:

<code_scheme name="SFStyle" version="173">
  <JavaCodeStyleSettings>
    <option name="ANNOTATION_PARAMETER_WRAP" value="5" />
    <option name="NEW_LINE_AFTER_LPAREN_IN_ANNOTATION" value="true" />
    <option name="RPAREN_ON_NEW_LINE_IN_ANNOTATION" value="true" />
    <option name="LAYOUT_STATIC_IMPORTS_SEPARATELY" value="false" />
    <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="100" />
    <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="100" />
    <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
      <value />
    </option>
    <option name="IMPORT_LAYOUT_TABLE">
      <value>
        <package name="" withSubpackages="true" static="false" />
        <emptyLine />
        <package name="javax" withSubpackages="false" static="false" />
        <package name="java" withSubpackages="false" static="false" />
        <emptyLine />
      </value>
    </option>
    <option name="MULTI_CATCH_TYPES_WRAP" value="5" />
    <option name="ALIGN_TYPES_IN_MULTI_CATCH" value="false" />
    <option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
    <option name="JD_P_AT_EMPTY_LINES" value="false" />
  </JavaCodeStyleSettings>
  <codeStyleSettings language="JAVA">
    <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
    <option name="ALIGN_MULTILINE_RESOURCES" value="false" />
    <option name="ALIGN_MULTILINE_FOR" value="false" />
    <option name="CALL_PARAMETERS_WRAP" value="5" />
    <option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
    <option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
    <option name="METHOD_PARAMETERS_WRAP" value="5" />
    <option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
    <option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
    <option name="RESOURCE_LIST_WRAP" value="5" />
    <option name="RESOURCE_LIST_LPAREN_ON_NEXT_LINE" value="true" />
    <option name="RESOURCE_LIST_RPAREN_ON_NEXT_LINE" value="true" />
    <option name="EXTENDS_LIST_WRAP" value="5" />
    <option name="THROWS_LIST_WRAP" value="5" />
    <option name="EXTENDS_KEYWORD_WRAP" value="1" />
    <option name="THROWS_KEYWORD_WRAP" value="1" />
    <option name="METHOD_CALL_CHAIN_WRAP" value="5" />
    <option name="BINARY_OPERATION_WRAP" value="1" />
    <option name="TERNARY_OPERATION_WRAP" value="1" />
    <option name="FOR_STATEMENT_WRAP" value="5" />
    <option name="FOR_STATEMENT_LPAREN_ON_NEXT_LINE" value="true" />
    <option name="FOR_STATEMENT_RPAREN_ON_NEXT_LINE" value="true" />
    <option name="ARRAY_INITIALIZER_WRAP" value="5" />
    <option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true" />
    <option name="ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE" value="true" />
    <option name="ASSIGNMENT_WRAP" value="1" />
    <option name="WRAP_COMMENTS" value="true" />
    <option name="ASSERT_STATEMENT_WRAP" value="1" />
    <option name="IF_BRACE_FORCE" value="1" />
    <option name="DOWHILE_BRACE_FORCE" value="1" />
    <option name="WHILE_BRACE_FORCE" value="1" />
    <option name="FOR_BRACE_FORCE" value="1" />
    <option name="PARAMETER_ANNOTATION_WRAP" value="1" />
    <option name="VARIABLE_ANNOTATION_WRAP" value="1" />
    <option name="ENUM_CONSTANTS_WRAP" value="5" />
  </codeStyleSettings>
</code_scheme>

And I simply format using: lua vim.lsp.buf.format({ async = false })

Expected Result

Due to the following 2 lines:

    <option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
    <option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />

I expected it would leave the ) bracket on the next line

Actual Result

Instead, it gets formatted like this:

public class test {
    public void methodWithParameters(
            String test,
            String test2,
            String test3) {
    }
}

I'm assuming I have something somewhere configured incorrectly, please let me know if this is something on my end

For reference, my full nvim configuration can be found here: https://github.com/Rahmerh/dotfiles/tree/main/home/.config/nvim

Thanks in advance for your help!

apoorvshah10 commented 1 month ago

I do have similar issue then I went down a rabbit hole and finally found this: Indent issue

My workaround, using nvim for editing file and using intellij just for format.. I know its bad but thats all I have :)

rogeriofrsouza commented 1 month ago

This should be moved to a Discussion, as this is a problem related to your configuration and not an actual issue in the plugin.

Btw why don't you set the url inside the format table? And also, can you check the log output of the LSP?

format = {
  enabled = true,
  settings = {
    url = vim.fn.getcwd() .. "/formatter-settings.xml",
  },
},

If it doesn't work, this could be an issue with the xml file. The LSP expects all the settings. Partials are ignored šŸ˜¢ https://github.com/eclipse-jdtls/eclipse.jdt.ls/issues/3108

Rahmerh commented 1 month ago

I'm sorry, I wasn't sure at the time of creating this issue if it was due to my configuration or an issue in the project. I'm not sure how to move this to a discussion but yes, this can be moved.

I tried the configuration you provided, but no luck.

I did check the logs and I found this bit:

[ERROR][2024-07-24 07:32:09] ...lsp/handlers.lua:623    "24 Jul 2024, 07:32:09 Illegal character in opaque part at index 2: C:\\Users\\<REDACTED-PATH>\\formatter-settings.xmll\r\n\tat java.base/java.net.URI$Parser.fail(URI.java:2995)\r\n\tat java.base/java.net.URI$Parser.checkChars(URI.java:3166)\r\n\tat java.base/java.net.URI$Parser.parse(URI.java:3202)\r\n\tat java.base/java.net.URI.<init>(URI.java:645)\r\n\tat org.eclipse.jdt.ls.core.internal.managers.StandardProjectsManager.getURIs(StandardProjectsManager.java:561)\r\n\tat org.eclipse.jdt.ls.core.internal.managers.StandardProjectsManager.registerWatchers(StandardProjectsManager.java:512)\r\n\tat org.eclipse.jdt.ls.core.internal.handlers.JDTLanguageServer$2.run(JDTLanguageServer.java:328)\r\n\tat org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)\r\n"
[ERROR][2024-07-24 07:32:09] ...lsp/handlers.lua:623    "24 Jul 2024, 07:32:09 Illegal character in opaque part at index 2: C:\\Users\\<REDACTED-PATH>\\formatter-settings.xml\r\n\tat java.base/java.net.URI$Parser.fail(URI.java:2995)\r\n\tat java.base/java.net.URI$Parser.checkChars(URI.java:3166)\r\n\tat java.base/java.net.URI$Parser.parse(URI.java:3202)\r\n\tat java.base/java.net.URI.<init>(URI.java:645)\r\n\tat org.eclipse.jdt.ls.core.internal.managers.StandardProjectsManager.getURIs(StandardProjectsManager.java:561)\r\n\tat org.eclipse.jdt.ls.core.internal.managers.StandardProjectsManager.registerWatchers(StandardProjectsManager.java:512)\r\n\tat org.eclipse.jdt.ls.core.internal.managers.StandardProjectsManager$1.run(StandardProjectsManager.java:131)\r\n\tat org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)\r\n"

I had to slightly edit the log but the key parts are still here.

It doesn't tell me which line this is on, but it's something I haven't noticed before. Any clues what this could be?

Edit: Turns out I'm an idiot! I was using the intellij xml formatter settings, once I exported it as eclipse settings it finally worked! Turns out I had to select a profile for it to work, which didn't exist in intellij's formatter settings. Thanks for the help, I'll close the issue!

rogeriofrsouza commented 1 month ago

Hey good to know it was solved šŸŽ‰