1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
local misc = require("core.misc")
local map, auto = misc.map, misc.auto
local jdtls = require("jdtls")
local jdtls_install = vim.fs.joinpath(vim.fn.stdpath('data'),
"/mason/packages/jdtls")
local java_dap_install = vim.fs.joinpath(vim.fn.stdpath('data'),
"/mason/packages/java-debug-adapter")
-- make sure to check if things with 💀 need updating
local config = {
cmd = {
"/usr/lib/jvm/openjdk21/bin/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",
"settings.gradle", -- Gradle (multi-project)
"settings.gradle.kts", -- Gradle (multi-project)
"build.xml", -- Ant
"pom.xml" -- Maven
}, { upward = true })[1]),
on_attach = function(_, bufnr)
jdtls.setup.add_commands()
-- 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
})
-- setup nvim-dap
require("dap").adapters.java = nil -- remove any old java adapters
jdtls.setup_dap({ hotcodereplace = "auto" })
require("jdtls.dap").setup_dap_main_class_configs()
end,
-- don"t print out status messages
handlers = {
["language/status"] = function() end
},
init_options = {
bundles = {
vim.fs.joinpath(java_dap_install,
vim.fn.glob("/extension/server/com.microsoft.java.debug.plugin-*.jar",
true)
)
}
}
}
-- generate the path to the java file(s)
---@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
local function version_check()
-- check the java version
local out = vim.system({
config.cmd[1], -- use the same java executable that the lsp will be using
(cache_path and "JavaVersion") or src_path
}, { cwd = vim.fn.stdpath("cache"), text = true }):wait()
-- parse the version information aquired
local v = vim.version.parse(out.stdout)
-- if there's an error, no version info, or the java version is
-- less than 21 stop the lsp from starting
if out.code ~= 0 then
vim.notify(string.format(
"java version check failed: exit code %s", out.code),
vim.log.levels.ERROR, { title = misc.appid })
vim.notify(string.format(
"%s", vim.inspect(out.stdout)),
vim.log.levels.ERROR, { title = misc.appid })
return false
elseif not v then
vim.notify("no java version info found", vim.log.levels.ERROR,
{ title = misc.appid })
return false
elseif v.major < 21 then
vim.notify(string.format(
"java version %s < 21.0.0 Cannot run jdtls, bailing out",
v[1] .. "." .. v[2] .. "." .. v[3]),
vim.log.levels.ERROR, { title = misc.appid })
return false
end
return true
end
-- start the jdtls with dap!
if not version_check() then
return
end
jdtls.start_or_attach(config)
|