-
-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: support multi clients #350
fix: support multi clients #350
Conversation
Could you explain what problem this fixes? If it is that you're having multiple jdtls clients because you've multiple projects open at the same time, you could add a |
I use workspaces.nvim to record the paths of different projects and open them. There are times when multiple java projects are opened, which can cause multiple jdtls servers to start. When I used the I'm not familiar with the api, but I happened to find vim.lsp.buf_get_clients(), and the api worked as I expected. Here is my configuration, is there another way to solve this problem? -- 每个java缓冲区需要执行setup函数,首次执行将启动lsp并attach,后续仅attach
local jdtls = require "jdtls"
local utils = require "user.utils"
local lsp_utils = require "user.ide.lsp-utils"
local java_home_preset = {
java_home_5 = os.getenv("JAVA_HOME_5"),
java_home_6 = os.getenv("JAVA_HOME_6"),
java_home_7 = os.getenv("JAVA_HOME_7"),
java_home_8 = os.getenv("JAVA_HOME_8"),
java_home_9 = os.getenv("JAVA_HOME_9"),
java_home_10 = os.getenv("JAVA_HOME_10"),
java_home_11 = os.getenv("JAVA_HOME_11"),
java_home_12 = os.getenv("JAVA_HOME_12"),
java_home_13 = os.getenv("JAVA_HOME_13"),
java_home_14 = os.getenv("JAVA_HOME_14"),
java_home_15 = os.getenv("JAVA_HOME_15"),
java_home_16 = os.getenv("JAVA_HOME_16"),
java_home_17 = os.getenv("JAVA_HOME_17"),
java_home_18 = os.getenv("JAVA_HOME_18"),
}
local stdpath_config = vim.fn.stdpath("config")
local stdpath_data = vim.fn.stdpath("data")
local stdpath_cache = vim.fn.stdpath("cache")
local java_home_17 = java_home_preset.java_home_17
local cp_sp = utils.os_name == "win" and ";" or ":"
local cp = "." .. cp_sp .. utils.fs_concat({ java_home_17, "lib", "dt.jar" }) .. cp_sp .. utils.fs_concat({ java_home_17, "lib", "tools.jar" })
local java = utils.fs_concat({ java_home_17, "bin", "java" })
local jdtls_home = utils.fs_concat({ stdpath_data, "mason", "packages", "jdtls" })
local lombok_jar = utils.fs_concat({ jdtls_home, "lombok.jar" })
local launcher_jar = vim.fn.glob(utils.fs_concat({ jdtls_home, "plugins", "org.eclipse.equinox.launcher_*.jar" }))
local config_dir = utils.fs_concat({ jdtls_home, (utils.os_name == "win" and "config_win" or "config_linux") })
local runtimes_preset = {
{
name = "J2SE-1.5",
path = java_home_preset.java_home_5,
},
{
name = "JavaSE-1.6",
path = java_home_preset.java_home_6,
sources = utils.fs_concat({ java_home_preset.java_home_6, "src.zip" }),
javadoc = "https://docs.oracle.com/javase/6/docs/api",
},
{
name = "JavaSE-1.7",
path = java_home_preset.java_home_7,
sources = utils.fs_concat({ java_home_preset.java_home_7, "src.zip" }),
javadoc = "https://docs.oracle.com/javase/7/docs/api",
},
{
name = "JavaSE-1.8",
path = java_home_preset.java_home_8,
sources = utils.fs_concat({ java_home_preset.java_home_8, "src.zip" }),
javadoc = "https://docs.oracle.com/javase/8/docs/api",
default = true,
},
{
name = "JavaSE-9",
path = java_home_preset.java_home_9,
sources = utils.fs_concat({ java_home_preset.java_home_9, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/9/docs/api",
},
{
name = "JavaSE-10",
path = java_home_preset.java_home_10,
sources = utils.fs_concat({ java_home_preset.java_home_10, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/10/docs/api",
},
{
name = "JavaSE-11",
path = java_home_preset.java_home_11,
sources = utils.fs_concat({ java_home_preset.java_home_11, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/11/docs/api",
},
{
name = "JavaSE-12",
path = java_home_preset.java_home_12,
sources = utils.fs_concat({ java_home_preset.java_home_12, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/12/docs/api",
},
{
name = "JavaSE-13",
path = java_home_preset.java_home_13,
sources = utils.fs_concat({ java_home_preset.java_home_13, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/13/docs/api",
},
{
name = "JavaSE-14",
path = java_home_preset.java_home_14,
sources = utils.fs_concat({ java_home_preset.java_home_14, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/14/docs/api",
},
{
name = "JavaSE-15",
path = java_home_preset.java_home_15,
sources = utils.fs_concat({ java_home_preset.java_home_15, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/15/docs/api",
},
{
name = "JavaSE-16",
path = java_home_preset.java_home_16,
sources = utils.fs_concat({ java_home_preset.java_home_16, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/16/docs/api",
},
{
name = "JavaSE-17",
path = java_home_preset.java_home_17,
sources = utils.fs_concat({ java_home_preset.java_home_17, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/17/docs/api",
},
{
name = "JavaSE-18",
path = java_home_preset.java_home_18,
sources = utils.fs_concat({ java_home_preset.java_home_18, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/18/docs/api",
},
{
name = "JavaSE-19",
path = java_home_preset.java_home_19,
sources = utils.fs_concat({ java_home_preset.java_home_19, "lib", "src.zip" }),
javadoc = "https://docs.oracle.com/javase/19/docs/api",
},
}
local function build_runtimes()
local runtimes = {}
for _, item in pairs(runtimes_preset) do
if item.path ~= nil then
table.insert(runtimes, item)
end
end
return runtimes
end
local M = {}
M.setup = function()
-- 获取工作目录
local root_dir = utils.find_root_dir({
'build.xml', -- Ant
"mvnw", -- Maven
'pom.xml', -- Maven
'settings.gradle', -- Gradle
'settings.gradle.kts', -- Gradle
"gradlew", -- Gradle
})
local is_single_file = root_dir == nil
local workspace_dir = root_dir or vim.fn.expand("%:p")
-- 转义工作目录作为名称
local workspace_name = string.gsub(workspace_dir, utils.fs_separator, "__")
if utils.os_name == "win" then
workspace_name = string.gsub(workspace_name, ":", "++")
end
-- 数据目录
local data_dir = utils.fs_concat({ stdpath_cache, "lsp", "jdtls", workspace_name })
-- jdtls配置
local config = {}
-- jdtls启动命令
config.cmd = {
java,
"-cp", cp,
"-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",
"-Xmx4G",
"-javaagent:" .. lombok_jar,
"-jar", launcher_jar,
"-configuration", config_dir,
"-data", data_dir,
"--add-modules=ALL-SYSTEM",
"--add-opens java.base/java.util=ALL-UNNAMED",
"--add-opens java.base/java.lang=ALL-UNNAMED",
}
-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
config.on_attach = function(client, bufnr)
lsp_utils.on_attach(client, bufnr)
-- jdtls特性
jdtls.setup_dap({ hotcodereplace = "auto" })
jdtls.setup.add_commands()
-- https://github.com/mfussenegger/nvim-jdtls#nvim-dap-configuration
-- 注册用于调试的主类,如果是新增的main方法需要使用:JdtRefreshDebugConfigs命令刷新
if not is_single_file then
require("jdtls.dap").setup_dap_main_class_configs()
end
-- 注册调试命令
vim.cmd([[
command! JdtTestClass lua require'jdtls'.test_class()
command! JdtTestMethod lua require'jdtls'.test_nearest_method()
command! JdtRemoteDebug lua require'user.ide.jdtls.command'.remote_debug_by_input()
command! JdtDebug lua require'user.ide.jdtls.command'.debug()
command! JdtA lua require'user.ide.jdtls.command'.test()
]])
-- 设置jdt的扩展快捷键
vim.keymap.set("n", "gp", "<Cmd>lua require'jdtls'.super_implementation()<CR>", { noremap = true, silent = true, buffer = bufnr, desc = "Lsp Super Implementation" })
end
config.capabilities = lsp_utils.make_capabilities()
config.root_dir = workspace_dir
config.settings = {
java = {
signatureHelp = { enabled = true },
contentProvider = { preferred = "fernflower" },
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.*"
}
},
sources = {
-- 不在import中使用*
organizeImports = {
starThreshold = 999,
staticStarThreshold = 999,
},
},
configuration = {
-- See https://github.com/eclipse/eclipse.jdt.ls/wiki/Running-the-JAVA-LS-server-from-the-command-line#initialize-request
-- And search for `interface RuntimeOption`
-- The `name` is NOT arbitrary, but must match one of the elements from `enum ExecutionEnvironment` in the link above
runtimes = build_runtimes(),
},
},
}
-- See https://github.com/mfussenegger/nvim-jdtls#java-debug-installation
-- debug插件
local bundles = {
vim.fn.glob(utils.fs_concat({ stdpath_config, "lua", "user", "ide", "jdtls", "plugins", "java-debug", "com.microsoft.java.debug.plugin-*.jar"})),
}
-- 单元测试插件
vim.list_extend(bundles, vim.split(vim.fn.glob(utils.fs_concat({ stdpath_config, "lua", "user", "ide", "jdtls", "plugins", "vscode-java-test", "*.jar" })), "\n"))
local extendedClientCapabilities = jdtls.extendedClientCapabilities
extendedClientCapabilities.resolveAdditionalTextEditsSupport = true
config.init_options = {
bundles = bundles,
extendedClientCapabilities = extendedClientCapabilities,
}
-- This starts a new client & server,
-- or attaches to an existing client & server depending on the `root_dir`.
require("jdtls").start_or_attach(config)
end
return M |
Based on your description, I checked the api again, should I use
|
Yes I think something like this should also work as fix: diff --git a/lua/jdtls.lua b/lua/jdtls.lua
index 97c2328..6323b90 100644
--- a/lua/jdtls.lua
+++ b/lua/jdtls.lua
@@ -36,11 +36,11 @@ function M.start_or_attach(config)
end
local request = function(bufnr, method, params, handler)
local client = nil
- for _, c in pairs(vim.lsp.get_active_clients()) do
+ for _, c in pairs(vim.lsp.get_active_clients({ bufnr = bufnr })) do
if c.name == 'jdtls' then
client = c
break
end
end
|
Yes, I modified the commit and it works fine. |
Thanks, merged. |
support multi clients