LazyVim.LazyVim/lua/lazyvim/plugins/extras/lang/java.lua
akioweh fa94c73362
fix printable characters being mapped in select mode
most of the "visual mode" mappings use "v" instead of "x", affecting
select mode, which should not have printable characters remapped. (this
is felt when e.g. using snippets)
2025-07-29 00:16:33 +04:00

299 lines
11 KiB
Lua

-- This is the same as in lspconfig.configs.jdtls, but avoids
-- needing to require that when this module loads.
local java_filetypes = { "java" }
-- Utility function to extend or override a config table, similar to the way
-- that Plugin.opts works.
---@param config table
---@param custom function | table | nil
local function extend_or_override(config, custom, ...)
if type(custom) == "function" then
config = custom(config, ...) or config
elseif custom then
config = vim.tbl_deep_extend("force", config, custom) --[[@as table]]
end
return config
end
return {
recommended = function()
return LazyVim.extras.wants({
ft = "java",
root = {
"build.gradle",
"build.gradle.kts",
"build.xml", -- Ant
"pom.xml", -- Maven
"settings.gradle", -- Gradle
"settings.gradle.kts", -- Gradle
},
})
end,
-- Add java to treesitter.
{
"nvim-treesitter/nvim-treesitter",
opts = { ensure_installed = { "java" } },
},
-- Ensure java debugger and test packages are installed.
{
"mfussenegger/nvim-dap",
optional = true,
opts = function()
-- Simple configuration to attach to remote java debug process
-- Taken directly from https://github.com/mfussenegger/nvim-dap/wiki/Java
local dap = require("dap")
dap.configurations.java = {
{
type = "java",
request = "attach",
name = "Debug (Attach) - Remote",
hostName = "127.0.0.1",
port = 5005,
},
}
end,
dependencies = {
{
"mason-org/mason.nvim",
opts = { ensure_installed = { "java-debug-adapter", "java-test" } },
},
},
},
-- Configure nvim-lspconfig to install the server automatically via mason, but
-- defer actually starting it to our configuration of nvim-jtdls below.
{
"neovim/nvim-lspconfig",
opts = {
-- make sure mason installs the server
servers = {
jdtls = {},
},
setup = {
jdtls = function()
return true -- avoid duplicate servers
end,
},
},
},
-- Set up nvim-jdtls to attach to java files.
{
"mfussenegger/nvim-jdtls",
dependencies = { "folke/which-key.nvim" },
ft = java_filetypes,
opts = function()
local cmd = { vim.fn.exepath("jdtls") }
if LazyVim.has("mason.nvim") then
local mason_registry = require("mason-registry")
local lombok_jar = mason_registry.get_package("jdtls"):get_install_path() .. "/lombok.jar"
table.insert(cmd, string.format("--jvm-arg=-javaagent:%s", lombok_jar))
end
return {
-- How to find the root dir for a given filename. The default comes from
-- lspconfig which provides a function specifically for java projects.
root_dir = LazyVim.lsp.get_raw_config("jdtls").default_config.root_dir,
-- How to find the project name for a given root dir.
project_name = function(root_dir)
return root_dir and vim.fs.basename(root_dir)
end,
-- Where are the config and workspace dirs for a project?
jdtls_config_dir = function(project_name)
return vim.fn.stdpath("cache") .. "/jdtls/" .. project_name .. "/config"
end,
jdtls_workspace_dir = function(project_name)
return vim.fn.stdpath("cache") .. "/jdtls/" .. project_name .. "/workspace"
end,
-- How to run jdtls. This can be overridden to a full java command-line
-- if the Python wrapper script doesn't suffice.
cmd = cmd,
full_cmd = function(opts)
local fname = vim.api.nvim_buf_get_name(0)
local root_dir = opts.root_dir(fname)
local project_name = opts.project_name(root_dir)
local cmd = vim.deepcopy(opts.cmd)
if project_name then
vim.list_extend(cmd, {
"-configuration",
opts.jdtls_config_dir(project_name),
"-data",
opts.jdtls_workspace_dir(project_name),
})
end
return cmd
end,
-- These depend on nvim-dap, but can additionally be disabled by setting false here.
dap = { hotcodereplace = "auto", config_overrides = {} },
-- Can set this to false to disable main class scan, which is a performance killer for large project
dap_main = {},
test = true,
settings = {
java = {
inlayHints = {
parameterNames = {
enabled = "all",
},
},
},
},
}
end,
config = function(_, opts)
-- Find the extra bundles that should be passed on the jdtls command-line
-- if nvim-dap is enabled with java debug/test.
local bundles = {} ---@type string[]
if LazyVim.has("mason.nvim") then
local mason_registry = require("mason-registry")
if opts.dap and LazyVim.has("nvim-dap") and mason_registry.is_installed("java-debug-adapter") then
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 also depends on java-debug-adapter.
if opts.test and mason_registry.is_installed("java-test") then
local java_test_pkg = mason_registry.get_package("java-test")
local java_test_path = java_test_pkg:get_install_path()
vim.list_extend(jar_patterns, {
java_test_path .. "/extension/server/*.jar",
})
end
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
end
local function attach_jdtls()
local fname = vim.api.nvim_buf_get_name(0)
-- Configuration can be augmented and overridden by opts.jdtls
local config = extend_or_override({
cmd = opts.full_cmd(opts),
root_dir = opts.root_dir(fname),
init_options = {
bundles = bundles,
},
settings = opts.settings,
-- enable CMP capabilities
capabilities = LazyVim.has("cmp-nvim-lsp") and require("cmp_nvim_lsp").default_capabilities() or nil,
}, opts.jdtls)
-- Existing server will be reused if the root_dir matches.
require("jdtls").start_or_attach(config)
-- not need to require("jdtls.setup").add_commands(), start automatically adds commands
end
-- Attach the jdtls for each java buffer. HOWEVER, this plugin loads
-- depending on filetype, so this autocmd doesn't run for the first file.
-- For that, we call directly below.
vim.api.nvim_create_autocmd("FileType", {
pattern = java_filetypes,
callback = attach_jdtls,
})
-- 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", {
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
if client and client.name == "jdtls" then
local wk = require("which-key")
wk.add({
{
mode = "n",
buffer = args.buf,
{ "<leader>cx", group = "extract" },
{ "<leader>cxv", require("jdtls").extract_variable_all, desc = "Extract Variable" },
{ "<leader>cxc", require("jdtls").extract_constant, desc = "Extract Constant" },
{ "<leader>cgs", require("jdtls").super_implementation, desc = "Goto Super" },
{ "<leader>cgS", require("jdtls.tests").goto_subjects, desc = "Goto Subjects" },
{ "<leader>co", require("jdtls").organize_imports, desc = "Organize Imports" },
},
})
wk.add({
{
mode = "x",
buffer = args.buf,
{ "<leader>cx", group = "extract" },
{
"<leader>cxm",
[[<ESC><CMD>lua require('jdtls').extract_method(true)<CR>]],
desc = "Extract Method",
},
{
"<leader>cxv",
[[<ESC><CMD>lua require('jdtls').extract_variable_all(true)<CR>]],
desc = "Extract Variable",
},
{
"<leader>cxc",
[[<ESC><CMD>lua require('jdtls').extract_constant(true)<CR>]],
desc = "Extract Constant",
},
},
})
if LazyVim.has("mason.nvim") then
local mason_registry = require("mason-registry")
if opts.dap and LazyVim.has("nvim-dap") and mason_registry.is_installed("java-debug-adapter") then
-- custom init for Java debugger
require("jdtls").setup_dap(opts.dap)
if opts.dap_main then
require("jdtls.dap").setup_dap_main_class_configs(opts.dap_main)
end
-- Java Test require Java debugger to work
if opts.test and mason_registry.is_installed("java-test") then
-- custom keymaps for Java test runner (not yet compatible with neotest)
wk.add({
{
mode = "n",
buffer = args.buf,
{ "<leader>t", group = "test" },
{
"<leader>tt",
function()
require("jdtls.dap").test_class({
config_overrides = type(opts.test) ~= "boolean" and opts.test.config_overrides or nil,
})
end,
desc = "Run All Test",
},
{
"<leader>tr",
function()
require("jdtls.dap").test_nearest_method({
config_overrides = type(opts.test) ~= "boolean" and opts.test.config_overrides or nil,
})
end,
desc = "Run Nearest Test",
},
{ "<leader>tT", require("jdtls.dap").pick_test, desc = "Run Test" },
},
})
end
end
end
-- User can set additional keymaps in opts.on_attach
if opts.on_attach then
opts.on_attach(args)
end
end
end,
})
-- Avoid race condition by calling attach the first time, since the autocmd won't fire.
attach_jdtls()
end,
},
}