performance for null-ls cache path detection

async call inside null-ls
bugfix fish/bash/zsh GoTestFile
pull/298/head
ray-x 1 year ago
parent 0912de62af
commit b7f7110d01

@ -240,20 +240,25 @@ function M.make(...)
if vim.fn.empty(vim.fn.glob(args[#args])) == 0 then -- pkg name in args if vim.fn.empty(vim.fn.glob(args[#args])) == 0 then -- pkg name in args
changed = true changed = true
if value:find("FAIL") == nil then if value:find("FAIL") == nil then
local p = extract_filepath(value) local p, fn, ln= extract_filepath(value, package_path)
if p then if p == true then -- path existed, but need to attach the pkg name
-- log(fn, ln, package_path, package_path:gsub('%.%.%.', ''))
-- remove ... in package path
value = package_path:gsub('%.%.%.', '') .. util.ltrim(value) value = package_path:gsub('%.%.%.', '') .. util.ltrim(value)
end end
end end
else else
local p = extract_filepath(value) local p, n = extract_filepath(value)
if p then
log(p, n, #lines)
if p == true then
failed = true failed = true
value = p .. util.ltrim(value) value = n .. util.ltrim(value)
changed = true changed = true
log(value)
end end
end end
trace(value) log(value, #lines)
table.insert(lines, value) table.insert(lines, value)
if itemn == 1 and failed and changed then if itemn == 1 and failed and changed then
itemn = #lines itemn = #lines

@ -508,9 +508,10 @@ M.get_test_cases = function()
end end
return tests[1] return tests[1]
end end
tests = vim.fn.join(tests, '\\|') local sep = '|'
utils.log(tests) local testsstr = vim.fn.join(tests, sep)
return tests utils.log(tests, testsstr)
return testsstr, tests
end end
M.test_file = function(...) M.test_file = function(...)
@ -572,10 +573,7 @@ M.test_file = function(...)
end end
table.insert(cmd_args, '-run') table.insert(cmd_args, '-run')
local sh = vim.o.shell tests = "'" .. tests .. "'"
if sh:find('fish') then
tests = "'" .. tests .. "'"
end
table.insert(cmd_args, tests) -- shell script | is a pipe table.insert(cmd_args, tests) -- shell script | is a pipe
table.insert(cmd_args, relpath) table.insert(cmd_args, relpath)

@ -32,18 +32,22 @@ local function handler()
end end
local verbose = true local verbose = true
local failure = {} local failure = {}
if #msgs > 160 then -- lua is still slow if #msgs > 100 then -- lua is slow
log('reduce')
verbose = false verbose = false
local fname = vfn.expand('%:t:r') local fname = vfn.expand('%:t:r')
local reduce = {} local reduce = {}
for _, m in pairs(msgs) do for _, m in pairs(msgs) do
local f = m:find(fname) local other = m:find('=== PAUSE')
local n = m:find('fail') or m:find('FAIL') or m:find('panic') if not other then
if f or n then local f = m:find(fname)
table.insert(reduce, m) local n = m:find('fail') or m:find('FAIL') or m:find('panic')
end if f or n then
if n then table.insert(reduce, m)
table.insert(failure, 'failed:' .. m) elseif n then
table.insert(failure, 'failed:' .. m)
end
end end
end end
msgs = reduce msgs = reduce
@ -52,97 +56,105 @@ local function handler()
-- the output is jsonencoded -- the output is jsonencoded
local output = '' local output = ''
local json_decode = vfn.json_decode
local qf = {} local qf = {}
local panic = {} -- store failed or panic info local panic = {} -- store failed or panic info
for i, m in pairs(msgs) do for idx, m in pairs(msgs) do
log(i, m) -- log(idx)
if vfn.empty(m) == 0 then if vfn.empty(m) == 0 then
local entry = vfn.json_decode(m) if m:find('--- PASS') or m:find('--- SKIP') or m:find('=== RUN') then
-- log(entry)
if entry.Action == 'run' then
package = entry.Package
output = '' output = ''
elseif entry.Action == 'output' then else
package = entry.Package local entry = json_decode(m)
if vfn.empty(entry.Output) == 0 then entry = entry or {}
local ma = vfn.matchlist(entry.Output, [[\v\s*(\w+.+\.go):(\d+):]]) -- log(entry)
if ma[2] then if entry.Action == 'run' then
log(ma) package = entry.Package
filename = package .. utils.sep() .. ma[2] output = ''
if vfn.filereadable(filename) == 0 then elseif entry.Action == 'output' then
filename = vfn.fnamemodify(vfn.expand('%:h'), ':~:.') .. utils.sep() .. ma[2] package = entry.Package
end if vfn.empty(entry.Output) == 1 or false then
line = ma[3] output = ''
end
if not verbose then
output = entry.Output
else else
output = output .. (entry.Output or '') log(idx, entry)
entry.Output = utils.trim(entry.Output)
entry.Output = entry.Output:gsub('\t', ' ')
local found = false
local fname
local lnum
found, fname, lnum = extract_filepath(entry.Output, package)
if fname then
filename = fname
line = lnum
end
-- log(found, filename, lnum)
if found == true then
local pkg_path = require('go.gotest').get_test_path() .. utils.sep()
output = pkg_path .. utils.ltrim(entry.Output)
else -- not found or format is correct
if #output > 1 then
output = output .. (entry.Output or '')
else
output = output .. (entry.Output or '')
end
end
if entry.Output:find('FAIL') or entry.Output:find('panic') then
table.insert(panic, entry.Output)
end
log(idx, filename, output or 'nil')
end end
if entry.Output:find('FAIL') or entry.Output:find('panic') then elseif entry.Action == 'pass' or entry.Action == 'skip' then
table.insert(panic, entry.Output) -- log(entry)
-- reset
output = ''
elseif entry.Action == 'fail' and vfn.empty(output) == 0 then
log(idx, entry, filename, output)
if filename and filename:find(vfn.expand('%:t:r')) then -- can be output from other files
table.insert(diags, {
file = filename,
row = tonumber(line),
col = 1,
message = output,
severity = severities.error,
source = 'go test',
})
end end
log(output or 'nil') local qflines = vim.split(output, '\n')
end for i, value in ipairs(qflines) do
elseif entry.Action == 'pass' or entry.Action == 'skip' then if vim.fn.empty(value) == 0 then
-- log(entry) -- local p, _ = extract_filepath(value)
-- reset -- if p then
output = '' -- value = pkg_path .. utils.ltrim(value)
elseif entry.Action == 'fail' and vfn.empty(output) == 0 then -- log(value)
-- log(entry) -- end
if filename and filename:find(vfn.expand('%:t:r')) then -- can be output from other files qflines[i] = value
table.insert(diags, {
file = filename,
row = tonumber(line),
col = 1,
message = output,
severity = severities.error,
source = 'go test',
})
end
local qflines = vim.split(output, '\n')
for i, value in ipairs(qflines) do
if vim.fn.empty(value) == 0 then
local p = extract_filepath(value)
if p then
value = p .. utils.ltrim(value)
end end
qflines[i] = value end
-- log(qflines)
vim.list_extend(qf, qflines)
output = ''
elseif entry.Action == 'fail' then -- empty output
-- log(idx, entry)
-- reset
local plines = ''
if #panic > 0 then
plines = table.concat(panic, '')
end end
end end
log(qflines)
vim.list_extend(qf, qflines)
output = ''
elseif entry.Action == 'fail' then -- empty output
-- log(entry)
-- reset
local plines = ''
if #panic > 0 then
plines = table.concat(panic, '')
end
vim.notify(
'go test failed package: '
.. entry.Package
.. 'test: '
.. (entry.Test or '')
.. '\n please check quickfix!\n'
.. plines,
vim.log.levels.WARN
)
end end
end end
if #qf > 0 then
local efm = require('go.gotest').efm()
vfn.setqflist({}, ' ', { title = 'gotest', lines = qf, efm = efm })
end
end end
log(diags)
if not verbose and #failure > 0 then if #qf > 0 then
vim.notify( local efm = require('go.gotest').efm()
'go test failed package: ' .. package .. '\n please check quickfix!', vfn.setqflist({}, ' ', { title = 'gotest', lines = qf, efm = efm })
vim.log.levels.WARN log(qf, efm)
)
end end
log(diags)
vim.notify('go test failed: ' .. '\n please check quickfix!\n', vim.log.levels.WARN)
-- local ok, d = pcall(vfn.json_decode, msg) -- local ok, d = pcall(vfn.json_decode, msg)
return done(diags) return done(diags)
end end
@ -250,6 +262,7 @@ return {
vim.notify('failed to load null-ls', vim.log.levels.WARN) vim.notify('failed to load null-ls', vim.log.levels.WARN)
return return
end end
local pkg_path = ''
return h.make_builtin({ return h.make_builtin({
name = 'gotest', name = 'gotest',
@ -262,20 +275,19 @@ return {
local gt = require('go.gotest') local gt = require('go.gotest')
local a = { 'test', '-json' } local a = { 'test', '-json' }
local tests = gt.get_test_cases() local tests = gt.get_test_cases()
-- log(tests) log(tests)
local pkg = require('go.gotest').get_test_path() local pkg = require('go.gotest').get_test_path()
if not tests or not tests[1] then pkg_path = pkg
if vfn.empty(tests) == 1 then
table.insert(a, pkg) table.insert(a, pkg)
else else
tests = tests[1]
local sh = vim.o.shell local sh = vim.o.shell
table.insert(a, '-run') table.insert(a, '-run')
table.insert(a, tests) table.insert(a, tests)
table.insert(a, pkg) table.insert(a, pkg)
end end
-- log(a) log(a)
return a return a
end, end,
method = methods.internal.DIAGNOSTICS_ON_SAVE, method = methods.internal.DIAGNOSTICS_ON_SAVE,
@ -293,7 +305,7 @@ return {
-- end -- end
return true return true
end, end,
on_output = handler(), on_output = handler(pkg_path),
}, },
factory = h.generator_factory, factory = h.generator_factory,
}) })

@ -177,7 +177,8 @@ util.check_same = function(tbl1, tbl2)
end end
util.map = function(modes, key, result, options) util.map = function(modes, key, result, options)
options = util.merge({ noremap = true, silent = false, expr = false, nowait = false }, options or {}) options =
util.merge({ noremap = true, silent = false, expr = false, nowait = false }, options or {})
local buffer = options.buffer local buffer = options.buffer
options.buffer = nil options.buffer = nil
@ -245,6 +246,8 @@ util.log = function(...)
local info = debug.getinfo(2, 'Sl') local info = debug.getinfo(2, 'Sl')
str = str .. info.short_src .. ':' .. info.currentline str = str .. info.short_src .. ':' .. info.currentline
local _, ms = vim.loop.gettimeofday()
str = string.format('[%s %d] %s', os.date(), ms, str)
for i, v in ipairs(arg) do for i, v in ipairs(arg) do
if type(v) == 'table' then if type(v) == 'table' then
str = str .. ' |' .. tostring(i) .. ': ' .. vim.inspect(v) .. '\n' str = str .. ' |' .. tostring(i) .. ': ' .. vim.inspect(v) .. '\n'
@ -370,16 +373,16 @@ function util.load_plugin(name, modulename)
if has_packer or has_lazy then if has_packer or has_lazy then
-- packer installed -- packer installed
if has_packer then if has_packer then
local loader = require('packer').loader local loader = require('packer').loader
if not pkg[name] or not pkg[name].loaded then if not pkg[name] or not pkg[name].loaded then
util.log('packer loader ' .. name) util.log('packer loader ' .. name)
vim.cmd('packadd ' .. name) -- load with default vim.cmd('packadd ' .. name) -- load with default
if pkg[name] ~= nil then if pkg[name] ~= nil then
loader(name) loader(name)
end
end end
end
else else
require('lazy').load({plugins =name}) require('lazy').load({ plugins = name })
end end
else else
util.log('packadd ' .. name) util.log('packadd ' .. name)
@ -425,7 +428,8 @@ end
-- end -- end
function util.relative_to_cwd(name) function util.relative_to_cwd(name)
local rel = fn.isdirectory(name) == 0 and fn.fnamemodify(name, ':h:.') or fn.fnamemodify(name, ':.') local rel = fn.isdirectory(name) == 0 and fn.fnamemodify(name, ':h:.')
or fn.fnamemodify(name, ':.')
if rel == '.' then if rel == '.' then
return '.' return '.'
else else
@ -790,63 +794,79 @@ end
local namepath = {} local namepath = {}
util.extract_filepath = function(msg) util.extract_filepath = function(msg, pkg_path)
msg = msg or '' msg = msg or ''
-- util.log(msg) -- util.log(msg)
--[[ or [[ findAllSubStr_test.go:234: Error inserting caseResult1: operation error DynamoDB: PutItem, exceeded maximum number of attempts]] --[[ or [[ findAllSubStr_test.go:234: Error inserting caseResult1: operation error DynamoDB: PutItem, exceeded maximum number of attempts]]
-- or 'path/path2/filename.go:50:11: Error invaild -- or 'path/path2/filename.go:50:11: Error invaild
-- or /home/ray/go/src/github/sample/app/driver.go:342 +0x19e5 -- or /home/ray/go/src/github/sample/app/driver.go:342 +0x19e5
local pos, _ = msg:find([[[%w_%-%./]+%.go:%d+:]]) local ma = fn.matchlist(msg, [[\v\s*(\w+.+\.go):(\d+):]])
if not pos then ma = ma or fn.matchlist(msg, [[\v\s*(\w+.+\.go):(\d+)]])
pos, _ = msg:find([[[%w_%-%./]+%.go:%d+ ]]) -- test failure with panic local filename, lnum
end if ma[2] then
local pos2 util.log(ma)
if not pos then filename = ma[2]
lnum = ma[3]
else
return return
end end
pos2 = msg:find(':') util.log('fname : ' .. (filename or 'nil') .. ':' .. (lnum or '-1'))
local s = msg:sub(1, pos2 - 1)
util.log('fname : ', s) if namepath[filename] then
if vim.fn.filereadable(s) == 1 then -- if name is same, no need to update path
util.log('filename', s) return (namepath[filename] ~= filename), namepath[filename], lnum
end
if vim.fn.filereadable(filename) == 1 then
util.log('filename', filename)
-- no need to extract path, already quickfix format -- no need to extract path, already quickfix format
return namepath[filename] = filename
return false, filename, lnum
end end
if not pos2 then
util.log('incorrect format', msg) if pkg_path then
return local pn = pkg_path:gsub('%.%.%.', '')
local fname = pn .. util.sep() .. filename
if vim.fn.filereadable(fname) == 1 then
namepath[filename] = fname
util.log('fname with pkg_name', fname)
return true, fname, lnum
end
end end
pos2 = msg:find(':')
local fname = msg:sub(pos, pos2 - 1) local fname = fn.fnamemodify(fn.expand('%:h'), ':~:.') .. util.sep() .. ma[2]
util.log(fname, namepath[fname]) util.log(fname, namepath[fname])
if namepath[fname] ~= nil then
return namepath[fname]
end
if vim.fn.filereadable(fname) == 1 then if vim.fn.filereadable(fname) == 1 then
return namepath[filename] = fname
return true, fname, lnum
end
if namepath[filename] ~= nil then
util.log(namepath[filename])
return namepath[filename], lnum
end end
if vim.fn.executable('find') == 0 then if vim.fn.executable('find') == 0 then
return return false, fname, lnum
end end
-- note: slow operations -- note: slow operations
local cmd = 'find ./ -type f -name ' .. fname local cmd = 'find ./ -type f -name ' .. filename
local path = vim.fn.systemlist(cmd) local path = vim.fn.systemlist(cmd)
if vim.v.shell_error ~= 0 then if vim.v.shell_error ~= 0 then
util.warn('find failed ' .. cmd .. vim.inspect(path)) util.warn('find failed ' .. cmd .. vim.inspect(path))
return
end end
for _, value in pairs(path) do for _, value in pairs(path) do
local st, _ = value:find(fname) local st, _ = value:find(filename)
if st then if st then
-- find cmd returns `./path/path2/filename.go`, the leading './' is not needed for quickfix -- find cmd returns `./path/path2/filename.go`, the leading './' is not needed for quickfix
local p = value:sub(1, st - 1) local p = value:sub(1, st - 1)
util.log(value, st, p) util.log(value, st, p)
namepath[st] = p namepath[filename] = p
return p return true, p, lnum
end end
end end
-- nothing... we will not check this file again
namepath[filename] = filename
end end
return util return util

Loading…
Cancel
Save