write all failed test into the quickfix list
This commit is contained in:
@@ -286,6 +286,63 @@ local function split_output_lines(text)
|
||||
return lines
|
||||
end
|
||||
|
||||
local function normalize_go_name(name)
|
||||
if not name or name == "" then
|
||||
return nil
|
||||
end
|
||||
return (name:gsub("%s+", "_"))
|
||||
end
|
||||
|
||||
local function add_location(target, key, file, line, label)
|
||||
if not key or key == "" or not file or file == "" or not line then
|
||||
return
|
||||
end
|
||||
local text = label or key
|
||||
if not target[key] then
|
||||
target[key] = {}
|
||||
end
|
||||
table.insert(target[key], {
|
||||
filename = file,
|
||||
lnum = line,
|
||||
col = 1,
|
||||
text = text,
|
||||
})
|
||||
end
|
||||
|
||||
local function collect_file_locations(file, target)
|
||||
local ok, lines = pcall(vim.fn.readfile, file)
|
||||
if not ok or type(lines) ~= "table" then
|
||||
return
|
||||
end
|
||||
local funcs = find_test_functions(lines)
|
||||
for _, fn in ipairs(funcs) do
|
||||
add_location(target, fn.name, file, fn.start + 1, fn.name)
|
||||
local normalized = normalize_go_name(fn.name)
|
||||
if normalized and normalized ~= fn.name then
|
||||
add_location(target, normalized, file, fn.start + 1, fn.name)
|
||||
end
|
||||
for _, sub in ipairs(find_t_runs(lines, fn)) do
|
||||
local full = fn.name .. "/" .. sub.name
|
||||
add_location(target, full, file, sub.start + 1, full)
|
||||
local normalized_full = normalize_go_name(full)
|
||||
if normalized_full and normalized_full ~= full then
|
||||
add_location(target, normalized_full, file, sub.start + 1, full)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function collect_go_test_files(root)
|
||||
if not root or root == "" then
|
||||
root = vim.loop.cwd()
|
||||
end
|
||||
local files = vim.fn.globpath(root, "**/*_test.go", false, true)
|
||||
if type(files) ~= "table" then
|
||||
return {}
|
||||
end
|
||||
return files
|
||||
end
|
||||
|
||||
function runner.parse_test_output(output)
|
||||
local out = {}
|
||||
if not output or output == "" then
|
||||
@@ -399,4 +456,47 @@ function runner.build_failed_command(last_command, failures, _scope_kind)
|
||||
}
|
||||
end
|
||||
|
||||
function runner.collect_failed_locations(failures, command, scope_kind)
|
||||
if type(failures) ~= "table" or #failures == 0 then
|
||||
return {}
|
||||
end
|
||||
local files = {}
|
||||
if scope_kind == "all" then
|
||||
files = collect_go_test_files(command and command.cwd or nil)
|
||||
elseif command and command.file then
|
||||
files = { command.file }
|
||||
end
|
||||
if #files == 0 then
|
||||
return {}
|
||||
end
|
||||
local locations = {}
|
||||
for _, file in ipairs(files) do
|
||||
collect_file_locations(file, locations)
|
||||
end
|
||||
local items = {}
|
||||
local seen = {}
|
||||
local function add_locations(name, locs)
|
||||
for _, loc in ipairs(locs or {}) do
|
||||
local key = string.format("%s:%d:%s", loc.filename or "", loc.lnum or 0, loc.text or name or "")
|
||||
if not seen[key] then
|
||||
seen[key] = true
|
||||
table.insert(items, loc)
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, name in ipairs(failures) do
|
||||
local direct = locations[name]
|
||||
if direct then
|
||||
add_locations(name, direct)
|
||||
elseif not name:find("/", 1, true) then
|
||||
for full, locs in pairs(locations) do
|
||||
if full:sub(-#name - 1) == "/" .. name then
|
||||
add_locations(full, locs)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return items
|
||||
end
|
||||
|
||||
return runner
|
||||
|
||||
@@ -186,7 +186,69 @@ local function collect_js_structs(lines)
|
||||
return describes, tests
|
||||
end
|
||||
|
||||
local function build_full_name(lines, idx, leaf_name)
|
||||
local build_full_name
|
||||
local shorten_js_name
|
||||
local normalize_js_name
|
||||
|
||||
local function add_location(target, name, file, line)
|
||||
if not name or name == "" or not file or file == "" or not line then
|
||||
return
|
||||
end
|
||||
if not target[name] then
|
||||
target[name] = {}
|
||||
end
|
||||
table.insert(target[name], {
|
||||
filename = file,
|
||||
lnum = line,
|
||||
col = 1,
|
||||
text = name,
|
||||
})
|
||||
end
|
||||
|
||||
local function collect_js_locations(lines, file, target)
|
||||
local describes, tests = collect_js_structs(lines)
|
||||
for _, t in ipairs(tests) do
|
||||
local full = build_full_name(lines, t.start + 1, t.name)
|
||||
add_location(target, full, file, t.start + 1)
|
||||
add_location(target, t.name, file, t.start + 1)
|
||||
local short = shorten_js_name and shorten_js_name(full) or nil
|
||||
if short and short ~= full then
|
||||
add_location(target, short, file, t.start + 1)
|
||||
end
|
||||
end
|
||||
for _, d in ipairs(describes) do
|
||||
local full = build_full_name(lines, d.start + 1, d.name)
|
||||
add_location(target, full, file, d.start + 1)
|
||||
add_location(target, d.name, file, d.start + 1)
|
||||
local short = shorten_js_name and shorten_js_name(full) or nil
|
||||
if short and short ~= full then
|
||||
add_location(target, short, file, d.start + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function collect_js_test_files(root, patterns)
|
||||
if not root or root == "" then
|
||||
root = vim.loop.cwd()
|
||||
end
|
||||
local files = {}
|
||||
local seen = {}
|
||||
for _, pat in ipairs(patterns or {}) do
|
||||
local glob = "**/*" .. pat .. "*"
|
||||
local hits = vim.fn.globpath(root, glob, false, true)
|
||||
if type(hits) == "table" then
|
||||
for _, file in ipairs(hits) do
|
||||
if not seen[file] then
|
||||
seen[file] = true
|
||||
table.insert(files, file)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return files
|
||||
end
|
||||
|
||||
build_full_name = function(lines, idx, leaf_name)
|
||||
local parts = { leaf_name }
|
||||
for i = idx - 1, 1, -1 do
|
||||
local line = lines[i]
|
||||
@@ -597,7 +659,17 @@ function M.new(opts)
|
||||
skip = string.char(0xE2, 0x97, 0x8B),
|
||||
}
|
||||
|
||||
local function shorten_js_name(name)
|
||||
normalize_js_name = function(name)
|
||||
if not name or name == "" then
|
||||
return nil
|
||||
end
|
||||
local out = name
|
||||
out = out:gsub("%s*[%>›»]%s*", " ")
|
||||
out = out:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "")
|
||||
return out
|
||||
end
|
||||
|
||||
shorten_js_name = function(name)
|
||||
if not name or name == "" then
|
||||
return nil
|
||||
end
|
||||
@@ -1108,6 +1180,61 @@ function M.new(opts)
|
||||
}
|
||||
end
|
||||
|
||||
function runner.collect_failed_locations(failures, command, scope_kind)
|
||||
if type(failures) ~= "table" or #failures == 0 then
|
||||
return {}
|
||||
end
|
||||
local files = {}
|
||||
if scope_kind == "all" then
|
||||
files = collect_js_test_files(command and command.cwd or nil, runner.patterns)
|
||||
else
|
||||
local file = command and command.file or nil
|
||||
if not file and command and type(command.cmd) == "table" then
|
||||
file = find_test_file_arg(command.cmd)
|
||||
end
|
||||
if file then
|
||||
files = { file }
|
||||
end
|
||||
end
|
||||
if #files == 0 then
|
||||
return {}
|
||||
end
|
||||
local locations = {}
|
||||
for _, file in ipairs(files) do
|
||||
local ok, lines = pcall(vim.fn.readfile, file)
|
||||
if ok and type(lines) == "table" then
|
||||
collect_js_locations(lines, file, locations)
|
||||
end
|
||||
end
|
||||
local items = {}
|
||||
local seen = {}
|
||||
for _, name in ipairs(failures) do
|
||||
local keys = { name }
|
||||
if normalize_js_name then
|
||||
local normalized = normalize_js_name(name)
|
||||
if normalized and normalized ~= name then
|
||||
table.insert(keys, normalized)
|
||||
end
|
||||
end
|
||||
if shorten_js_name then
|
||||
local short = shorten_js_name(name)
|
||||
if short and short ~= name then
|
||||
table.insert(keys, short)
|
||||
end
|
||||
end
|
||||
for _, key_name in ipairs(keys) do
|
||||
for _, loc in ipairs(locations[key_name] or {}) do
|
||||
local key = string.format("%s:%d", loc.filename or "", loc.lnum or 0)
|
||||
if not seen[key] then
|
||||
seen[key] = true
|
||||
table.insert(items, loc)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return items
|
||||
end
|
||||
|
||||
return runner
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user