local utils = require("utils") local M = {} function M.setup() local jdtls = require("jdtls") local jdtls_dap = require("jdtls.dap") local jdtls_setup = require("jdtls.setup") local lsp_signature = require("lsp_signature") local on_attach = function(ev, bufnr) local opts = { buffer = ev.buf, silent = true } utils.common_mappings(opts) -- Java specific utils.nmapkey("di", jdtls.organize_imports, "Organize imports", opts) utils.nmapkey("dt", jdtls.test_class, "Test class", opts) utils.nmapkey("dn", jdtls.test_nearest_method, "Test nearest method", opts) utils.nvmapkey("dm", jdtls.extract_method, "Extract method", opts) utils.nvmapkey("dv", jdtls.extract_variable, "Extract variable", opts) utils.nvmapkey("dc", jdtls.extract_constant, "Extract constant", opts) jdtls.setup_dap({ hotcodereplace = "auto" }) jdtls_dap.setup_dap_main_class_configs() jdtls_setup.add_commands() -- Create a command `:Format` local to the LSP buffer -- TODO: shortcut vim.api.nvim_buf_create_user_command(bufnr, "Format", function(_) vim.lsp.buf.format() end, { desc = "Format current buffer with LSP" }) lsp_signature.on_attach({ bind = true, padding = "", handler_opts = { border = "rounded", }, hint_prefix = "󱄑 ", }, bufnr) end local home = os.getenv("HOME") local root_dir = jdtls_setup.find_root({ ".git", "mvnw", "gradlew" }) local project_name = vim.fn.fnamemodify(root_dir, ":p:h:t") local nvim_d = home .. "/.local/share/nvim" local mason_d = nvim_d .. "/mason/packages" local jdtls_d = mason_d .. "/jdtls" local cmd = { "/usr/lib/jvm/java-1.21.0-openjdk-amd64/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", "-javaagent:" .. jdtls_d .. "/lombok.jar", "--add-modules=ALL-SYSTEM", "--add-opens", "java.base/java.util=ALL-UNNAMED", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "-jar", vim.fn.glob(jdtls_d .. "/plugins/org.eclipse.equinox.launcher_*.jar", true), "-configuration", jdtls_d .. "/config_linux", "-data", home .. "/.cache/jdtls/workspace/" .. project_name, } local settings = { java = { references = { includeDecompiledSources = true, }, -- TODO: enable format = { enabled = false, settings = { url = vim.fn.stdpath("config") .. "/lang_servers/intellij-java-google-style.xml", profile = "GoogleStyle", }, }, eclipse = { downloadSources = true, }, maven = { downloadSources = true, }, signatureHelp = { enabled = true }, contentProvider = { preferred = "fernflower" }, implementationsCodeLens = { enabled = true, }, import = { gradle = { wrapper = { 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.*", }, filteredTypes = { "com.sun.*", "io.micrometer.shaded.*", "java.awt.*", "jdk.*", "sun.*", }, importOrder = { "java", "javax", "com", "org", }, }, sources = { organizeImports = { starThreshold = 9999, staticStarThreshold = 9999, }, }, codeGeneration = { toString = { template = "${object.className}{${member.name()}=${member.value}, ${otherMembers}}", }, useBlocks = true, }, configuration = { updateBuildConfiguration = "automatic", runtimes = { { name = "JavaSE-17", path = os.getenv("JAVA_17_HOME"), }, { name = "JavaSE-21", path = os.getenv("JAVA_21_HOME"), }, }, }, project = { referencedLibraries = { "**/lib/*.jar", }, }, }, } -- Start Server local jdap_d = mason_d .. "/java-debug-adapter/extension/server" local jtest_d = mason_d .. "/java-test/extension/server" jdtls.start_or_attach({ flags = { allow_incremental_sync = true, }, init_options = { bundles = { vim.fn.glob(jdap_d .. "/com.microsoft.java.debug.plugin-*.jar"), vim.fn.glob(jtest_d .. "/com.microsoft.java.test.plugin-*.jar"), vim.fn.glob(jtest_d .. "/com.microsoft.java.test.runner-*.jar"), -- TODO: pde --vim.fn.glob(home .. "/pde/extension/server/*.jar") }, extendedClientCapabilities = { resolveAdditionalTextEditsSupport = true, }, }, on_init = function(client) client.notify("workspace/didChangeConfiguration", { settings = settings }) end, settings = settings, cmd = cmd, on_attach = on_attach, capabilities = { workspace = { configuration = true, }, textDocument = { completion = { completionItem = { snippetSupport = true, }, }, }, }, }) vim.cmd( "command! -buffer -nargs=? -complete=custom,v:lua.require'jdtls'._complete_compile JdtCompile lua require('jdtls').compile()" ) vim.cmd( "command! -buffer -nargs=? -complete=custom,v:lua.require'jdtls'._complete_set_runtime JdtSetRuntime lua require('jdtls').set_runtime()" ) vim.cmd("command! -buffer JdtUpdateConfig lua require('jdtls').update_project_config()") vim.cmd("command! -buffer JdtJol lua require('jdtls').jol()") vim.cmd("command! -buffer JdtBytecode lua require('jdtls').javap()") vim.cmd("command! -buffer JdtJshell lua require('jdtls').jshell()") end return M