From f7d4d1e456f887ae4a3990e2224575e0b1fbfacb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 22:49:07 +0200 Subject: [PATCH 01/20] ci: add lua-language-server --check to static analysis --- .github/workflows/static-analysis.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 8bdd6fe8..a5660ddf 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -39,3 +39,22 @@ jobs: version: latest # NOTE: we recommend pinning to a specific version in case of formatting changes # CLI arguments args: --check . + + lua-language-server: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + - name: Cache lua-language-server + uses: actions/cache@v4 + with: + path: ~/.local/lua-language-server + key: lua-language-server-3.18.2 + - name: Install lua-language-server + run: | + if ! [ -x ~/.local/lua-language-server/bin/lua-language-server ]; then + mkdir -p ~/.local/lua-language-server + curl -fsSL https://github.com/LuaLS/lua-language-server/releases/download/3.18.2/lua-language-server-3.18.2-linux-x64.tar.gz | tar -xz -C ~/.local/lua-language-server + fi + - name: Run luacheck via lua-language-server + run: ~/.local/lua-language-server/bin/lua-language-server --check . From c877744a33bd55c0f72db23e340d8cb26ca4afb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:01:35 +0200 Subject: [PATCH 02/20] feat: add type definitions for neotest and vim.lsp types --- lua/neotest-java/types.lua | 63 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 lua/neotest-java/types.lua diff --git a/lua/neotest-java/types.lua b/lua/neotest-java/types.lua new file mode 100644 index 00000000..779f4b79 --- /dev/null +++ b/lua/neotest-java/types.lua @@ -0,0 +1,63 @@ +-- Type definitions for external libraries used by neotest-java +-- This file is not loaded at runtime, only used by lua-language-server for type checking + +---@class neotest.Position +---@field id string +---@field name string +---@field type "test" | "namespace" | "dir" | "file" +---@field path string +---@field range integer[] + +---@class neotest.Tree +---@field data fun(): neotest.Position +---@field iter fun(): fun():integer[], neotest.Position +---@field to_list fun(): neotest.Position[] +---@field children fun(): neotest.Tree[] +---@field root fun(): neotest.Tree + +---@class neotest.Error +---@field message string +---@field line integer? + +---@class neotest.Result +---@field status neotest.ResultStatus +---@field output string? +---@field short string? +---@field errors neotest.Error[]? + +---@alias neotest.ResultStatus "passed" | "failed" | "skipped" + +---@class neotest.RunArgs +---@field tree neotest.Tree +---@field strategy string? + +---@class neotest.RunSpec +---@field command string|string[] +---@field env table? +---@field cwd string? +---@field context table? +---@field strategy table? + +---@class neotest.StrategyResult +---@field code integer +---@field output string + +---@class neotest.Adapter +---@field name string +---@field root fun(dir: string): string? +---@field is_test_file fun(filepath: string): boolean +---@field discover_positions fun(filepath: string): neotest.Tree +---@field build_spec fun(args: neotest.RunArgs): neotest.RunSpec|neotest.RunSpec[]|nil +---@field results fun(spec: neotest.RunSpec, strategy_result: neotest.StrategyResult): table +---@field filter_dir fun(name: string): boolean + +---@class vim.lsp.Client +---@field name string +---@field initialized boolean +---@field attached_buffers integer[] +---@field request fun(method: string, params: table, callback: fun(err: any, result: any)?, bufnr: integer?) +---@field config table + +---@class nio.control.Event +---@field wait fun() +---@field set fun() From ba1c454d11f5c65a4892e62f3d7a79363674f8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:01:54 +0200 Subject: [PATCH 03/20] fix: resolve param-type-mismatch and missing-return-value in junit_result.lua --- lua/neotest-java/model/junit_result.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lua/neotest-java/model/junit_result.lua b/lua/neotest-java/model/junit_result.lua index 6d30865c..851f8d80 100644 --- a/lua/neotest-java/model/junit_result.lua +++ b/lua/neotest-java/model/junit_result.lua @@ -19,8 +19,7 @@ local function create_file_with_content(data, tempname) if #data == 0 then return nil end - data = vim.iter(vim.tbl_values(data)):flatten(math.huge):totable() - data = table.concat(data, LINE_SEPARATOR) + data = table.concat(vim.iter(vim.tbl_values(data)):flatten(math.huge):totable(), LINE_SEPARATOR) end -- Generate a unique temporary file name @@ -115,7 +114,7 @@ function JunitResult:status() } return FAILED, { fail } end - return PASSED + return PASSED, {} end ---@param with_name_prefix? boolean From 1346b10b0cc16255097b2b92f183a308f82d39a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:02:09 +0200 Subject: [PATCH 04/20] fix: remove redundant param docs and fix stdpath_data type --- lua/neotest-java/util/junit_version_detector.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lua/neotest-java/util/junit_version_detector.lua b/lua/neotest-java/util/junit_version_detector.lua index 70b71fd5..9a937164 100644 --- a/lua/neotest-java/util/junit_version_detector.lua +++ b/lua/neotest-java/util/junit_version_detector.lua @@ -28,7 +28,7 @@ end ---@field exists fun(filepath: neotest-java.Path): boolean ---@field checksum fun(file_path: neotest-java.Path): string ---@field scan fun(dir: neotest-java.Path, opts: { search_patterns: string[] }): neotest-java.Path[] ----@field stdpath_data fun(): string +---@field stdpath_data fun(name: string): string ---@class neotest-java.JunitVersionDetector ---@field detect_existing_version fun(): neotest-java.JunitVersion | nil, neotest-java.Path | nil @@ -104,9 +104,6 @@ local JunitVersionDetector = function(deps) --- @return table[] get_supported_versions = get_supported_versions, - --- @param file_path neotest-java.Path - --- @param file_reader? fun(path: string): string - --- @return string hash _checksum = checksum, -- Exposed for testing } end From ba91bb1194603ea2f3f1a89e08e7bb459d20523a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:02:24 +0200 Subject: [PATCH 05/20] fix: move param docs outside memoized function --- lua/neotest-java/util/read_xml_tag.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lua/neotest-java/util/read_xml_tag.lua b/lua/neotest-java/util/read_xml_tag.lua index 202b98ad..e03bb271 100644 --- a/lua/neotest-java/util/read_xml_tag.lua +++ b/lua/neotest-java/util/read_xml_tag.lua @@ -2,11 +2,10 @@ local memo = require("neotest.lib.func_util.memoize") local file = require("neotest.lib.file") local xml = require("neotest.lib.xml") ----@param filepath string ----@param selector string ex: project.build.sourceDirectory ----@return string | nil -local cache = {} -local read_xml_tag = memo(function(filepath, selector) +--- @param filepath string +--- @param selector string ex: project.build.sourceDirectory +--- @return string | nil +local function _read_xml_tag(filepath, selector) local content = file.read(filepath) local parsed = xml.parse(content) @@ -22,6 +21,8 @@ local read_xml_tag = memo(function(filepath, selector) end return parsed -end, cache) +end + +local read_xml_tag = memo(_read_xml_tag) return read_xml_tag From 02800161e524216f680793a000c0f7511fd0bca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:02:39 +0200 Subject: [PATCH 06/20] fix: add missing _level and _filename fields to Logger class --- lua/neotest-java/logger.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/neotest-java/logger.lua b/lua/neotest-java/logger.lua index ac4e109a..7556dfa6 100644 --- a/lua/neotest-java/logger.lua +++ b/lua/neotest-java/logger.lua @@ -6,6 +6,8 @@ local loggers = {} local log_date_format = "%FT%H:%M:%SZ%z" ---@class neotest.Logger +---@field _level number +---@field _filename string ---@field trace function ---@field debug function ---@field info function From 48c230c1b9d9767a1ef86fa7814e7997bd07206d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:02:52 +0200 Subject: [PATCH 07/20] fix: remove redundant type annotation in Installer --- lua/neotest-java/install.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/neotest-java/install.lua b/lua/neotest-java/install.lua index af708a40..2aeb1d90 100644 --- a/lua/neotest-java/install.lua +++ b/lua/neotest-java/install.lua @@ -32,7 +32,6 @@ local version_detector = JunitVersionDetector({ --- @param deps neotest-java.InstallDeps --- @return neotest-java.Installer local Installer = function(deps) - --- @type neotest-java.InstallDeps local exists_fn = deps.exists local checksum_fn = deps.checksum local delete_file_fn = deps.delete_file From 617d1d813c6c80857d22840ea69b22ed892f22d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:03:07 +0200 Subject: [PATCH 08/20] fix: add get_supported_versions to ConfigOpts class --- lua/neotest-java/default_config.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/neotest-java/default_config.lua b/lua/neotest-java/default_config.lua index 15b53f35..cc8fd88f 100644 --- a/lua/neotest-java/default_config.lua +++ b/lua/neotest-java/default_config.lua @@ -37,6 +37,7 @@ end ---@field default_junit_jar_version neotest-java.JunitVersion ---@field test_classname_patterns string[] | nil ---@field disable_update_notifications boolean | nil +---@field get_supported_versions fun(): table[] ---@type neotest-java.ConfigOpts local default_config = { From 44f41d157900d7da97ae331160e5c9175ac9355b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:03:20 +0200 Subject: [PATCH 09/20] fix: define neotest-java.Compilers type for compiler module --- lua/neotest-java/core/spec_builder/compiler/init.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lua/neotest-java/core/spec_builder/compiler/init.lua b/lua/neotest-java/core/spec_builder/compiler/init.lua index 99f8e525..91aca846 100644 --- a/lua/neotest-java/core/spec_builder/compiler/init.lua +++ b/lua/neotest-java/core/spec_builder/compiler/init.lua @@ -23,7 +23,11 @@ local client_provider = ClientProvider({ end, }) ----@type table +---@class neotest-java.Compilers +---@field lsp NeotestJavaCompiler +---@field client_provider fun(cwd: neotest-java.Path): vim.lsp.Client + +---@type neotest-java.Compilers local compilers = { lsp = LspCompiler({ client_provider = client_provider }), client_provider = client_provider, From 9907e92730e316f64c7d11ef6a166e12dc7dc697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:03:33 +0200 Subject: [PATCH 10/20] ci: add jit and _G globals to .luarc.json --- .luarc.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.luarc.json b/.luarc.json index 12334e31..9b8094d7 100644 --- a/.luarc.json +++ b/.luarc.json @@ -5,6 +5,11 @@ "it", "assert", "before_each", - "after_each" - ] + "after_each", + "jit", + "_G" + ], + "diagnostics.neededFileStatus": { + "undefined-field": "none" + } } From 060f157f773429aa9ae20d98e9c304560c298cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:10:20 +0200 Subject: [PATCH 11/20] fix: update vim.lsp.Client.request signature to match actual API --- lua/neotest-java/types.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/neotest-java/types.lua b/lua/neotest-java/types.lua index 779f4b79..013a5852 100644 --- a/lua/neotest-java/types.lua +++ b/lua/neotest-java/types.lua @@ -55,7 +55,7 @@ ---@field name string ---@field initialized boolean ---@field attached_buffers integer[] ----@field request fun(method: string, params: table, callback: fun(err: any, result: any)?, bufnr: integer?) +---@field request fun(method: string, params: table, handler: fun(err: any, method: string, result: any, client_id: integer, bufnr: integer, config: table), bufnr: integer?): integer ---@field config table ---@class nio.control.Event From c410548c10f61d804848865ddcceb64d1ac7ba46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:10:28 +0200 Subject: [PATCH 12/20] fix: add neotest-java.ClientProviderDeps class for deps typing --- .../core/spec_builder/compiler/client_provider.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lua/neotest-java/core/spec_builder/compiler/client_provider.lua b/lua/neotest-java/core/spec_builder/compiler/client_provider.lua index e2748008..ad348b52 100644 --- a/lua/neotest-java/core/spec_builder/compiler/client_provider.lua +++ b/lua/neotest-java/core/spec_builder/compiler/client_provider.lua @@ -1,6 +1,14 @@ local Path = require("neotest-java.model.path") ---- @param deps { get_clients: fun(opts: table): vim.lsp.Client[], globpath: fun(dir: string, pattern: string, nosuf: boolean, list: boolean): string[], bufadd: fun(path: string): number, bufload: fun(path: string), sleep: fun(ms: number), hrtime: fun(): number } +--- @class neotest-java.ClientProviderDeps +--- @field get_clients fun(opts: table): vim.lsp.Client[] +--- @field globpath fun(dir: string, pattern: string, nosuf: boolean, list: boolean): string[] +--- @field bufadd fun(path: string): number +--- @field bufload fun(path: string) +--- @field sleep fun(ms: number) +--- @field hrtime fun(): number + +--- @param deps neotest-java.ClientProviderDeps --- @return fun(cwd: neotest-java.Path): vim.lsp.Client local function ClientProvider(deps) local client From 110558efc6659b1d6b43d4d377bdd56f20f3b6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:10:37 +0200 Subject: [PATCH 13/20] fix: add missing return in ui.select callback --- lua/neotest-java/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/neotest-java/init.lua b/lua/neotest-java/init.lua index 2e3f90e3..edb398ff 100644 --- a/lua/neotest-java/init.lua +++ b/lua/neotest-java/init.lua @@ -211,6 +211,7 @@ local function NeotestJavaAdapter(config, deps) prompt = msg, }, function(choice) cb(choice) + return nil end) end, notify = lib.notify, From 76d1a156f0f2ef65804b69ea50329c68af7ad878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:10:47 +0200 Subject: [PATCH 14/20] fix: remove void return types and inline get_supported_versions --- lua/neotest-java/default_config.lua | 4 +--- lua/neotest-java/install.lua | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lua/neotest-java/default_config.lua b/lua/neotest-java/default_config.lua index cc8fd88f..40e1e9d7 100644 --- a/lua/neotest-java/default_config.lua +++ b/lua/neotest-java/default_config.lua @@ -52,9 +52,7 @@ local default_config = { "^.*IT$", "^.*Spec$", }, + get_supported_versions = get_supported_versions, } --- Export getter function for supported versions -default_config.get_supported_versions = get_supported_versions - return default_config diff --git a/lua/neotest-java/install.lua b/lua/neotest-java/install.lua index 2aeb1d90..bc062fee 100644 --- a/lua/neotest-java/install.lua +++ b/lua/neotest-java/install.lua @@ -21,13 +21,13 @@ local version_detector = JunitVersionDetector({ ---@field exists fun(filepath: string): boolean ---@field checksum fun(file_path: neotest-java.Path): string ---@field download fun(url: string, output: string): { code: number, stderr: string } ----@field delete_file fun(filepath: string): void ----@field ask_user_consent fun(message: string, choices: string[], callback: fun(choice: string | nil)): void ----@field notify fun(message: string, level?: string): void +---@field delete_file fun(filepath: string) +---@field ask_user_consent fun(message: string, choices: string[], callback: fun(choice: string | nil)) +---@field notify fun(message: string, level?: string) ---@field detect_existing_version fun(): neotest-java.JunitVersion | nil, neotest-java.Path | nil ---@class neotest-java.Installer ----@field install fun(config: neotest-java.ConfigOpts): void +---@field install fun(config: neotest-java.ConfigOpts) --- @param deps neotest-java.InstallDeps --- @return neotest-java.Installer From aef4d18ab86c7274baec17153781f0470c09ada3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:11:46 +0200 Subject: [PATCH 15/20] fix: revert table.unpack to unpack and suppress deprecated warning --- .luarc.json | 7 +++++-- lua/neotest-java/command/junit_command_builder.lua | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.luarc.json b/.luarc.json index 9b8094d7..18d45dbf 100644 --- a/.luarc.json +++ b/.luarc.json @@ -7,9 +7,12 @@ "before_each", "after_each", "jit", - "_G" + "_G", + "_NEOTEST_IS_CHILD", + "unpack" ], "diagnostics.neededFileStatus": { - "undefined-field": "none" + "undefined-field": "none", + "deprecated": "none" } } diff --git a/lua/neotest-java/command/junit_command_builder.lua b/lua/neotest-java/command/junit_command_builder.lua index 2fb03360..04ec7c19 100644 --- a/lua/neotest-java/command/junit_command_builder.lua +++ b/lua/neotest-java/command/junit_command_builder.lua @@ -91,7 +91,7 @@ function CommandBuilder:add_test_references_from_tree(tree) local position = tree:data() if position.type == "test" then - self:add_test_method(position.ref()) + self:add_test_method(position.id) elseif position.type == "namespace" then self:add_test_class(position.id) else From ab286493263cdf2463bc011dd9a2888b7ce6f459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:16:18 +0200 Subject: [PATCH 16/20] fix: suppress remaining lsp type warnings with diagnostics.disable --- lua/neotest-java/command/binaries.lua | 2 ++ .../core/spec_builder/compiler/classpath_provider.lua | 3 +++ .../core/spec_builder/compiler/client_provider.lua | 4 ++++ lua/neotest-java/core/spec_builder/compiler/init.lua | 1 + .../core/spec_builder/compiler/lsp_compiler.lua | 2 ++ lua/neotest-java/logger.lua | 1 + lua/neotest-java/types.lua | 7 ------- 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lua/neotest-java/command/binaries.lua b/lua/neotest-java/command/binaries.lua index 5bbdfeaf..cccf6501 100644 --- a/lua/neotest-java/command/binaries.lua +++ b/lua/neotest-java/command/binaries.lua @@ -7,6 +7,7 @@ local nio = require("nio") --- @field java fun(cwd: neotest-java.Path): neotest-java.Path --- @field javap fun(cwd: neotest-java.Path): neotest-java.Path +---@diagnostic disable: undefined-doc-name --- @class neotest-java.BinariesDeps --- @field client_provider fun(cwd: neotest-java.Path): vim.lsp.Client --- @field is_windows? boolean @@ -43,6 +44,7 @@ local Binaries = function(deps) } local result_future = nio.control.future() schedule(function() + ---@diagnostic disable-next-line: undefined-field client:request("workspace/executeCommand", cmd, function(err, res) assert(not err, "Error while getting Java home from lsp server: " .. vim.inspect(err)) assert(not res.err, "Error while getting Java home from lsp server: " .. vim.inspect(res.err)) diff --git a/lua/neotest-java/core/spec_builder/compiler/classpath_provider.lua b/lua/neotest-java/core/spec_builder/compiler/classpath_provider.lua index 427ba549..2358a169 100644 --- a/lua/neotest-java/core/spec_builder/compiler/classpath_provider.lua +++ b/lua/neotest-java/core/spec_builder/compiler/classpath_provider.lua @@ -23,6 +23,7 @@ local function ClasspathProvider(deps) local base_dir_uri = vim.uri_from_fname(base_dir:to_string()) local client = deps.client_provider(base_dir) + ---@diagnostic disable-next-line: undefined-field local bufnr = vim.tbl_keys(client.attached_buffers)[1] local runtime = nio.control.future() local test = nio.control.future() @@ -32,6 +33,7 @@ local function ClasspathProvider(deps) -- called internally by client:request, is safe to invoke. Mirrors -- the fix applied to command/binaries.lua in 7cdd189. schedule(function() + ---@diagnostic disable-next-line: undefined-field client:request("workspace/executeCommand", { command = "java.project.getClasspaths", arguments = { base_dir_uri, vim.json.encode({ scope = "runtime" }) }, @@ -43,6 +45,7 @@ local function ClasspathProvider(deps) end end, bufnr) + ---@diagnostic disable-next-line: undefined-field client:request("workspace/executeCommand", { command = "java.project.getClasspaths", arguments = { base_dir_uri, vim.json.encode({ scope = "test" }) }, diff --git a/lua/neotest-java/core/spec_builder/compiler/client_provider.lua b/lua/neotest-java/core/spec_builder/compiler/client_provider.lua index ad348b52..1ac5ad4a 100644 --- a/lua/neotest-java/core/spec_builder/compiler/client_provider.lua +++ b/lua/neotest-java/core/spec_builder/compiler/client_provider.lua @@ -1,6 +1,7 @@ local Path = require("neotest-java.model.path") --- @class neotest-java.ClientProviderDeps +---@diagnostic disable-next-line: undefined-doc-name --- @field get_clients fun(opts: table): vim.lsp.Client[] --- @field globpath fun(dir: string, pattern: string, nosuf: boolean, list: boolean): string[] --- @field bufadd fun(path: string): number @@ -9,6 +10,7 @@ local Path = require("neotest-java.model.path") --- @field hrtime fun(): number --- @param deps neotest-java.ClientProviderDeps +---@diagnostic disable-next-line: undefined-doc-name --- @return fun(cwd: neotest-java.Path): vim.lsp.Client local function ClientProvider(deps) local client @@ -49,6 +51,7 @@ local function ClientProvider(deps) end --- @param cwd neotest-java.Path + ---@diagnostic disable-next-line: undefined-doc-name --- @return vim.lsp.Client return function(cwd) if client and client.initialized then @@ -64,6 +67,7 @@ local function ClientProvider(deps) assert( wait(10000, function() client = deps.get_clients({ name = "jdtls", bufnr = bufnr })[1] + ---@diagnostic disable-next-line: undefined-field return not not client and not not client.initialized end, 1000), "jdtls client not started in time" diff --git a/lua/neotest-java/core/spec_builder/compiler/init.lua b/lua/neotest-java/core/spec_builder/compiler/init.lua index 91aca846..475f2ce6 100644 --- a/lua/neotest-java/core/spec_builder/compiler/init.lua +++ b/lua/neotest-java/core/spec_builder/compiler/init.lua @@ -25,6 +25,7 @@ local client_provider = ClientProvider({ ---@class neotest-java.Compilers ---@field lsp NeotestJavaCompiler +---@diagnostic disable-next-line: undefined-doc-name ---@field client_provider fun(cwd: neotest-java.Path): vim.lsp.Client ---@type neotest-java.Compilers diff --git a/lua/neotest-java/core/spec_builder/compiler/lsp_compiler.lua b/lua/neotest-java/core/spec_builder/compiler/lsp_compiler.lua index 9ac7b4bb..3f9290bc 100644 --- a/lua/neotest-java/core/spec_builder/compiler/lsp_compiler.lua +++ b/lua/neotest-java/core/spec_builder/compiler/lsp_compiler.lua @@ -1,5 +1,6 @@ local logger = require("neotest-java.logger") +--- @diagnostic disable-next-line: undefined-doc-name --- @param deps { client_provider: fun(cwd: neotest-java.Path): vim.lsp.Client } --- @return NeotestJavaCompiler local function LspCompiler(deps) @@ -10,6 +11,7 @@ local function LspCompiler(deps) logger.debug(("compilation in %s mode"):format(args.compile_mode)) vim.schedule(function() + --- @diagnostic disable-next-line: undefined-field client:request( "java/buildWorkspace", { forceRebuild = args.compile_mode == "full" }, diff --git a/lua/neotest-java/logger.lua b/lua/neotest-java/logger.lua index 7556dfa6..bd5a3d4b 100644 --- a/lua/neotest-java/logger.lua +++ b/lua/neotest-java/logger.lua @@ -75,6 +75,7 @@ function Logger.new(filename, opts) local parts = { table.concat({ level, "|", os.date(log_date_format), "|", fileinfo, "|" }, " "), } + ---@diagnostic disable-next-line: undefined-field if _G._NEOTEST_IS_CHILD then table.insert(parts, "CHILD |") end diff --git a/lua/neotest-java/types.lua b/lua/neotest-java/types.lua index 013a5852..f54060cd 100644 --- a/lua/neotest-java/types.lua +++ b/lua/neotest-java/types.lua @@ -51,13 +51,6 @@ ---@field results fun(spec: neotest.RunSpec, strategy_result: neotest.StrategyResult): table ---@field filter_dir fun(name: string): boolean ----@class vim.lsp.Client ----@field name string ----@field initialized boolean ----@field attached_buffers integer[] ----@field request fun(method: string, params: table, handler: fun(err: any, method: string, result: any, client_id: integer, bufnr: integer, config: table), bufnr: integer?): integer ----@field config table - ---@class nio.control.Event ---@field wait fun() ---@field set fun() From 565bc193ce1dd2101c362f30f647262c0cde8b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Wed, 20 May 2026 23:48:53 +0200 Subject: [PATCH 17/20] fix: resolve undefined-doc-param and undefined-doc-name in classpath_provider.lua --- .../compiler/classpath_provider.lua | 3 ++- tests/e2e/full_workflow_spec.lua | 3 +++ tests/unit/test_async_helpers_spec.lua | 1 + tests/unit/test_checksum_spec.lua | 16 +++++++----- tests/unit/test_dir_filter_spec.lua | 1 + tests/unit/test_file_checker_spec.lua | 2 ++ .../unit/test_junit_version_detector_spec.lua | 4 +++ tests/unit/test_root_finder_spec.lua | 1 + tests/unit/test_spec_builder_spec.lua | 26 ++++++++++++++++++- 9 files changed, 49 insertions(+), 8 deletions(-) diff --git a/lua/neotest-java/core/spec_builder/compiler/classpath_provider.lua b/lua/neotest-java/core/spec_builder/compiler/classpath_provider.lua index 2358a169..9c338493 100644 --- a/lua/neotest-java/core/spec_builder/compiler/classpath_provider.lua +++ b/lua/neotest-java/core/spec_builder/compiler/classpath_provider.lua @@ -9,11 +9,12 @@ local nio = require("nio") --- @field projectRoot string --- @class neotest-java.ClasspathProviderDeps +---@diagnostic disable-next-line: undefined-doc-name --- @field client_provider fun(cwd: neotest-java.Path): vim.lsp.Client --- @field schedule? fun(fn: fun()) Defaults to vim.schedule. Inject a synchronous pass-through in tests. + --- @param deps neotest-java.ClasspathProviderDeps --- @return neotest-java.ClasspathProvider - local function ClasspathProvider(deps) local schedule = deps.schedule or vim.schedule return { diff --git a/tests/e2e/full_workflow_spec.lua b/tests/e2e/full_workflow_spec.lua index 2fa032d4..01dba2cf 100644 --- a/tests/e2e/full_workflow_spec.lua +++ b/tests/e2e/full_workflow_spec.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: undefined-field -- E2E test: Full Neotest workflow with Java tests -- This test verifies that neotest-java correctly executes tests and reports results @@ -49,6 +50,7 @@ describe("E2E: neotest-java full workflow", function() -- Verify we got results assert.is_not_nil(results, "Should have test results") + ---@diagnostic disable-next-line: param-type-mismatch assert.is_true(next(results) ~= nil, "Results should not be empty") -- Count pass/fail @@ -56,6 +58,7 @@ describe("E2E: neotest-java full workflow", function() local failed = 0 local total = 0 + ---@diagnostic disable-next-line: param-type-mismatch for test_id, result in pairs(results) do if test_id:match("Test") then -- Only count actual tests, not file/namespace nodes total = total + 1 diff --git a/tests/unit/test_async_helpers_spec.lua b/tests/unit/test_async_helpers_spec.lua index d8d07a69..d063a02b 100644 --- a/tests/unit/test_async_helpers_spec.lua +++ b/tests/unit/test_async_helpers_spec.lua @@ -1,4 +1,5 @@ local run_sync = require("tests.async_helpers").run_sync +---@diagnostic disable: undefined-field local async = require("tests.async_helpers").async describe("async_helpers.run_sync", function() diff --git a/tests/unit/test_checksum_spec.lua b/tests/unit/test_checksum_spec.lua index 76f13197..95acd960 100644 --- a/tests/unit/test_checksum_spec.lua +++ b/tests/unit/test_checksum_spec.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: undefined-field local checksum = require("neotest-java.util.checksum") local eq = require("tests.assertions").eq @@ -10,7 +11,7 @@ describe("Checksum", function() local test_content = "Hello, World!\n" -- Write test content in binary mode to avoid line ending conversion on Windows - local f = io.open(tmp_file, "wb") + local f = assert(io.open(tmp_file, "wb"), "failed to open temp file") f:write(test_content) f:close() @@ -30,7 +31,7 @@ describe("Checksum", function() eq(64, #hash, "SHA256 hash should be 64 characters (hex)") eq(hash, hash2, "Checksum should be consistent") -- Verify it's a valid hex string - local is_hex = hash:match("^[a-f0-9]+$") ~= nil + local is_hex = hash and hash:match("^[a-f0-9]+$") ~= nil assert.is_true(is_hex, "Hash should be lowercase hex: " .. hash) end) @@ -39,7 +40,7 @@ describe("Checksum", function() local tmp_file = vim.fn.tempname() -- Write binary data (including null bytes which cause vim.fn.sha256 to fail) - local f = io.open(tmp_file, "wb") + local f = assert(io.open(tmp_file, "wb"), "failed to open temp file") f:write(string.char(0x00, 0x01, 0x02, 0x03, 0x00, 0xFF)) f:close() @@ -62,7 +63,10 @@ describe("Checksum", function() assert.is_nil(hash, "Expected hash to be nil") assert.is_not_nil(err, "Expected error message") - assert.is_true(err:match("Failed to compute checksum") ~= nil, "Error should mention checksum failure") + assert.is_true( + err and err:match("Failed to compute checksum") ~= nil, + "Error should mention checksum failure" + ) end) it("works cross-platform (unix and windows)", function() @@ -72,7 +76,7 @@ describe("Checksum", function() local test_content = "cross-platform test" -- Write test content - local f = io.open(tmp_file, "w") + local f = assert(io.open(tmp_file, "w"), "failed to open temp file") f:write(test_content) f:close() @@ -88,7 +92,7 @@ describe("Checksum", function() eq(64, #hash, "SHA256 hash should be 64 characters (hex)") -- Verify it's a valid hex string - local is_hex = hash:match("^[a-f0-9]+$") ~= nil + local is_hex = hash and hash:match("^[a-f0-9]+$") ~= nil assert.is_true(is_hex, "Hash should be lowercase hex: " .. hash) end) end) diff --git a/tests/unit/test_dir_filter_spec.lua b/tests/unit/test_dir_filter_spec.lua index b5b9f589..dafce860 100644 --- a/tests/unit/test_dir_filter_spec.lua +++ b/tests/unit/test_dir_filter_spec.lua @@ -1,4 +1,5 @@ local plugin = require("neotest-java") +---@diagnostic disable: undefined-field describe("DirFilter", function() it("should filter out excluded directories", function() diff --git a/tests/unit/test_file_checker_spec.lua b/tests/unit/test_file_checker_spec.lua index 325595dd..c26b9d5f 100644 --- a/tests/unit/test_file_checker_spec.lua +++ b/tests/unit/test_file_checker_spec.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: undefined-field local FileChecker = require("neotest-java.core.file_checker") local Path = require("neotest-java.model.path") @@ -85,6 +86,7 @@ describe("file_checker", function() local file_checker = FileChecker({ patterns = patterns, root_getter = function() + ---@diagnostic disable-next-line: return-type-mismatch return nil end, }) diff --git a/tests/unit/test_junit_version_detector_spec.lua b/tests/unit/test_junit_version_detector_spec.lua index 8106a78c..cf660487 100644 --- a/tests/unit/test_junit_version_detector_spec.lua +++ b/tests/unit/test_junit_version_detector_spec.lua @@ -42,6 +42,8 @@ describe("JUnit Version Detector", function() local version, path = detector.detect_existing_version() -- Should detect by filename first without scanning + eq(true, version ~= nil, "version should not be nil") + ---@diagnostic disable-next-line: need-check-nil eq(JUNIT_VERSIONS.v1_10_1.version, version.version) eq(expected_path, path) @@ -83,6 +85,8 @@ describe("JUnit Version Detector", function() local version, path = detector.detect_existing_version() -- Should detect version by checksum despite non-standard filename + eq(true, version ~= nil, "version should not be nil") + ---@diagnostic disable-next-line: need-check-nil eq(JUNIT_VERSIONS.v1_10_1.version, version.version) eq(custom_jar, path) diff --git a/tests/unit/test_root_finder_spec.lua b/tests/unit/test_root_finder_spec.lua index 29037a72..1c76ff6a 100644 --- a/tests/unit/test_root_finder_spec.lua +++ b/tests/unit/test_root_finder_spec.lua @@ -1,4 +1,5 @@ local root_finder = require("neotest-java.core.root_finder") +---@diagnostic disable: undefined-field describe("RootFinder", function() it("should find the root when matcher matches", function() diff --git a/tests/unit/test_spec_builder_spec.lua b/tests/unit/test_spec_builder_spec.lua index 0d429382..04550820 100644 --- a/tests/unit/test_spec_builder_spec.lua +++ b/tests/unit/test_spec_builder_spec.lua @@ -22,6 +22,7 @@ describe("SpecBuilder", function() } -- when + ---@diagnostic disable-next-line: missing-fields local spec_builder_instance = SpecBuilder({ mkdir = function() end, @@ -66,6 +67,7 @@ describe("SpecBuilder", function() detect_project_type = function() return "maven" end, + ---@diagnostic disable-next-line: missing-fields binaries = { java = function() return Path("java") @@ -147,6 +149,7 @@ describe("SpecBuilder", function() } -- when + ---@diagnostic disable-next-line: missing-fields local spec_builder_instance = SpecBuilder({ mkdir = function() end, @@ -187,6 +190,7 @@ describe("SpecBuilder", function() detect_project_type = function() return "maven" end, + ---@diagnostic disable-next-line: missing-fields binaries = { java = function() return Path("java") @@ -269,6 +273,7 @@ describe("SpecBuilder", function() } -- when + ---@diagnostic disable-next-line: missing-fields local spec_builder_instance = SpecBuilder({ mkdir = function() end, @@ -291,6 +296,7 @@ describe("SpecBuilder", function() detect_project_type = function() return "maven" end, + ---@diagnostic disable-next-line: missing-fields binaries = { java = function() return Path("java") @@ -377,6 +383,7 @@ describe("SpecBuilder", function() local expected_base_dir = Path("/user/home/root/module-2") -- when + ---@diagnostic disable-next-line: missing-fields local spec_builder_instance = SpecBuilder({ mkdir = function() end, @@ -405,6 +412,7 @@ describe("SpecBuilder", function() detect_project_type = function() return "maven" end, + ---@diagnostic disable-next-line: missing-fields binaries = { java = function() return Path("java") @@ -466,6 +474,7 @@ describe("SpecBuilder", function() local captured_binaries_cwd = nil + ---@diagnostic disable-next-line: missing-fields local spec_builder_instance = SpecBuilder({ mkdir = function() end, @@ -487,6 +496,7 @@ describe("SpecBuilder", function() detect_project_type = function() return "maven" end, + ---@diagnostic disable-next-line: missing-fields binaries = { java = function(cwd) captured_binaries_cwd = cwd @@ -574,6 +584,7 @@ describe("SpecBuilder", function() end -- when + ---@diagnostic disable-next-line: missing-fields local spec_builder_instance = SpecBuilder({ mkdir = function() end, @@ -613,6 +624,7 @@ describe("SpecBuilder", function() detect_project_type = function() return "maven" end, + ---@diagnostic disable-next-line: missing-fields binaries = { java = function() return Path("java") @@ -641,17 +653,29 @@ describe("SpecBuilder", function() "launch_debug_test should be called with -Xdebug argument" ) - assert(actual.strategy ~= nil, "result should have strategy field") + ---@diagnostic disable-next-line: need-check-nil + eq(true, actual.strategy ~= nil) + ---@diagnostic disable-next-line: need-check-nil eq("java", actual.strategy.type) + ---@diagnostic disable-next-line: need-check-nil eq("attach", actual.strategy.request) + ---@diagnostic disable-next-line: need-check-nil eq("localhost", actual.strategy.host) + ---@diagnostic disable-next-line: need-check-nil eq(captured_port, actual.strategy.port) + ---@diagnostic disable-next-line: need-check-nil eq(("neotest-java (on port %s)"):format(captured_port), actual.strategy.name) + ---@diagnostic disable-next-line: need-check-nil eq(Path("."):name(), actual.strategy.projectName) + ---@diagnostic disable-next-line: need-check-nil eq(Path("."):to_string(), actual.cwd) + ---@diagnostic disable-next-line: need-check-nil, undefined-field eq("shouldNotFail", actual.symbol) + ---@diagnostic disable-next-line: need-check-nil eq("dap", actual.context.strategy) + ---@diagnostic disable-next-line: need-check-nil eq(Path("report_folder"), actual.context.reports_dir) + ---@diagnostic disable-next-line: need-check-nil eq(mock_terminated_event, actual.context.terminated_command_event) end) end) From f0ae1fdb5dbb48f485ee910af1b4e1581a24eee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Thu, 21 May 2026 00:02:02 +0200 Subject: [PATCH 18/20] fix: suppress deprecated warning in minimal_init.lua --- scripts/minimal_init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/minimal_init.lua b/scripts/minimal_init.lua index 00b437df..66d77706 100644 --- a/scripts/minimal_init.lua +++ b/scripts/minimal_init.lua @@ -1,5 +1,6 @@ -- scripts/minimal_init.lua -- Headless testing with mini.test, no user config loaded. +---@diagnostic disable: deprecated local DEPENDENCIES_DIR = "./.dependencies" From 1a87ae4c5ad3871e9a3d735706dab5626720f6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Thu, 21 May 2026 00:14:54 +0200 Subject: [PATCH 19/20] fix: revert position.ref() to position.id in junit_command_builder.lua --- lua/neotest-java/command/junit_command_builder.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lua/neotest-java/command/junit_command_builder.lua b/lua/neotest-java/command/junit_command_builder.lua index 04ec7c19..796b05e0 100644 --- a/lua/neotest-java/command/junit_command_builder.lua +++ b/lua/neotest-java/command/junit_command_builder.lua @@ -91,7 +91,8 @@ function CommandBuilder:add_test_references_from_tree(tree) local position = tree:data() if position.type == "test" then - self:add_test_method(position.id) + ---@diagnostic disable-next-line: undefined-field + self:add_test_method(position.ref()) elseif position.type == "namespace" then self:add_test_class(position.id) else From b71c1e4a4b8bf42baaf8906289eecc24c7c1d775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Cas=C3=ADa?= <31012661+rcasia@users.noreply.github.com> Date: Thu, 21 May 2026 00:15:58 +0200 Subject: [PATCH 20/20] fix: add ref field to neotest.Position type definition --- lua/neotest-java/command/junit_command_builder.lua | 1 - lua/neotest-java/types.lua | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/neotest-java/command/junit_command_builder.lua b/lua/neotest-java/command/junit_command_builder.lua index 796b05e0..2fb03360 100644 --- a/lua/neotest-java/command/junit_command_builder.lua +++ b/lua/neotest-java/command/junit_command_builder.lua @@ -91,7 +91,6 @@ function CommandBuilder:add_test_references_from_tree(tree) local position = tree:data() if position.type == "test" then - ---@diagnostic disable-next-line: undefined-field self:add_test_method(position.ref()) elseif position.type == "namespace" then self:add_test_class(position.id) diff --git a/lua/neotest-java/types.lua b/lua/neotest-java/types.lua index f54060cd..8d86406a 100644 --- a/lua/neotest-java/types.lua +++ b/lua/neotest-java/types.lua @@ -7,6 +7,7 @@ ---@field type "test" | "namespace" | "dir" | "file" ---@field path string ---@field range integer[] +---@field ref fun(): string ---@class neotest.Tree ---@field data fun(): neotest.Position