From cc3dfa496ea53d0476b51ea8370f67695937620a Mon Sep 17 00:00:00 2001 From: aqav <66734646+aqav@users.noreply.github.com> Date: Sat, 12 Aug 2023 17:11:03 +0800 Subject: [PATCH] feat(java): better java support --- lua/lazyvim/plugins/extras/lang/java.lua | 173 ++++++++++++----------- 1 file changed, 88 insertions(+), 85 deletions(-) diff --git a/lua/lazyvim/plugins/extras/lang/java.lua b/lua/lazyvim/plugins/extras/lang/java.lua index bf99a78d..cb61dea7 100644 --- a/lua/lazyvim/plugins/extras/lang/java.lua +++ b/lua/lazyvim/plugins/extras/lang/java.lua @@ -1,119 +1,112 @@ return { - -- add Java to nvim-treesitter + -- Add java to treesitter. { "nvim-treesitter/nvim-treesitter", opts = function(_, opts) - opts.ensure_installed = opts.ensure_installed or {} - vim.list_extend(opts.ensure_installed, { "java" }) + if type(opts.ensure_installed) == "table" then + vim.list_extend(opts.ensure_installed, { "java" }) + end end, }, - -- install Java LSP - { - "williamboman/mason.nvim", - opts = function(_, opts) - opts.ensure_installed = opts.ensure_installed or {} - vim.list_extend(opts.ensure_installed, { "jdtls" }) - end, - }, - -- install java-debug-adapter and java-test - -- https://github.com/jay-babu/mason-nvim-dap.nvim/blob/main/lua/mason-nvim-dap/mappings/source.lua + + -- Ensure java debugger and test packages are installed { "mfussenegger/nvim-dap", + optional = true, dependencies = { { - "jay-babu/mason-nvim-dap.nvim", + "williamboman/mason.nvim", opts = function(_, opts) opts.ensure_installed = opts.ensure_installed or {} - vim.list_extend(opts.ensure_installed, { "javadbg", "javatest" }) + vim.list_extend(opts.ensure_installed, { "java-test", "java-debug-adapter" }) end, }, }, }, - -- don't setup jdtls with lspconfig - -- https://github.com/mfussenegger/nvim-jdtls#nvim-lspconfig-and-nvim-jdtls-differences + + -- Set up lsp { "neovim/nvim-lspconfig", opts = { + -- make sure mason installs the server + servers = { + jdtls = {}, + }, setup = { jdtls = function() - return true + return true -- avoid duplicate servers end, }, }, }, - -- setup jdtls + + -- Set up nvim-jdtls { "mfussenegger/nvim-jdtls", - dependencies = { -- add all dependencies used below - "neovim/nvim-lspconfig", - "mfussenegger/nvim-dap", - "hrsh7th/nvim-cmp", - "folke/which-key.nvim", - }, + dependencies = { "folke/which-key.nvim" }, ft = { "java" }, config = function() - local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:t") - local workspace_dir = vim.fn.stdpath("data") .. "/lsp/java/" .. project_name - 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", - "-Xmx1g", - "--add-modules=ALL-SYSTEM", - "--add-opens", - "java.base/java.util=ALL-UNNAMED", - "--add-opens", - "java.base/java.lang=ALL-UNNAMED", - "-jar", - vim.fn.expand("$MASON/share/jdtls/plugins/org.eclipse.equinox.launcher.jar"), + -- The configuration for jdtls contains two useful items: + -- 1. The list of filetypes on which to match. + -- 2. Custom method for finding the root for a java project. + local lsp_config = require("lspconfig.server_configurations.jdtls").default_config + local find_java_project_root = lsp_config.root_dir + local filetypes = lsp_config.filetypes + -- lookup paths for java test and debugger package + local mason_registry = require("mason-registry") + local bundles = {} + if mason_registry.has_package("java-test") and mason_registry.has_package("java-debug-adapter") then + -- jdtls tools configuration for debugging support + local java_test_pkg = mason_registry.get_package("java-test") + local java_test_path = java_test_pkg:get_install_path() + local java_dbg_pkg = mason_registry.get_package("java-debug-adapter") + local java_dbg_path = java_dbg_pkg:get_install_path() + local jar_patterns = { + java_dbg_path .. "/extension/server/com.microsoft.java.debug.plugin-*.jar", + java_test_path .. "/extension/server/*.jar", + } + for _, jar_pattern in ipairs(jar_patterns) do + for _, bundle in ipairs(vim.split(vim.fn.glob(jar_pattern), "\n")) do + table.insert(bundles, bundle) + end + end + end + + local fname = vim.api.nvim_buf_get_name(0) + local root_dir = find_java_project_root(fname) + local project_name = root_dir and vim.fs.basename(root_dir) + local cmd = { "jdtls" } + if project_name then + local jdtls_cache_dir = vim.fn.stdpath("cache") .. "/jdtls/" .. project_name + vim.list_extend(cmd, { "-configuration", - vim.fn.expand("$MASON/share/jdtls/config"), + jdtls_cache_dir .. "/config", "-data", - workspace_dir, - }, - root_dir = require("jdtls.setup").find_root({ - ".git", - "mvnw", - "gradlew", - "pom.xml", - "build.gradle", - "build.gradle.kts", - "settings.gradle", - "settings.gradle.kts", - "build.xml", - ".project", - }), - settings = { - java = {}, - }, - -- silent setup - handlers = { - ["$/progress"] = function() end, - ["language/status"] = function() end, - }, + jdtls_cache_dir .. "/workspace", + }) + end + local jdtls_base_config = { + cmd = cmd, + root_dir = root_dir, init_options = { - bundles = { - vim.fn.expand("$MASON/share/java-debug-adapter/com.microsoft.java.debug.plugin.jar"), - (table.unpack or unpack)(vim.split(vim.fn.glob("$MASON/share/java-test/*.jar"), "\n", {})), - }, + bundles = bundles, }, - filetypes = { "java" }, - capabilities = require("cmp_nvim_lsp").default_capabilities(), -- enable CMP capabilities + -- enable CMP capabilities + capabilities = require("cmp_nvim_lsp").default_capabilities(), } - -- attach every Java buffer + -- Attach jdtls for the proper filetypes (i.e. java). + -- Existing server will be reused if the root_dir matches. vim.api.nvim_create_autocmd("FileType", { - pattern = "java", + pattern = filetypes, callback = function() - require("jdtls").start_or_attach(config) + local jdtls_opts = require("lazyvim.util").opts("nvim-jdtls") + require("jdtls").start_or_attach(vim.tbl_deep_extend("force", jdtls_opts or {}, jdtls_base_config)) + -- not need to require("jdtls.setup").add_commands(), start automatically adds commands end, }) - -- setup keymap and DAP after the LSP is fully attached + -- Setup keymap and dap after the lsp is fully attached -- https://github.com/mfussenegger/nvim-jdtls#nvim-dap-configuration -- https://neovim.io/doc/user/lsp.html#LspAttach vim.api.nvim_create_autocmd("LspAttach", { @@ -131,19 +124,29 @@ return { ["c"] = { name = "+code" }, ["cx"] = { name = "+extract" }, ["cxm"] = { [[lua require('jdtls').extract_method(true)]], "Extract Method" }, - ["cxv"] = { [[lua require('jdtls').extract_variable_all(true)]], "Extract Variable" }, + ["cxv"] = { + [[lua require('jdtls').extract_variable_all(true)]], + "Extract Variable", + }, ["cxc"] = { [[lua require('jdtls').extract_constant(true)]], "Extract Constant" }, }, { mode = "v", buffer = args.buf }) - require("jdtls.dap").setup_dap() - require("jdtls.dap").setup_dap_main_class_configs() + if mason_registry.has_package("java-debug-adapter") then + -- custom init for Java debugger + require("jdtls").setup_dap({ hotcodereplace = "auto", config_overrides = {} }) + require("jdtls.dap").setup_dap_main_class_configs() - require("which-key").register({ - ["t"] = { name = "+test" }, - ["tT"] = { require("jdtls.dap").test_class, "Run All Test" }, - ["tr"] = { require("jdtls.dap").test_nearest_method, "Run Nearest Test" }, - ["tt"] = { require("jdtls.dap").pick_test, "Run Test" }, - }, { mode = "n", buffer = args.buf }) + -- Java Test require Java debugger to work + if mason_registry.has_package("java-test") then + -- custom keymaps for Java test runner (not yet compatible with neotest) + require("which-key").register({ + ["t"] = { name = "+test" }, + ["tt"] = { require("jdtls.dap").test_class, "Run All Test" }, + ["tr"] = { require("jdtls.dap").test_nearest_method, "Run Nearest Test" }, + ["tT"] = { require("jdtls.dap").pick_test, "Run Test" }, + }, { mode = "n", buffer = args.buf }) + end + end end, }) end,