Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lua/neotest-java/command/junit_command_builder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ local CommandBuilder = {

local method_name
if type == "test" then
method_name = node_name
method_name = qualified_name
end

self._test_references[#self._test_references + 1] = {
Expand Down Expand Up @@ -99,7 +99,7 @@ local CommandBuilder = {
local selectors = {}
for _, v in ipairs(self._test_references) do
if v.type == "test" then
table.insert(selectors, "-m=" .. v.qualified_name .. "#" .. v.method_name)
table.insert(selectors, "--select-method='" .. v.qualified_name .. "'")
elseif v.type == "file" then
table.insert(selectors, "-c=" .. v.qualified_name)
elseif v.type == "dir" then
Expand Down
214 changes: 214 additions & 0 deletions lua/neotest-java/core/positions_discoverer_dev.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
local lib = require("neotest.lib")
local Tree = require("neotest.types").Tree

local PositionsDiscoverer = {}

---Given a file path, parse all the tests within it.
---@async
---@param file_path string Absolute file path
---@return neotest.Tree | nil
function PositionsDiscoverer.discover_positions(file_path)
local src = lib.files.read(file_path)

-- We only need to capture package and test-method names.
local query = vim.treesitter.query.parse(
"java",
[[

;; Package declaration
(program
(package_declaration
(scoped_identifier) @package.name
)?
)

;; Test class
(class_declaration
name: (identifier) @class.name
) @class.definition

;; Annotated test methods
(method_declaration
(modifiers
[
(marker_annotation
name: (identifier) @annotation
(#any-of? @annotation "Test" "ParameterizedTest" "TestFactory" "CartesianTest")
)
(annotation
name: (identifier) @annotation
(#any-of? @annotation "Test" "ParameterizedTest" "TestFactory" "CartesianTest")
)
]
)
name: (identifier) @test.name
) @test.definition

]]
)

local ts_tree = vim.treesitter.get_string_parser(src, "java"):parse()[1]

-- function just to take the pacakage name
--- @return string | nil
local get_package_name = function()
local result = nil
for id, node in query:iter_captures(ts_tree:root(), src, 0, -1) do
local cap = query.captures[id]
if cap == "package.name" then
result = (vim.treesitter.get_node_text(node, src) or ""):gsub("%s+", "")
break
end
end
return result
end

local pkg = get_package_name()

--- recursively build list of nodes from TSNode tree
--- @param node TSNode
--- @return {id: string, name: string, path: string, range: table}[]
local function build_tree(node)
local captures = vim
.iter(query:iter_captures(node, src, 0, -1))
---@param child TSNode
:filter(function(_, child)
return not child:parent() or child:parent() == node
end)
:map(function(id, child)
return {
id = id,
child = child,
}
end)
:totable()

return vim
.iter(captures)
:map(function(c)
return query.captures[c.id], c.child
end)
--- @param child TSNode
:map(function(cap, child)
if cap == "package.declaration" then
return {
id = pkg or "<no package>",
name = file_path:gsub(".*/", ""),
path = file_path,
range = { node:range() },
}
end

if cap == "class.definition" then
local name = vim.treesitter.get_node_text(child:field("name")[1], src) or "Unknown"

local function is_nonempty(x)
if x == nil then
return false
end
if type(x) ~= "table" then
return true
end
return next(x) ~= nil -- tabla vacía => false
end
local children = vim.iter(child:iter_children()):map(build_tree):filter(is_nonempty):totable()
local children_flattered = vim.iter(children):flatten():totable()

local inner_classname = name
local cur = child:parent()
while cur do
if cur:type() == "class_declaration" then
inner_classname = vim.treesitter.get_node_text(cur:field("name")[1], src)
.. "$"
.. inner_classname
end
cur = cur:parent()
end

local fqn = (pkg and (pkg .. ".") or "") .. inner_classname

-- return {
-- {
-- id = fqn,
-- name = name,
-- path = file_path,
-- range = { child:range() },
-- type = "namespace",
-- },
-- unpack(children_flattered),
-- }
--
--
--
-- construye el nodo de clase y pega sus hijos SIN flatten
local nodes = {
{
id = fqn,
name = name,
path = file_path,
range = { child:range() },
type = "namespace",
},
}

for _, subtree in ipairs(children) do
-- subtree puede ser:
-- - una lista { namespace, ...children }
-- - un único nodo (p.ej., un método)
table.insert(nodes, subtree)
end

print(vim.inspect({ fqn = fqn, n = nodes }))
return nodes
end

if cap == "test.definition" then
local name = vim.treesitter.get_node_text(child:field("name")[1], src) or "Unknown"

local parts = {}
local cur = child:parent()
while cur do
if cur:type() == "class_declaration" then
parts[#parts + 1] = vim.treesitter.get_node_text(cur:field("name")[1], src)
end
cur = cur:parent()
end

local inner_classname = vim.iter(parts):rev():join("$")

local fqn = (pkg and (pkg .. ".") or "") .. inner_classname .. "#" .. name

return {
{
id = fqn,
name = name,
path = file_path,
range = { child:range() },
type = "test",
},
}
end
end)
:flatten()
:totable()
end

local l = build_tree(ts_tree:root())

print("L: " .. vim.inspect(l))

return Tree.from_list({
{
id = file_path,
name = file_path:gsub(".*/", ""),
path = file_path,
range = { ts_tree:root():range() },
type = "file",
},
l,
}, function(pos)
return pos.id
end)
end

return PositionsDiscoverer
4 changes: 2 additions & 2 deletions lua/neotest-java/core/result_builder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function ResultBuilder.build_results(spec, result, tree, scan, read_file) -- lua
local classname = jresult:classname()

name = name:gsub("%(.*%)", "")
local unique_key = build_unique_key(classname, name)
local unique_key = classname .. "#" .. name
testcases[unique_key] = testcase
testcases_junit[unique_key] = jresult
end
Expand Down Expand Up @@ -140,7 +140,7 @@ function ResultBuilder.build_results(spec, result, tree, scan, read_file) -- lua
qualified_name = qualified_name .. "::" .. inner_classes
end

local unique_key = build_unique_key(qualified_name, node.name)
local unique_key = node.id

if is_parameterized then
local jtestcases = extract_parameterized_tests(testcases, unique_key)
Expand Down
9 changes: 4 additions & 5 deletions lua/neotest-java/core/spec_builder/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,16 @@ function SpecBuilder.build_spec(args, project_type, config)
command:test_reference(resolve_qualfied_name(child.path), child.name, "file")
end
end
elseif position.type == "file" then
command:test_reference(resolve_qualfied_name(absolute_path), position.name, "file")
elseif position.type == "namespace" then
for _, child in tree:iter() do
if child.type == "test" then
command:test_reference(resolve_qualfied_name(child.path), child.name, "test")
command:test_reference(child.id, child.name, "test")
end
end
elseif position.type == "file" then
command:test_reference(resolve_qualfied_name(absolute_path), position.name, "file")
elseif position.type == "test" then
-- note: parameterized tests are not being discovered by the junit standalone, so we run tests per file
command:test_reference(resolve_qualfied_name(absolute_path), position.name, "file")
command:test_reference(position.id, position.name, "test")
end

-- COMPILATION STEP
Expand Down
5 changes: 3 additions & 2 deletions lua/neotest-java/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ local File = require("neotest.lib.file")
local file_checker = require("neotest-java.core.file_checker")
local root_finder = require("neotest-java.core.root_finder")
local dir_filter = require("neotest-java.core.dir_filter")
local position_discoverer = require("neotest-java.core.positions_discoverer")
-- local position_discoverer = require("neotest-java.core.positions_discoverer")
local position_discoverer = require("neotest-java.core.positions_discoverer_dev")
local spec_builder = require("neotest-java.core.spec_builder")
local result_builder = require("neotest-java.core.result_builder")
local log = require("neotest-java.logger")
Expand Down Expand Up @@ -55,7 +56,7 @@ local NeotestJavaAdapter = {
-- build spec
return spec_builder.build_spec(args, project_type, ch.get_context().config)
end,
};
}

-- on init
(function()
Expand Down
Loading
Loading