vim.opt_local.shiftwidth = 2 vim.opt_local.tabstop = 2 vim.opt_local.cmdheight = 2 -- more space in the neovim command line for displaying messages local status, jdtls = pcall(require, 'jdtls') if not status then return end -- Determine OS local home = os.getenv 'HOME' if vim.fn.has 'mac' == 1 then WORKSPACE_PATH = home .. '/workspace/' CONFIG = 'mac' elseif vim.fn.has 'unix' == 1 then WORKSPACE_PATH = home .. '/workspace/' CONFIG = 'linux' else print 'Unsupported system' end -- Find root of project local root_markers = { '.git', 'mvnw', 'gradlew', 'pom.xml', 'build.gradle' } local root_dir = require('jdtls.setup').find_root(root_markers) if root_dir == '' then return end local extendedClientCapabilities = jdtls.extendedClientCapabilities extendedClientCapabilities.resolveAdditionalTextEditsSupport = true local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ':p:h:t') local workspace_dir = WORKSPACE_PATH .. project_name JAVA_DAP_ACTIVE = true local bundles = { vim.fn.glob( home .. '/.config/nvim/.java-debug/com.microsoft.java.debug.plugin/target/com.microsoft.java.debug.plugin-*.jar' ), } vim.list_extend(bundles, vim.split(vim.fn.glob(home .. '/.config/nvim/.vscode-java-test/server/*.jar'), '\n')) local function lsp_keymaps(bufnr) local opt = { noremap = true, silent = true } local keymap = vim.api.nvim_buf_set_keymap keymap(bufnr, 'n', 'gD', 'lua vim.lsp.buf.declaration()', opt) keymap(bufnr, 'n', 'gd', 'lua vim.lsp.buf.definition()', opt) keymap(bufnr, 'n', 'K', 'lua vim.lsp.buf.hover()', opt) keymap(bufnr, 'n', 'gI', 'lua vim.lsp.buf.implementation()', opt) keymap(bufnr, 'n', 'gr', 'TroubleToggle lsp_references', opt) keymap(bufnr, 'n', 'gl', 'lua vim.diagnostic.open_float()', opt) keymap(bufnr, 'n', 'lf', 'lua vim.lsp.buf.format { async = true }', opt) keymap(bufnr, 'n', 'li', 'LspInfo', opt) keymap(bufnr, 'n', 'lI', 'LspInstallInfo', opt) keymap(bufnr, 'n', 'la', 'lua vim.lsp.buf.code_action()', opt) keymap(bufnr, 'n', 'lj', 'lua vim.diagnostic.goto_next({buffer=0})', opt) keymap(bufnr, 'n', 'lk', 'lua vim.diagnostic.goto_prev({buffer=0})', opt) keymap(bufnr, 'n', 'lr', 'lua vim.lsp.buf.rename()', opt) keymap(bufnr, 'n', 'ls', 'lua vim.lsp.buf.signature_help()', opt) keymap(bufnr, 'n', 'lq', 'lua vim.diagnostic.setloclist()', opt) keymap(bufnr, 'n', 'e', 'lua vim.diagnostic.open_float()', opt) end local on_attach = function(client, bufnr) --[[ vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') ]] lsp_keymaps(bufnr) if client.name == 'jdtls' then client.server_capabilities.documentFormattingProvider = false end if client.name == 'jdt.ls' then client.server_capabilities.documentFormattingProvider = false vim.lsp.codelens.refresh() if JAVA_DAP_ACTIVE then require('jdtls').setup_dap { hotcodereplace = 'auto' } require('jdtls.dap').setup_dap_main_class_configs() end end local ft = vim.api.nvim_buf_get_option(bufnr, 'filetype') local nls = require 'plugins.null-ls' local enable = false if nls.has_formatter(ft) then enable = client.name == 'null-ls' else enable = not (client.name == 'null-ls') end -- util.info(client.name .. " " .. (enable and "yes" or "no"), "format") client.server_capabilities.documentFormattingProvider = enable end local cmp_nvim_lsp = require 'cmp_nvim_lsp' local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities.textDocument.completion.completionItem.snippetSupport = true capabilities = cmp_nvim_lsp.default_capabilities(capabilities) -- See `:help vim.lsp.start_client` for an overview of the supported `config` options. local config = { -- The command that starts the language server -- See: https://github.com/eclipse/eclipse.jdt.ls#running-from-the-command-line cmd = { -- 💀 'java', -- or '/path/to/java11_or_newer/bin/java' -- depends on if `java` is in your $PATH env variable and if it points to the right version. '-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', '-javaagent:' .. home .. '/.local/share/nvim/mason/packages/jdtls/lombok.jar', '-Xms1g', '--add-modules=ALL-SYSTEM', '--add-opens', 'java.base/java.util=ALL-UNNAMED', '--add-opens', 'java.base/java.lang=ALL-UNNAMED', -- 💀 '-jar', vim.fn.glob(home .. '/.local/share/nvim/mason/packages/jdtls/plugins/org.eclipse.equinox.launcher_*.jar'), -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ -- Must point to the Change this to -- eclipse.jdt.ls installation the actual version -- 💀 '-configuration', home .. '/.local/share/nvim/mason/packages/jdtls/config_' .. CONFIG, -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ -- Must point to the Change to one of `linux`, `win` or `mac` -- eclipse.jdt.ls installation Depending on your system. -- 💀 -- See `data directory configuration` section in the README '-data', workspace_dir, }, on_attach = on_attach, capabilities = capabilities, -- 💀 -- This is the default if not provided, you can remove it. Or adjust as needed. -- One dedicated LSP server & client will be started per unique root_dir root_dir = root_dir, -- Here you can configure eclipse.jdt.ls specific settings -- See https://github.com/eclipse/eclipse.jdt.ls/wiki/Running-the-JAVA-LS-server-from-the-command-line#initialize-request -- or https://github.com/redhat-developer/vscode-java#supported-vs-code-settings -- for a list of options settings = { java = { eclipse = { downloadSources = true, }, configuration = { updateBuildConfiguration = 'interactive', }, maven = { downloadSources = true, }, implementationsCodeLens = { enabled = true, }, referencesCodeLens = { enabled = true, }, references = { includeDecompiledSources = true, }, -- Set this to true to use jdtls as your formatter format = { enabled = false, }, }, 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.*', }, }, contentProvider = { preferred = 'fernflower' }, extendedClientCapabilities = extendedClientCapabilities, sources = { organizeImports = { starThreshold = 9999, staticStarThreshold = 9999, }, }, codeGeneration = { toString = { template = '${object.className}{${member.name()}=${member.value}, ${otherMembers}}', }, useBlocks = true, }, }, flags = { allow_incremental_sync = true, }, -- Language server `initializationOptions` -- You need to extend the `bundles` with paths to jar files -- if you want to use additional eclipse.jdt.ls plugins. -- -- See https://github.com/mfussenegger/nvim-jdtls#java-debug-installation -- -- If you don't plan on using the debugger or other eclipse.jdt.ls plugins you can remove this init_options = { -- bundles = {}, bundles = bundles, }, } vim.api.nvim_create_autocmd({ 'BufWritePost' }, { pattern = { '*.java' }, callback = function() vim.lsp.codelens.refresh() end, }) -- This starts a new client & server, -- or attaches to an existing client & server depending on the `root_dir`. require('jdtls').start_or_attach(config) 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 JdtBytecode lua require('jdtls').javap()" -- Shorten function name local keymap = vim.keymap.set -- Silent keymap option local opts = { silent = true } keymap('n', 'jo', "lua require'jdtls'.organize_imports()", opts) keymap('n', 'jv', "lua require('jdtls').extract_variable()", opts) keymap('n', 'jc', "lua require('jdtls').extract_constant()", opts) keymap('n', 'jt', "lua require'jdtls'.test_nearest_method()", opts) keymap('n', 'jT', "lua require'jdtls'.test_class()", opts) keymap('n', 'ju', 'JdtUpdateConfig', opts) keymap('v', 'jv', "lua require('jdtls').extract_variable(true)", opts) keymap('v', 'jc', "lua require('jdtls').extract_constant(true)", opts) keymap('v', 'jm', "lua require('jdtls').extract_method(true)", opts) local wk = require 'which-key' local optsj = { mode = 'n', -- NORMAL mode prefix = '', buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings silent = true, -- use `silent` when creating keymaps noremap = true, -- use `noremap` when creating keymaps nowait = true, -- use `nowait` when creating keymaps } local vopts = { mode = 'v', -- VISUAL mode prefix = '', buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings silent = true, -- use `silent` when creating keymaps noremap = true, -- use `noremap` when creating keymaps nowait = true, -- use `nowait` when creating keymaps } local mappingsj = { L = { name = 'Java', o = { "lua require'jdtls'.organize_imports()", 'Organize Imports' }, v = { "lua require('jdtls').extract_variable()", 'Extract Variable' }, c = { "lua require('jdtls').extract_constant()", 'Extract Constant' }, t = { "lua require'jdtls'.test_nearest_method()", 'Test Method' }, T = { "lua require'jdtls'.test_class()", 'Test Class' }, u = { 'JdtUpdateConfig', 'Update Config' }, }, } local vmappings = { L = { name = 'Java', v = { "lua require('jdtls').extract_variable(true)", 'Extract Variable' }, c = { "lua require('jdtls').extract_constant(true)", 'Extract Constant' }, m = { "lua require('jdtls').extract_method(true)", 'Extract Method' }, }, } wk.register(mappingsj, optsj) wk.register(vmappings, vopts)