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 home = os.getenv("HOME") local root_markers = { ".git", "mvnw", "gradlew" } local root_dir = jdtls_setup.find_root(root_markers) local project_name = vim.fn.fnamemodify(root_dir, ":p:h:t") local workspace_dir = home .. "/.cache/jdtls/workspace/" .. project_name local path_to_nvim_packages = home .. "/.local/share/nvim" local path_to_mason_packages = home .. "/.local/share/nvim/mason/packages" local path_to_jdtls = path_to_mason_packages .. "/jdtls" local path_to_java_dap = path_to_mason_packages .. "/java-debug-adapter" local path_to_jtest = path_to_mason_packages .. "/java-test" local path_to_config = path_to_jdtls .. "/config_linux" local lombok_path = path_to_jdtls .. "/lombok.jar" local path_to_jar = vim.fn.glob(path_to_jdtls .. "/plugins/org.eclipse.equinox.launcher_*.jar", true) local bundles = { -- vim.fn.glob(path_to_java_dap .. "/extension/server/com.microsoft.java.debug.plugin-*.jar", true), vim.fn.glob( path_to_nvim_packages .. "/java-debug/com.microsoft.java.debug.plugin/target/com.microsoft.java.debug.plugin-*.jar" ), } vim.list_extend(bundles, vim.split(vim.fn.glob(path_to_nvim_packages .. "/vscode-java-test/server/*.jar"), "\n")) -- vim.list_extend(bundles, vim.split(vim.fn.glob(path_to_jtest .. "/extension/server/*.jar", true), "\n")) local on_attach = function(_, bufnr) -- Regular Neovim LSP client keymappings local opts = { noremap = true, silent = true, buffer = bufnr } local telescope = require("telescope.builtin") utils.nmapkey("gR", telescope.lsp_references, "Go to references", opts) utils.nmapkey("gD", jdtls.declaration, "Go to declaration", opts) utils.nmapkey("K", jdtls.hover, "Hover text", opts) utils.nmapkey("gd", jdtls.definition, "Go to definition", opts) utils.nmapkey("gi", jdtls.implementation, "Go to implementation", opts) utils.nmapkey("gt", telescope.lsp_type_definitions, "Show LSP type definitions", opts) utils.nmapkey("", jdtls.signature_help, "Show signature", opts) utils.nmapkey("wa", jdtls.add_workspace_folder, "Add workspace folder", opts) utils.nmapkey("wr", jdtls.remove_workspace_folder, "Remove workspace folder", opts) utils.nmapkey("wl", function() print(vim.inspect(jdtls.list_workspace_folders())) end, "List workspace folders", opts) utils.nmapkey("D", telescope.diagnostics({ bufnr = 0 }), "Show buffer diagnostics", opts) -- show diagnostics for file utils.nmapkey("d", vim.diagnostic.open_float, "Show line diagnostics", opts) -- show diagnostics for line utils.nmapkey("[d", function() vim.diagnostic.jump({ count = -1, float = true }) end, "Go to previous diagnostic", opts) -- jump to previous diagnostic in buffer utils.nmapkey("]d", function() vim.diagnostic.jump({ count = 1, float = true }) end, "Go to next diagnostic", opts) -- jump to next diagnostic in buffer utils.nmapkey("rs", "LspRestart", "Restart LSP", opts) -- mapping to restart lsp if necessary -- Java extensions provided by jdtls 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.nmapkey("cf", jdtls.formatting, "LSP Format", opts) utils.nmapkey("", jdtls.organize_imports, "Organize imports", opts) utils.mapkey({ "n", "v" }, "ev", jdtls.extract_variable, "Extract variable", opts) utils.mapkey({ "n", "v" }, "ec", jdtls.extract_constant, "Extract constant", opts) utils.mapkey({ "n", "v" }, "em", jdtls.extract_variable, "Extract method", opts) end local config = { init_options = { bundles = vim.split(vim.fn.glob("/home/iborrelli/pde/extension/server/*.jar"), "\n"), }, flags = { allow_incremental_sync = true, }, on_attach = on_attach, -- We pass our on_attach keybindings to the configuration map } config.cmd = { "/usr/lib/jvm/java-21-openjdk/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:" .. lombok_path, "--add-modules=ALL-SYSTEM", "--add-opens", "java.base/java.util=ALL-UNNAMED", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "-jar", path_to_jar, "-configuration", path_to_config, "-data", workspace_dir, } -- print(table.concat(config.cmd, " ")) -- print(vim.inspect(config.cmd)) config.settings = { java = { references = { includeDecompiledSources = true, }, -- format = { -- enabled = true, -- 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}}", -- -- flags = { -- -- allow_incremental_sync = true, -- -- }, -- }, -- useBlocks = true, -- }, configuration = { updateBuildConfiguration = "automatic", runtimes = { { name = "JavaSE-17", path = "/usr/lib/jvm/java-17-openjdk/", }, { name = "JavaSE-21", path = "/usr/lib/jvm/java-21-openjdk/", }, }, }, -- project = { -- referencedLibraries = { -- "**/lib/*.jar", -- }, -- }, }, } -- -- LSP settings for Java. -- local on_attach = function(_, bufnr) -- 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 -- vim.api.nvim_buf_create_user_command(bufnr, "Format", function(_) -- vim.lsp.buf.format() -- end, { desc = "Format current buffer with LSP" }) -- -- require("lsp_signature").on_attach({ -- bind = true, -- padding = "", -- handler_opts = { -- border = "rounded", -- }, -- hint_prefix = "󱄑 ", -- }, bufnr) -- -- -- NOTE: comment out if you don't use Lspsaga -- -- require("lspsaga").init_lsp_saga() -- end local capabilities = { workspace = { configuration = true, }, textDocument = { completion = { completionItem = { snippetSupport = true, }, }, }, } config.on_attach = on_attach config.capabilities = capabilities config.on_init = function(client, _) client.notify("workspace/didChangeConfiguration", { settings = config.settings }) end local extendedClientCapabilities = require("jdtls").extendedClientCapabilities extendedClientCapabilities.resolveAdditionalTextEditsSupport = true config.init_options = { extendedClientCapabilities = extendedClientCapabilities, } -- Start Server require("jdtls").start_or_attach(config) -- -- Set Java Specific Keymaps -- require("jdtls.keymaps") end return M