local misc = require('core.misc') local lsp = require('core.lsp.functions') local map, auto = misc.map, misc.auto return { 'mfussenegger/nvim-jdtls', disable = vim.version().minor < 6, requires = 'mfussenegger/nvim-dap', function() auto("FileType", { pattern = "java", callback = function() local jdtls = require('jdtls') local jdtls_install = require('mason-registry').get_package('jdtls'):get_install_path() -- make sure to check if things with 💀 need updating local config = { cmd = { 'java', -- 💀 '-jar', vim.fn.glob(jdtls_install..'/plugins/org.eclipse.equinox.launcher_*.jar'), -- 💀 '-configuration', jdtls_install..'/config_linux', '-data', vim.fn.stdpath('cache')..'/nvim-jdtls', '--add-modules=ALL-SYSTEM', '--add-opens', 'java.base/java.lang=ALL-UNNAMED', '--add-opens', 'java.base/java.util=ALL-UNNAMED', '-Declipse.application=org.eclipse.jdt.ls.core.id1', '-Declipse.product=org.eclipse.jdt.ls.core.product', '-Dlog.level=ALL', '-Dlog.protocol=true', '-Dosgi.bundles.defaultStartLevel=4', '-Xmx1G', }, root_dir = vim.fs.dirname(vim.fs.find({ 'gradlew', '.git', 'mvnw', 'build.xml' }, { upward = true })[1]), -- don't print out status messages handlers = { ['language/status'] = function() end }, capabilities = lsp.capabilities(), on_attach = function(client, bufnr) lsp.attach(client, bufnr) -- add some jdtls specific mappings local opts = { buffer = bufnr } map('n', 'cri', jdtls.organize_imports, opts) map('n', 'crv', jdtls.extract_variable, opts) map('n', 'crc', jdtls.extract_constant, opts) map('x', 'crv', function() jdtls.extract_variable(true) end, opts) map('x', 'crc', function() jdtls.extract_constant(true) end, opts) map('x', 'crm', function() jdtls.extract_method(true) end, opts) pcall(vim.lsp.codelens.refresh) auto('BufWritePost', { buffer = bufnr, desc = 'refresh codelens', callback = function() pcall(vim.lsp.codelens.refresh) end }) end, } ---@type string|nil local cache_path = vim.fs.joinpath(vim.fn.stdpath("cache"), "/JavaVersion.class") ---@type string|nil local src_path = vim.fs.joinpath(vim.fn.stdpath("config"), "/extras/JavaVersion.java") -- if either path is invalid if not cache_path or not src_path then return end --- build a cache of the JavaVersion code local function build_cache() -- check if we have javac vim.system({ "javac" }, {}, function(out) if out.code == 127 then cache_path = nil return end -- compile our code vim.system({ 'javac', src_path, '-d', vim.fn.stdpath("cache") }, {}, function(out) if out.code ~= 0 then cache_path = nil end end) end) end -- check if we have a compiled version of JavaVersion local f, _ = io.open(cache_path, "r") if not f then -- if we don't have a cache build_cache() else io.close(f) end -- check the java version local buffer = {} vim.fn.jobstart({ config.cmd[1], (cache_path and "JavaVersion") or src_path }, { cwd = vim.fn.stdpath("cache"), stdin = nil, on_stdout = function(_, data, _) table.insert(buffer, table.concat(data)) end, on_exit = function(_, exit_code, _) local v = vim.version.parse(table.concat(buffer)) -- if there's an error, no version info, or the java version is -- less than 17 stop the lsp from starting if exit_code ~= 0 then vim.notify(string.format( "java version check failed: exit code %s", exit_code), vim.log.levels.ERROR, { title = misc.appid }) return elseif not v then vim.notify("no java version info found", vim.log.levels.ERROR, { title = misc.appid }) return elseif v.major < 17 then vim.notify(string.format( "java version %s < 17.0.0 Cannot run jdtls, bailing out", v[1].."."..v[2].."."..v[3]), vim.log.levels.ERROR, { title = misc.appid }) return end -- start lsp jdtls.start_or_attach(config) end }) end }) end }