From 1fbe03fe28e054b8d3da1bd8eaad56f9c503f567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Mon, 2 Dec 2024 15:50:51 +0100 Subject: [PATCH 01/13] feat: added mason-registry for searching ls and some refactorings --- lua/spring_boot.lua | 51 +++++++++++++++- lua/spring_boot/config.lua | 12 ++-- lua/spring_boot/launch.lua | 110 ++++++++-------------------------- lua/spring_boot/ls_config.lua | 39 ++++++++++++ 4 files changed, 118 insertions(+), 94 deletions(-) create mode 100644 lua/spring_boot/ls_config.lua diff --git a/lua/spring_boot.lua b/lua/spring_boot.lua index f979bac..7c0bfc1 100644 --- a/lua/spring_boot.lua +++ b/lua/spring_boot.lua @@ -41,13 +41,60 @@ M.init_lsp_commands = function() end end +M.get_ls_from_mason = function() + local success, mason_registry = pcall(require, "mason-registry") + local result = nil + if success then + local key_prefix = "vscode-spring-boot-tools/language-server.jar" + local mason_package = mason_registry.get_package("vscode-spring-boot-tools") + if mason_package:is_installed() then + local install_path = mason_package:get_install_path() + mason_package:get_receipt():if_present(function(recipe) + for key, value in pairs(recipe.links.share) do + if key:sub(1, #key_prefix) == key_prefix then + result = install_path .. "/" .. value + break + end + end + end) + end + end + return result +end + local initialized = false M.setup = function(opts) if initialized then return end - M._config = opts - require("spring_boot.launch").setup() + opts = vim.tbl_deep_extend("keep", opts, require("spring_boot.config")) + if not opts.ls_path then + opts.ls_path = M.get_ls_from_mason() -- get ls from mason-registry + if not opts.ls_path then + -- try to find ls on standard installation path of vscode + opts.ls_path = require("spring_boot.vscode").find_one("/vmware.vscode-spring-boot-*/language-server") + if vim.fn.isdirectory(opts.ls_path .. "/BOOT-INF") ~= 0 then + -- it's an exploded jar + opts.exploded_ls_jar_data = true + else + -- it's a single jar + local server_jar = vim.split(vim.fn.glob(opts.ls_path .. "/spring-boot-language-server*.jar"), "\n") + if #server_jar > 0 then + opts.ls_path = server_jar[1] + end + end + end + end + if vim.fn.isdirectory(opts.ls_path .. "/BOOT-INF") ~= 0 then + -- a path was given in opts + opts.exploded_ls_jar_data = true + end + if not opts.ls_path then + -- all possibilities finding the ls failed + vim.notify("Spring Boot LS is not installed", vim.log.levels.WARN) + end + M.init_lsp_commands() + require("spring_boot.launch").setup(opts) initialized = true end diff --git a/lua/spring_boot/config.lua b/lua/spring_boot/config.lua index 40690cc..4af064b 100644 --- a/lua/spring_boot/config.lua +++ b/lua/spring_boot/config.lua @@ -18,11 +18,11 @@ local M = { }, } -local function init() - local spring_boot = require("spring_boot") - M = vim.tbl_deep_extend("keep", spring_boot._config, M) - spring_boot._config = nil -end -init() +-- local function init() +-- local spring_boot = require("spring_boot") +-- M = vim.tbl_deep_extend("keep", spring_boot._config, M) +-- spring_boot._config = nil +-- end +-- init() return M diff --git a/lua/spring_boot/launch.lua b/lua/spring_boot/launch.lua index 0946846..2ddeecf 100644 --- a/lua/spring_boot/launch.lua +++ b/lua/spring_boot/launch.lua @@ -1,11 +1,10 @@ -local M = {} -local config = require("spring_boot.config") -local vscode = require("spring_boot.vscode") local classpath = require("spring_boot.classpath") local java_data = require("spring_boot.java_data") local util = require("spring_boot.util") -local root_dir = function() +local M = {} + +M.root_dir = function() local ok, jdtls = pcall(require, "jdtls.setup") if ok then return jdtls.find_root({ ".git", "mvnw", "gradlew" }) or vim.loop.cwd() @@ -13,135 +12,74 @@ local root_dir = function() return vim.loop.cwd() end -local bootls_path = function() - if config.ls_path then - return config.ls_path - end - local bls = vscode.find_one("/vmware.vscode-spring-boot-*/language-server") - if bls then - return bls - end -end - M.enable_classpath_listening = function() util.boot_execute_command("sts.vscode-spring-boot.enableClasspathListening", { true }) end -local logfile = function(rt_dir) - local lf +M.logfile = function(config) + local lf = "/dev/null" if config.log_file ~= nil then if type(config.log_file) == "function" then - lf = config.log_file(rt_dir) + lf = config.log_file(config.root_dir) elseif type(config.log_file) == "string" then lf = config.log_file == "" and nil or config.log_file end end - return lf or "/dev/null" + return lf end -local function bootls_cmd(rt_dir, java_cmd) - local boot_path = bootls_path() - if not boot_path then - vim.notify("Spring Boot LS is not installed", vim.log.levels.WARN) - return - end +M.bootls_cmd = function(config) + local boot_path = config.root_dir if config.exploded_ls_jar_data then local boot_classpath = {} table.insert(boot_classpath, boot_path .. "/BOOT-INF/classes") table.insert(boot_classpath, boot_path .. "/BOOT-INF/lib/*") - local cmd = { - java_cmd or util.java_bin(), + return { + config.java_cmd or util.java_bin(), "-XX:TieredStopAtLevel=1", "-Xmx1G", "-XX:+UseZGC", "-cp", table.concat(boot_classpath, util.is_win and ";" or ":"), "-Dsts.lsp.client=vscode", - "-Dsts.log.file=" .. logfile(rt_dir), + "-Dsts.log.file=" .. M.logfile(config), "-Dspring.config.location=file:" .. boot_path .. "/BOOT-INF/classes/application.properties", -- "-Dlogging.level.org.springframework=DEBUG", "org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp", } - return cmd else - local server_jar = vim.split(vim.fn.glob(boot_path .. "/spring-boot-language-server*.jar"), "\n") - if #server_jar == 0 then - vim.notify("Spring Boot LS jar not found", vim.log.levels.WARN) - return - end - local cmd = { - java_cmd or util.java_bin(), + return { + config.java_cmd or util.java_bin(), "-XX:TieredStopAtLevel=1", "-Xmx1G", "-XX:+UseZGC", "-Dsts.lsp.client=vscode", - "-Dsts.log.file=" .. logfile(rt_dir), + "-Dsts.log.file=" .. M.logfile(config), "-jar", - server_jar[1], + config.ls_path, } - return cmd end end -local ls_config = { - name = "spring-boot", - filetypes = { "java", "yaml", "jproperties" }, - -- root_dir = root_dir, - init_options = { - -- workspaceFolders = root_dir, - enableJdtClasspath = false, - }, - settings = { - spring_boot = {}, - }, - handlers = {}, - commands = {}, - get_language_id = function(bufnr, filetype) - if filetype == "yaml" then - local filename = vim.api.nvim_buf_get_name(bufnr) - if util.is_application_yml_file(filename) then - return "spring-boot-properties-yaml" - end - elseif filetype == "jproperties" then - local filename = vim.api.nvim_buf_get_name(bufnr) - if util.is_application_properties_file(filename) then - return "spring-boot-properties" - end - end - return filetype - end, -} -classpath.register_classpath_service(ls_config) -java_data.register_java_data_service(ls_config) - vim.lsp.commands["vscode-spring-boot.ls.start"] = function(_, _, _) M.enable_classpath_listening() return {} end -ls_config.handlers["sts/highlight"] = function() end -ls_config.handlers["sts/moveCursor"] = function(err, result, ctx, config) - -- TODO: move cursor - return { applied = true } -end - -M.setup = function(_) - ls_config = vim.tbl_deep_extend("keep", ls_config, config.server) - local capabilities = ls_config.capabilities or vim.lsp.protocol.make_client_capabilities() - capabilities.workspace = { +M.setup = function(opts) + local ls_config = vim.tbl_deep_extend("keep", require("spring_boot.ls_config"), opts.server) + ls_config.root_dir = opts.root_dir or M.root_dir() + classpath.register_classpath_service(ls_config) + java_data.register_java_data_service(ls_config) + ls_config.capabilities.workspace = { executeCommand = { value = true }, } - ls_config.capabilities = capabilities - if not ls_config.root_dir then - ls_config.root_dir = root_dir() - end - ls_config.cmd = (ls_config.cmd and #ls_config.cmd > 0) and ls_config.cmd - or bootls_cmd(ls_config.root_dir, config.java_cmd) + ls_config.cmd = M.bootls_cmd(opts) if not ls_config.cmd then return end - ls_config.init_options.workspaceFolders = ls_config.root_dir + ls_config.init_options.workspaceFolders = opts.root_dir local group = vim.api.nvim_create_augroup("spring_boot_ls", { clear = true }) vim.api.nvim_create_autocmd({ "FileType" }, { group = group, diff --git a/lua/spring_boot/ls_config.lua b/lua/spring_boot/ls_config.lua new file mode 100644 index 0000000..ccf615a --- /dev/null +++ b/lua/spring_boot/ls_config.lua @@ -0,0 +1,39 @@ +local util = require("spring_boot.util") + +local M = { + name = "spring-boot", + filetypes = { "java", "yaml", "jproperties" }, + root_dir = "", + init_options = { + -- workspaceFolders = "", + enableJdtClasspath = true, + }, + settings = { + spring_boot = {}, + }, + handlers = { + ["sts/highlight"] = function() end, + ["sts/moveCursor"] = function(err, result, ctx, config) + -- TODO: move cursor + return { applied = true } + end, + }, + commands = {}, + get_language_id = function(bufnr, filetype) + if filetype == "yaml" then + local filename = vim.api.nvim_buf_get_name(bufnr) + if util.is_application_yml_file(filename) then + return "spring-boot-properties-yaml" + end + elseif filetype == "jproperties" then + local filename = vim.api.nvim_buf_get_name(bufnr) + if util.is_application_properties_file(filename) then + return "spring-boot-properties" + end + end + return filetype + end, + capabilities = vim.lsp.protocol.make_client_capabilities(), +} + +return M From 6117aec170057deedb076f62d3705289d716466b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Mon, 2 Dec 2024 16:50:09 +0100 Subject: [PATCH 02/13] fix: not finding a client is ok --- lua/spring_boot/util.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/spring_boot/util.lua b/lua/spring_boot/util.lua index 45fa4b5..0177d1a 100644 --- a/lua/spring_boot/util.lua +++ b/lua/spring_boot/util.lua @@ -32,7 +32,7 @@ M.get_client = function(name) if clients and #clients > 0 then return clients[1] end - vim.notify("Client not found: " .. name, vim.log.levels.ERROR) + -- vim.notify("Client not found: " .. name, vim.log.levels.ERROR) return nil end From c40fc6bfae573f2af6a22eb6b7557a96b8066e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Mon, 2 Dec 2024 16:50:40 +0100 Subject: [PATCH 03/13] fix: better integration of mason-registry --- lua/spring_boot.lua | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/lua/spring_boot.lua b/lua/spring_boot.lua index 7c0bfc1..758f515 100644 --- a/lua/spring_boot.lua +++ b/lua/spring_boot.lua @@ -8,6 +8,7 @@ vim.g.spring_boot = { "jdt-ls-extension.jar", "sts-gradle-tooling.jar", }, + jdt_expanded_extensions_jars = {}, } local M = {} @@ -42,18 +43,24 @@ M.init_lsp_commands = function() end M.get_ls_from_mason = function() + local result = M.add_jars_from_package("vscode-spring-boot-tools", "vscode-spring-boot-tools/language-server.jar") + if #result > 0 then + return result[1] + end + return nil +end + +M.add_jars_from_package = function(package_name, key_prefix) local success, mason_registry = pcall(require, "mason-registry") - local result = nil + local result = {} if success then - local key_prefix = "vscode-spring-boot-tools/language-server.jar" - local mason_package = mason_registry.get_package("vscode-spring-boot-tools") + local mason_package = mason_registry.get_package(package_name) if mason_package:is_installed() then local install_path = mason_package:get_install_path() mason_package:get_receipt():if_present(function(recipe) for key, value in pairs(recipe.links.share) do if key:sub(1, #key_prefix) == key_prefix then - result = install_path .. "/" .. value - break + table.insert(result, install_path .. "/" .. value) end end end) @@ -70,7 +77,10 @@ M.setup = function(opts) opts = vim.tbl_deep_extend("keep", opts, require("spring_boot.config")) if not opts.ls_path then opts.ls_path = M.get_ls_from_mason() -- get ls from mason-registry - if not opts.ls_path then + if opts.ls_path then + vim.g.spring_boot.jdt_expanded_extensions_jars = + M.add_jars_from_package("vscode-spring-boot-tools", "vscode-spring-boot-tools/jdtls/") + else -- try to find ls on standard installation path of vscode opts.ls_path = require("spring_boot.vscode").find_one("/vmware.vscode-spring-boot-*/language-server") if vim.fn.isdirectory(opts.ls_path .. "/BOOT-INF") ~= 0 then @@ -88,6 +98,8 @@ M.setup = function(opts) if vim.fn.isdirectory(opts.ls_path .. "/BOOT-INF") ~= 0 then -- a path was given in opts opts.exploded_ls_jar_data = true + else + opts.exploded_ls_jar_data = false end if not opts.ls_path then -- all possibilities finding the ls failed @@ -99,6 +111,9 @@ M.setup = function(opts) end M.java_extensions = function() + if vim.g.spring_boot.jdt_expanded_extensions_jars and #vim.g.spring_boot.jdt_expanded_extensions_jars > 0 then + return vim.g.spring_boot.jdt_expanded_extensions_jars + end local bundles = {} local function bundle_jar(path) for _, jar in ipairs(vim.g.spring_boot.jdt_extensions_jars) do From 516dc958181e93c2a0c78f908d79653a1dea3297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Mon, 2 Dec 2024 16:50:58 +0100 Subject: [PATCH 04/13] fix: added default values --- lua/spring_boot/ls_config.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/spring_boot/ls_config.lua b/lua/spring_boot/ls_config.lua index ccf615a..cd0dfd7 100644 --- a/lua/spring_boot/ls_config.lua +++ b/lua/spring_boot/ls_config.lua @@ -5,8 +5,8 @@ local M = { filetypes = { "java", "yaml", "jproperties" }, root_dir = "", init_options = { - -- workspaceFolders = "", - enableJdtClasspath = true, + workspaceFolders = "", + enableJdtClasspath = false, }, settings = { spring_boot = {}, From 54aee3ea64f6cc30e36cbe990c1ddcbfe4981298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Mon, 2 Dec 2024 16:51:47 +0100 Subject: [PATCH 05/13] fix: register classpath and java_data if ls_config is completly built --- lua/spring_boot/launch.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lua/spring_boot/launch.lua b/lua/spring_boot/launch.lua index 2ddeecf..30b47bb 100644 --- a/lua/spring_boot/launch.lua +++ b/lua/spring_boot/launch.lua @@ -70,8 +70,7 @@ end M.setup = function(opts) local ls_config = vim.tbl_deep_extend("keep", require("spring_boot.ls_config"), opts.server) ls_config.root_dir = opts.root_dir or M.root_dir() - classpath.register_classpath_service(ls_config) - java_data.register_java_data_service(ls_config) + ls_config.init_options.enableJdtClasspath = util.get_client(opts.jdtls_name) ~= nil ls_config.capabilities.workspace = { executeCommand = { value = true }, } @@ -80,6 +79,8 @@ M.setup = function(opts) return end ls_config.init_options.workspaceFolders = opts.root_dir + classpath.register_classpath_service(ls_config) + java_data.register_java_data_service(ls_config) local group = vim.api.nvim_create_augroup("spring_boot_ls", { clear = true }) vim.api.nvim_create_autocmd({ "FileType" }, { group = group, From cb178e013995285b85217f3ac96ef95f3a7f32a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Mon, 2 Dec 2024 16:53:35 +0100 Subject: [PATCH 06/13] better naming of function --- lua/spring_boot.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lua/spring_boot.lua b/lua/spring_boot.lua index 758f515..a0906c6 100644 --- a/lua/spring_boot.lua +++ b/lua/spring_boot.lua @@ -43,14 +43,14 @@ M.init_lsp_commands = function() end M.get_ls_from_mason = function() - local result = M.add_jars_from_package("vscode-spring-boot-tools", "vscode-spring-boot-tools/language-server.jar") + local result = M.get_from_mason_registry("vscode-spring-boot-tools", "vscode-spring-boot-tools/language-server.jar") if #result > 0 then return result[1] end return nil end -M.add_jars_from_package = function(package_name, key_prefix) +M.get_from_mason_registry = function(package_name, key_prefix) local success, mason_registry = pcall(require, "mason-registry") local result = {} if success then @@ -79,7 +79,7 @@ M.setup = function(opts) opts.ls_path = M.get_ls_from_mason() -- get ls from mason-registry if opts.ls_path then vim.g.spring_boot.jdt_expanded_extensions_jars = - M.add_jars_from_package("vscode-spring-boot-tools", "vscode-spring-boot-tools/jdtls/") + M.get_from_mason_registry("vscode-spring-boot-tools", "vscode-spring-boot-tools/jdtls/") else -- try to find ls on standard installation path of vscode opts.ls_path = require("spring_boot.vscode").find_one("/vmware.vscode-spring-boot-*/language-server") From 792149d287fea1467868de36e4f0fd1ee15388a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Mon, 9 Dec 2024 12:00:55 +0100 Subject: [PATCH 07/13] reviewed again and integration with jdtls is now much simpler --- lua/spring_boot.lua | 65 ++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/lua/spring_boot.lua b/lua/spring_boot.lua index a0906c6..63966f7 100644 --- a/lua/spring_boot.lua +++ b/lua/spring_boot.lua @@ -1,4 +1,4 @@ -vim.g.spring_boot = { +local spring_boot = { jdt_extensions_path = nil, -- https://github.com/spring-projects/sts4/blob/7d3d91ecfa6087ae2d0e0f595da61ce8f52fed96/vscode-extensions/vscode-spring-boot/package.json#L33 jdt_extensions_jars = { @@ -10,6 +10,13 @@ vim.g.spring_boot = { }, jdt_expanded_extensions_jars = {}, } +spring_boot.is_bundle_jar = function(path) + for _, jar in ipairs(spring_boot.jdt_extensions_jars) do + if vim.endswith(path, jar) then + return true + end + end +end local M = {} @@ -78,22 +85,29 @@ M.setup = function(opts) if not opts.ls_path then opts.ls_path = M.get_ls_from_mason() -- get ls from mason-registry if opts.ls_path then - vim.g.spring_boot.jdt_expanded_extensions_jars = + spring_boot.jdt_expanded_extensions_jars = M.get_from_mason_registry("vscode-spring-boot-tools", "vscode-spring-boot-tools/jdtls/") - else - -- try to find ls on standard installation path of vscode - opts.ls_path = require("spring_boot.vscode").find_one("/vmware.vscode-spring-boot-*/language-server") - if vim.fn.isdirectory(opts.ls_path .. "/BOOT-INF") ~= 0 then - -- it's an exploded jar - opts.exploded_ls_jar_data = true - else - -- it's a single jar - local server_jar = vim.split(vim.fn.glob(opts.ls_path .. "/spring-boot-language-server*.jar"), "\n") - if #server_jar > 0 then - opts.ls_path = server_jar[1] - end + end + end + if not opts.ls_path then + -- try to find ls on standard installation path of vscode + opts.ls_path = require("spring_boot.vscode").find_one("/vmware.vscode-spring-boot-*/language-server") + end + if opts.ls_path then + if vim.fn.isdirectory(opts.ls_path .. "/BOOT-INF") ~= 0 then + -- it's an exploded jar + opts.exploded_ls_jar_data = true + elseif (opts.ls_path:sub(-#".jar")) ~= ".jar" then + -- it's a single jar + local server_jar = vim.split(vim.fn.glob(opts.ls_path .. "/spring-boot-language-server*.jar"), "\n") + if #server_jar > 0 then + opts.ls_path = server_jar[1] end end + else + -- all possibilities finding the language server failed + vim.notify("Spring Boot LS is not installed", vim.log.levels.WARN) + return end if vim.fn.isdirectory(opts.ls_path .. "/BOOT-INF") ~= 0 then -- a path was given in opts @@ -101,32 +115,27 @@ M.setup = function(opts) else opts.exploded_ls_jar_data = false end - if not opts.ls_path then - -- all possibilities finding the ls failed - vim.notify("Spring Boot LS is not installed", vim.log.levels.WARN) - end M.init_lsp_commands() require("spring_boot.launch").setup(opts) initialized = true end M.java_extensions = function() - if vim.g.spring_boot.jdt_expanded_extensions_jars and #vim.g.spring_boot.jdt_expanded_extensions_jars > 0 then - return vim.g.spring_boot.jdt_expanded_extensions_jars + if spring_boot.jdt_expanded_extensions_jars and #spring_boot.jdt_expanded_extensions_jars > 0 then + return spring_boot.jdt_expanded_extensions_jars end - local bundles = {} - local function bundle_jar(path) - for _, jar in ipairs(vim.g.spring_boot.jdt_extensions_jars) do - if vim.endswith(path, jar) then - return true - end + local bundles = M.get_from_mason_registry("vscode-spring-boot-tools", "vscode-spring-boot-tools/jdtls/") + if #bundles > 0 then + for _, v in pairs(bundles) do + table.insert(spring_boot.jdt_expanded_extensions_jars, v) end + return bundles end - local spring_boot_path = vim.g.spring_boot.jdt_extensions_path + local spring_boot_path = spring_boot.jdt_extensions_path or require("spring_boot.vscode").find_one("/vmware.vscode-spring-boot-*/jars") if spring_boot_path then for _, bundle in ipairs(vim.split(vim.fn.glob(spring_boot_path .. "/*.jar"), "\n")) do - if bundle_jar(bundle) then + if spring_boot.is_bundle_jar(bundle) then table.insert(bundles, bundle) end end From 687c06611b82a926a1ec6e73c049150f251c2902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Wed, 8 Jan 2025 10:05:45 +0100 Subject: [PATCH 08/13] better error handling --- lua/spring_boot.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lua/spring_boot.lua b/lua/spring_boot.lua index 63966f7..1dd3a98 100644 --- a/lua/spring_boot.lua +++ b/lua/spring_boot.lua @@ -62,6 +62,9 @@ M.get_from_mason_registry = function(package_name, key_prefix) local result = {} if success then local mason_package = mason_registry.get_package(package_name) + if mason_package == nil then + return result + end if mason_package:is_installed() then local install_path = mason_package:get_install_path() mason_package:get_receipt():if_present(function(recipe) From cf85353ee17fcdab3c6f37226d07f14765e8dd3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Wed, 8 Jan 2025 11:27:50 +0100 Subject: [PATCH 09/13] reviewed code --- lua/spring_boot/launch.lua | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lua/spring_boot/launch.lua b/lua/spring_boot/launch.lua index ee27596..8c8720b 100644 --- a/lua/spring_boot/launch.lua +++ b/lua/spring_boot/launch.lua @@ -12,10 +12,6 @@ M.root_dir = function() return vim.loop.cwd() end -M.enable_classpath_listening = function() - util.boot_execute_command("sts.vscode-spring-boot.enableClasspathListening", { true }) -end - ---@param opts bootls.Config M.logfile = function(opts, rt_dir) local lf = "/dev/null" @@ -99,7 +95,7 @@ classpath.register_classpath_service(M.ls_config) java_data.register_java_data_service(M.ls_config) vim.lsp.commands["vscode-spring-boot.ls.start"] = function(_, _, _) - M.enable_classpath_listening() + util.boot_execute_command("sts.vscode-spring-boot.enableClasspathListening", { true }) return {} end From 118a96926403cc8f895cbfe65c7cca6795e00ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Wed, 8 Jan 2025 17:41:10 +0100 Subject: [PATCH 10/13] added refreshing registry so that an jproperties file is correctly opened directly via cmdline --- lua/spring_boot.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/spring_boot.lua b/lua/spring_boot.lua index 1dd3a98..0a2585a 100644 --- a/lua/spring_boot.lua +++ b/lua/spring_boot.lua @@ -61,6 +61,8 @@ M.get_from_mason_registry = function(package_name, key_prefix) local success, mason_registry = pcall(require, "mason-registry") local result = {} if success then + vim.notify("refreshing mason registry", vim.log.levels.INFO) + mason_registry.refresh() local mason_package = mason_registry.get_package(package_name) if mason_package == nil then return result From a947a75208e3d9540e5376121119f6e09ef2376a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Thu, 9 Jan 2025 15:40:46 +0100 Subject: [PATCH 11/13] review after merge with upstream --- lua/spring_boot.lua | 33 ++++++------ lua/spring_boot/config.lua | 8 +-- lua/spring_boot/launch.lua | 99 +++++++++-------------------------- lua/spring_boot/ls_config.lua | 11 +++- 4 files changed, 54 insertions(+), 97 deletions(-) diff --git a/lua/spring_boot.lua b/lua/spring_boot.lua index 0a2585a..ed48abf 100644 --- a/lua/spring_boot.lua +++ b/lua/spring_boot.lua @@ -1,22 +1,23 @@ +local jdt_extensions_jars = { + "io.projectreactor.reactor-core.jar", + "org.reactivestreams.reactive-streams.jar", + "jdt-ls-commons.jar", + "jdt-ls-extension.jar", + "sts-gradle-tooling.jar", +} + local spring_boot = { jdt_extensions_path = nil, -- https://github.com/spring-projects/sts4/blob/7d3d91ecfa6087ae2d0e0f595da61ce8f52fed96/vscode-extensions/vscode-spring-boot/package.json#L33 - jdt_extensions_jars = { - "io.projectreactor.reactor-core.jar", - "org.reactivestreams.reactive-streams.jar", - "jdt-ls-commons.jar", - "jdt-ls-extension.jar", - "sts-gradle-tooling.jar", - }, jdt_expanded_extensions_jars = {}, -} -spring_boot.is_bundle_jar = function(path) - for _, jar in ipairs(spring_boot.jdt_extensions_jars) do - if vim.endswith(path, jar) then - return true + is_bundle_jar = function(path) + for _, jar in ipairs(jdt_extensions_jars) do + if vim.endswith(path, jar) then + return true + end end - end -end + end, +} local M = {} @@ -86,7 +87,8 @@ M.setup = function(opts) if initialized then return end - opts = vim.tbl_deep_extend("keep", opts, require("spring_boot.config")) + initialized = true + opts = vim.tbl_deep_extend("keep", opts or {}, require("spring_boot.config")) if not opts.ls_path then opts.ls_path = M.get_ls_from_mason() -- get ls from mason-registry if opts.ls_path then @@ -122,7 +124,6 @@ M.setup = function(opts) end M.init_lsp_commands() require("spring_boot.launch").setup(opts) - initialized = true end M.java_extensions = function() diff --git a/lua/spring_boot/config.lua b/lua/spring_boot/config.lua index b6a6b61..63c58b4 100644 --- a/lua/spring_boot/config.lua +++ b/lua/spring_boot/config.lua @@ -5,6 +5,7 @@ ---@field log_file? string|function The path to the spring boot ls log file. ---@field server vim.lsp.ClientConfig The language server configuration. ---@field exploded_ls_jar_data boolean The exploded language server jar data. +---@field autocmd boolean autimatically setup autocmd in neovim ---@type bootls.Config local M = { @@ -19,11 +20,4 @@ local M = { autocmd = true, } -local function init() - local spring_boot = require("spring_boot") - M = vim.tbl_deep_extend("keep", spring_boot._config or {}, M) - spring_boot._config = nil -end -init() - return M diff --git a/lua/spring_boot/launch.lua b/lua/spring_boot/launch.lua index 8c8720b..f5f0028 100644 --- a/lua/spring_boot/launch.lua +++ b/lua/spring_boot/launch.lua @@ -1,5 +1,6 @@ local classpath = require("spring_boot.classpath") local java_data = require("spring_boot.java_data") +local ls_config = require("spring_boot.ls_config") local util = require("spring_boot.util") local M = {} @@ -26,7 +27,6 @@ M.logfile = function(opts, rt_dir) end M.bootls_cmd = function(config, rt_dir, java_cmd) - local boot_path = config.ls_path if not config.ls_path then vim.notify("Spring Boot LS is not installed", vim.log.levels.WARN) return @@ -37,7 +37,7 @@ M.bootls_cmd = function(config, rt_dir, java_cmd) table.insert(boot_classpath, config.ls_path .. "/BOOT-INF/lib/*") return { - config.java_cmd or util.java_bin(), + config.java_cmd or java_cmd or util.java_bin(), "-XX:TieredStopAtLevel=1", "-Xmx1G", "-XX:+UseZGC", @@ -51,7 +51,7 @@ M.bootls_cmd = function(config, rt_dir, java_cmd) } else return { - config.java_cmd or util.java_bin(), + config.java_cmd or java_cmd or util.java_bin(), "-XX:TieredStopAtLevel=1", "-Xmx1G", "-XX:+UseZGC", @@ -63,91 +63,44 @@ M.bootls_cmd = function(config, rt_dir, java_cmd) end end -M.ls_config = { - name = "spring-boot", - filetypes = { "java", "yaml", "jproperties" }, - -- root_dir = root_dir, - init_options = { - -- workspaceFolders = root_dir, - enableJdtClasspath = false, - }, - settings = { - spring_boot = {}, - }, - handlers = {}, - commands = {}, - get_language_id = function(bufnr, filetype) - if filetype == "yaml" then - local filename = vim.api.nvim_buf_get_name(bufnr) - if util.is_application_yml_file(filename) then - return "spring-boot-properties-yaml" - end - elseif filetype == "jproperties" then - local filename = vim.api.nvim_buf_get_name(bufnr) - if util.is_application_properties_file(filename) then - return "spring-boot-properties" - end - end - return filetype - end, -} -classpath.register_classpath_service(M.ls_config) -java_data.register_java_data_service(M.ls_config) - -vim.lsp.commands["vscode-spring-boot.ls.start"] = function(_, _, _) - util.boot_execute_command("sts.vscode-spring-boot.enableClasspathListening", { true }) - return {} -end - -M.ls_config.handlers["sts/highlight"] = function() end -M.ls_config.handlers["sts/moveCursor"] = function(err, result, ctx, config) - -- TODO: move cursor - return { applied = true } -end -M._update_config = false -M.update_config = function(opts) - if M._update_config then - return +M._update_ls_config = true +M.update_ls_config = function(opts) + if not M._update_ls_config then + return {} end - M._update_config = true - M.ls_config = vim.tbl_deep_extend("keep", M.ls_config, opts.server) - local capabilities = M.ls_config.capabilities or vim.lsp.protocol.make_client_capabilities() - capabilities.workspace = { - executeCommand = { value = true }, - } - M.ls_config.capabilities = capabilities - if not M.ls_config.root_dir then - M.ls_config.root_dir = M.root_dir() + M._update_ls_config = false + local result = vim.tbl_deep_extend("keep", ls_config, opts.server) + if not result.root_dir then + result.root_dir = M.root_dir() end - M.ls_config.cmd = (M.ls_config.cmd and #M.ls_config.cmd > 0) and M.ls_config.cmd - or M.bootls_cmd(opts, M.ls_config.root_dir, opts.java_cmd) - if not M.ls_config.cmd then - return - end - M.ls_config.init_options.workspaceFolders = M.ls_config.root_dir - local on_init = M.ls_config.on_init - M.ls_config.on_init = function(client, ctx) - util.boot_ls_init(client, ctx) - if on_init then - on_init(client, ctx) - end + result.cmd = (result.cmd and #result.cmd > 0) and result.cmd or M.bootls_cmd(opts, result.root_dir, opts.java_cmd) + if not result.cmd then + return {} end + result.init_options.workspaceFolders = result.root_dir + return result end -M.setup = function(config) - M.update_config(config) - if config.autocmd then +M.setup = function(opts) + local current_ls_config = M.update_ls_config(opts) + classpath.register_classpath_service(current_ls_config) + java_data.register_java_data_service(current_ls_config) + vim.lsp.commands["vscode-spring-boot.ls.start"] = function(_, _, _) + util.boot_execute_command("sts.vscode-spring-boot.enableClasspathListening", { true }) + end + if opts.autocmd then local group = vim.api.nvim_create_augroup("spring_boot_ls", { clear = true }) vim.api.nvim_create_autocmd({ "FileType" }, { group = group, pattern = { "java", "yaml", "jproperties" }, desc = "Spring Boot Language Server", callback = function(_) - M.start(M.ls_config) + M.start(current_ls_config) end, }) end end + M.start = function(opts) local buf = vim.api.nvim_get_current_buf() local filename = vim.uri_from_bufnr(buf) diff --git a/lua/spring_boot/ls_config.lua b/lua/spring_boot/ls_config.lua index cd0dfd7..77eec89 100644 --- a/lua/spring_boot/ls_config.lua +++ b/lua/spring_boot/ls_config.lua @@ -33,7 +33,16 @@ local M = { end return filetype end, - capabilities = vim.lsp.protocol.make_client_capabilities(), + capabilities = vim.tbl_deep_extend( + "keep", + vim.lsp.protocol.make_client_capabilities(), + { workspace = { + executeCommand = { value = true }, + } } + ), + on_init = function(client, ctx) + util.boot_ls_init(client, ctx) + end, } return M From f16035e886e8b737a93664f6be4f781ae0a19cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Maa=C3=9Fen?= Date: Thu, 9 Jan 2025 15:41:56 +0100 Subject: [PATCH 12/13] removed annoying message --- lua/spring_boot.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/spring_boot.lua b/lua/spring_boot.lua index ed48abf..4f5e5eb 100644 --- a/lua/spring_boot.lua +++ b/lua/spring_boot.lua @@ -62,7 +62,6 @@ M.get_from_mason_registry = function(package_name, key_prefix) local success, mason_registry = pcall(require, "mason-registry") local result = {} if success then - vim.notify("refreshing mason registry", vim.log.levels.INFO) mason_registry.refresh() local mason_package = mason_registry.get_package(package_name) if mason_package == nil then From ec7b51799c4ae8fb146e5b3235525f1ff5b31166 Mon Sep 17 00:00:00 2001 From: luokai Date: Mon, 13 Jan 2025 19:08:59 +0800 Subject: [PATCH 13/13] =?UTF-8?q?fix:=20ftplugin=20=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 38 +++++++-------- lua/spring_boot.lua | 10 +++- lua/spring_boot/launch.lua | 90 ++++++++++++++++------------------- lua/spring_boot/ls_config.lua | 18 +++---- 4 files changed, 72 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index 37d6d1c..e9e4094 100644 --- a/README.md +++ b/README.md @@ -12,36 +12,30 @@ ## 安装 -- `lazy.nvim` +- `lazy.nvim` 使用 `` ```lua + -- 使用 `autocmd` 方式启动(默认) + -- 默认使用 mason 或 ~/.vscode/extensions/vmware.vscode-spring-boot-x.xx.x 中的 jar { "JavaHello/spring-boot.nvim", - ft = "java", + ft = {"java", "yaml", "jproperties"}, dependencies = { "mfussenegger/nvim-jdtls", -- or nvim-java, nvim-lspconfig "ibhagwan/fzf-lua", -- 可选 }, - init = function() - vim.g.spring_boot = { - jdt_extensions_path = nil, -- 默认使用 ~/.vscode/extensions/vmware.vscode-spring-boot-x.xx.x - jdt_extensions_jars = { - "io.projectreactor.reactor-core.jar", - "org.reactivestreams.reactive-streams.jar", - "jdt-ls-commons.jar", - "jdt-ls-extension.jar", - "sts-gradle-tooling.jar", - }, - } - end, - config = function() - require("spring_boot").setup { - ls_path = nil, -- 默认使用 ~/.vscode/extensions/vmware.vscode-spring-boot-x.xx.x - jdtls_name = "jdtls", - log_file = nil, - java_cmd = nil, - } - end, + ---@type bootls.Config + opts = {} }, + + -- 使用 `ftplugin` 或自定义 方式启动 + { + "JavaHello/spring-boot.nvim", + lazy = true, + dependencies = { + "mfussenegger/nvim-jdtls", -- or nvim-java, nvim-lspconfig + }, + config = false + } ``` - [Visual Studio Code](https://code.visualstudio.com/) 中安装[VScode Spring Boot](https://marketplace.visualstudio.com/items?itemName=vmware.vscode-spring-boot)(可选的) diff --git a/lua/spring_boot.lua b/lua/spring_boot.lua index 4f5e5eb..311ee22 100644 --- a/lua/spring_boot.lua +++ b/lua/spring_boot.lua @@ -82,6 +82,8 @@ M.get_from_mason_registry = function(package_name, key_prefix) end local initialized = false + +---@param opts bootls.Config M.setup = function(opts) if initialized then return @@ -103,7 +105,7 @@ M.setup = function(opts) if vim.fn.isdirectory(opts.ls_path .. "/BOOT-INF") ~= 0 then -- it's an exploded jar opts.exploded_ls_jar_data = true - elseif (opts.ls_path:sub(-#".jar")) ~= ".jar" then + else -- it's a single jar local server_jar = vim.split(vim.fn.glob(opts.ls_path .. "/spring-boot-language-server*.jar"), "\n") if #server_jar > 0 then @@ -122,7 +124,11 @@ M.setup = function(opts) opts.exploded_ls_jar_data = false end M.init_lsp_commands() - require("spring_boot.launch").setup(opts) + + if opts.autocmd then + require("spring_boot.launch").ls_autocmd(opts) + end + return opts end M.java_extensions = function() diff --git a/lua/spring_boot/launch.lua b/lua/spring_boot/launch.lua index f5f0028..bb8a6fc 100644 --- a/lua/spring_boot/launch.lua +++ b/lua/spring_boot/launch.lua @@ -2,103 +2,95 @@ local classpath = require("spring_boot.classpath") local java_data = require("spring_boot.java_data") local ls_config = require("spring_boot.ls_config") local util = require("spring_boot.util") - +local uv = vim.uv or vim.loop local M = {} M.root_dir = function() - local ok, jdtls = pcall(require, "jdtls.setup") - if ok then - return jdtls.find_root({ ".git", "mvnw", "gradlew" }) or vim.loop.cwd() - end - return vim.loop.cwd() + return vim.fs.root(0, { ".git", "mvnw", "gradlew" }) or uv.cwd() end ---@param opts bootls.Config -M.logfile = function(opts, rt_dir) - local lf = "/dev/null" +M.logfile = function(opts) + local lf if opts.log_file ~= nil then if type(opts.log_file) == "function" then - lf = opts.log_file(rt_dir) + lf = opts.log_file(opts.server.root_dir) elseif type(opts.log_file) == "string" then - lf = opts.log_file == "" and nil or opts.log_file + lf = opts.log_file end end - return lf + return lf or "/dev/null" end -M.bootls_cmd = function(config, rt_dir, java_cmd) - if not config.ls_path then - vim.notify("Spring Boot LS is not installed", vim.log.levels.WARN) - return - end +M.bootls_cmd = function(config) if config.exploded_ls_jar_data then local boot_classpath = {} table.insert(boot_classpath, config.ls_path .. "/BOOT-INF/classes") table.insert(boot_classpath, config.ls_path .. "/BOOT-INF/lib/*") return { - config.java_cmd or java_cmd or util.java_bin(), + config.java_cmd or util.java_bin(), "-XX:TieredStopAtLevel=1", "-Xmx1G", "-XX:+UseZGC", "-cp", table.concat(boot_classpath, util.is_win and ";" or ":"), "-Dsts.lsp.client=vscode", - "-Dsts.log.file=" .. M.logfile(config, rt_dir), + "-Dsts.log.file=" .. M.logfile(config), "-Dspring.config.location=file:" .. config.ls_path .. "/BOOT-INF/classes/application.properties", -- "-Dlogging.level.org.springframework=DEBUG", "org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp", } else return { - config.java_cmd or java_cmd or util.java_bin(), + config.java_cmd or util.java_bin(), "-XX:TieredStopAtLevel=1", "-Xmx1G", "-XX:+UseZGC", "-Dsts.lsp.client=vscode", - "-Dsts.log.file=" .. M.logfile(config, rt_dir), + "-Dsts.log.file=" .. M.logfile(config), "-jar", config.ls_path, } end end -M._update_ls_config = true +--- 使用 ftplugin 启动时,调用此方法 +---@param opts bootls.Config +---@return vim.lsp.ClientConfig M.update_ls_config = function(opts) - if not M._update_ls_config then - return {} - end - M._update_ls_config = false - local result = vim.tbl_deep_extend("keep", ls_config, opts.server) - if not result.root_dir then - result.root_dir = M.root_dir() + local client_config = vim.tbl_deep_extend("keep", opts.server, ls_config) + if not client_config.root_dir then + client_config.root_dir = M.root_dir() end - result.cmd = (result.cmd and #result.cmd > 0) and result.cmd or M.bootls_cmd(opts, result.root_dir, opts.java_cmd) - if not result.cmd then - return {} + if not client_config.cmd or #client_config.cmd == 0 then + if not opts.ls_path then + vim.notify("Spring Boot LS is not installed", vim.log.levels.WARN) + return {} + end + client_config.cmd = M.bootls_cmd(opts) end - result.init_options.workspaceFolders = result.root_dir - return result -end + client_config.init_options.workspaceFolders = client_config.root_dir -M.setup = function(opts) - local current_ls_config = M.update_ls_config(opts) - classpath.register_classpath_service(current_ls_config) - java_data.register_java_data_service(current_ls_config) + classpath.register_classpath_service(client_config) + java_data.register_java_data_service(client_config) vim.lsp.commands["vscode-spring-boot.ls.start"] = function(_, _, _) util.boot_execute_command("sts.vscode-spring-boot.enableClasspathListening", { true }) end - if opts.autocmd then - local group = vim.api.nvim_create_augroup("spring_boot_ls", { clear = true }) - vim.api.nvim_create_autocmd({ "FileType" }, { - group = group, - pattern = { "java", "yaml", "jproperties" }, - desc = "Spring Boot Language Server", - callback = function(_) - M.start(current_ls_config) - end, - }) - end + return client_config +end + +M.ls_autocmd = function(opts) + local current_ls_config = M.update_ls_config(opts) + local group = vim.api.nvim_create_augroup("spring_boot_ls", { clear = true }) + vim.api.nvim_create_autocmd({ "FileType" }, { + group = group, + pattern = { "java", "yaml", "jproperties" }, + desc = "Spring Boot Language Server", + callback = function(_) + M.start(current_ls_config) + end, + }) end M.start = function(opts) diff --git a/lua/spring_boot/ls_config.lua b/lua/spring_boot/ls_config.lua index 77eec89..4c938e5 100644 --- a/lua/spring_boot/ls_config.lua +++ b/lua/spring_boot/ls_config.lua @@ -3,14 +3,12 @@ local util = require("spring_boot.util") local M = { name = "spring-boot", filetypes = { "java", "yaml", "jproperties" }, - root_dir = "", + root_dir = nil, init_options = { - workspaceFolders = "", + workspaceFolders = nil, enableJdtClasspath = false, }, - settings = { - spring_boot = {}, - }, + settings = {}, handlers = { ["sts/highlight"] = function() end, ["sts/moveCursor"] = function(err, result, ctx, config) @@ -33,13 +31,11 @@ local M = { end return filetype end, - capabilities = vim.tbl_deep_extend( - "keep", - vim.lsp.protocol.make_client_capabilities(), - { workspace = { + capabilities = vim.tbl_deep_extend("force", vim.lsp.protocol.make_client_capabilities(), { + workspace = { executeCommand = { value = true }, - } } - ), + }, + }), on_init = function(client, ctx) util.boot_ls_init(client, ctx) end,