diff --git a/lua/go/asyncmake.lua b/lua/go/asyncmake.lua index 96f9dce..665920c 100644 --- a/lua/go/asyncmake.lua +++ b/lua/go/asyncmake.lua @@ -240,20 +240,25 @@ function M.make(...) if vim.fn.empty(vim.fn.glob(args[#args])) == 0 then -- pkg name in args changed = true if value:find("FAIL") == nil then - local p = extract_filepath(value) - if p then + local p, fn, ln= extract_filepath(value, package_path) + 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) end end else - local p = extract_filepath(value) - if p then + local p, n = extract_filepath(value) + + log(p, n, #lines) + if p == true then failed = true - value = p .. util.ltrim(value) + value = n .. util.ltrim(value) changed = true + log(value) end end - trace(value) + log(value, #lines) table.insert(lines, value) if itemn == 1 and failed and changed then itemn = #lines diff --git a/lua/go/gotest.lua b/lua/go/gotest.lua index 346d59a..298d9e5 100644 --- a/lua/go/gotest.lua +++ b/lua/go/gotest.lua @@ -508,9 +508,10 @@ M.get_test_cases = function() end return tests[1] end - tests = vim.fn.join(tests, '\\|') - utils.log(tests) - return tests + local sep = '|' + local testsstr = vim.fn.join(tests, sep) + utils.log(tests, testsstr) + return testsstr, tests end M.test_file = function(...) @@ -572,10 +573,7 @@ M.test_file = function(...) end table.insert(cmd_args, '-run') - local sh = vim.o.shell - if sh:find('fish') then - tests = "'" .. tests .. "'" - end + tests = "'" .. tests .. "'" table.insert(cmd_args, tests) -- shell script | is a pipe table.insert(cmd_args, relpath) diff --git a/lua/go/null_ls.lua b/lua/go/null_ls.lua index f89975d..e873d52 100644 --- a/lua/go/null_ls.lua +++ b/lua/go/null_ls.lua @@ -32,18 +32,22 @@ local function handler() end local verbose = true local failure = {} - if #msgs > 160 then -- lua is still slow + if #msgs > 100 then -- lua is slow + log('reduce') verbose = false local fname = vfn.expand('%:t:r') local reduce = {} + for _, m in pairs(msgs) do - local f = m:find(fname) - local n = m:find('fail') or m:find('FAIL') or m:find('panic') - if f or n then - table.insert(reduce, m) - end - if n then - table.insert(failure, 'failed:' .. m) + local other = m:find('=== PAUSE') + if not other then + local f = m:find(fname) + local n = m:find('fail') or m:find('FAIL') or m:find('panic') + if f or n then + table.insert(reduce, m) + elseif n then + table.insert(failure, 'failed:' .. m) + end end end msgs = reduce @@ -52,97 +56,105 @@ local function handler() -- the output is jsonencoded local output = '' + local json_decode = vfn.json_decode + local qf = {} local panic = {} -- store failed or panic info - for i, m in pairs(msgs) do - log(i, m) + for idx, m in pairs(msgs) do + -- log(idx) if vfn.empty(m) == 0 then - local entry = vfn.json_decode(m) - -- log(entry) - if entry.Action == 'run' then - package = entry.Package + if m:find('--- PASS') or m:find('--- SKIP') or m:find('=== RUN') then output = '' - elseif entry.Action == 'output' then - package = entry.Package - if vfn.empty(entry.Output) == 0 then - local ma = vfn.matchlist(entry.Output, [[\v\s*(\w+.+\.go):(\d+):]]) - if ma[2] then - log(ma) - filename = package .. utils.sep() .. ma[2] - if vfn.filereadable(filename) == 0 then - filename = vfn.fnamemodify(vfn.expand('%:h'), ':~:.') .. utils.sep() .. ma[2] - end - line = ma[3] - end - if not verbose then - output = entry.Output + else + local entry = json_decode(m) + entry = entry or {} + -- log(entry) + if entry.Action == 'run' then + package = entry.Package + output = '' + elseif entry.Action == 'output' then + package = entry.Package + if vfn.empty(entry.Output) == 1 or false then + output = '' 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 - if entry.Output:find('FAIL') or entry.Output:find('panic') then - table.insert(panic, entry.Output) + elseif entry.Action == 'pass' or entry.Action == 'skip' then + -- 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 - log(output or 'nil') - end - elseif entry.Action == 'pass' or entry.Action == 'skip' then - -- log(entry) - -- reset - output = '' - elseif entry.Action == 'fail' and vfn.empty(output) == 0 then - -- log(entry) - 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 - 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) + 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 = pkg_path .. utils.ltrim(value) + -- log(value) + -- end + qflines[i] = value 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 - 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 - if #qf > 0 then - local efm = require('go.gotest').efm() - vfn.setqflist({}, ' ', { title = 'gotest', lines = qf, efm = efm }) - end end - log(diags) - if not verbose and #failure > 0 then - vim.notify( - 'go test failed package: ' .. package .. '\n please check quickfix!', - vim.log.levels.WARN - ) + + if #qf > 0 then + local efm = require('go.gotest').efm() + vfn.setqflist({}, ' ', { title = 'gotest', lines = qf, efm = efm }) + log(qf, efm) 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) return done(diags) end @@ -250,6 +262,7 @@ return { vim.notify('failed to load null-ls', vim.log.levels.WARN) return end + local pkg_path = '' return h.make_builtin({ name = 'gotest', @@ -262,20 +275,19 @@ return { local gt = require('go.gotest') local a = { 'test', '-json' } local tests = gt.get_test_cases() - -- log(tests) + log(tests) 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) else - tests = tests[1] - local sh = vim.o.shell table.insert(a, '-run') table.insert(a, tests) table.insert(a, pkg) end - -- log(a) + log(a) return a end, method = methods.internal.DIAGNOSTICS_ON_SAVE, @@ -293,7 +305,7 @@ return { -- end return true end, - on_output = handler(), + on_output = handler(pkg_path), }, factory = h.generator_factory, }) diff --git a/lua/go/utils.lua b/lua/go/utils.lua index dba0ca1..a0c93b3 100644 --- a/lua/go/utils.lua +++ b/lua/go/utils.lua @@ -177,7 +177,8 @@ util.check_same = function(tbl1, tbl2) end 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 options.buffer = nil @@ -245,6 +246,8 @@ util.log = function(...) local info = debug.getinfo(2, 'Sl') 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 if type(v) == 'table' then 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 -- packer installed if has_packer then - local loader = require('packer').loader - if not pkg[name] or not pkg[name].loaded then - util.log('packer loader ' .. name) - vim.cmd('packadd ' .. name) -- load with default - if pkg[name] ~= nil then - loader(name) + local loader = require('packer').loader + if not pkg[name] or not pkg[name].loaded then + util.log('packer loader ' .. name) + vim.cmd('packadd ' .. name) -- load with default + if pkg[name] ~= nil then + loader(name) + end end - end else - require('lazy').load({plugins =name}) + require('lazy').load({ plugins = name }) end else util.log('packadd ' .. name) @@ -425,7 +428,8 @@ end -- end 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 return '.' else @@ -790,63 +794,79 @@ end local namepath = {} -util.extract_filepath = function(msg) +util.extract_filepath = function(msg, pkg_path) msg = msg or '' -- util.log(msg) --[[ 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 /home/ray/go/src/github/sample/app/driver.go:342 +0x19e5 - local pos, _ = msg:find([[[%w_%-%./]+%.go:%d+:]]) - if not pos then - pos, _ = msg:find([[[%w_%-%./]+%.go:%d+ ]]) -- test failure with panic - end - local pos2 - if not pos then + local ma = fn.matchlist(msg, [[\v\s*(\w+.+\.go):(\d+):]]) + ma = ma or fn.matchlist(msg, [[\v\s*(\w+.+\.go):(\d+)]]) + local filename, lnum + if ma[2] then + util.log(ma) + filename = ma[2] + lnum = ma[3] + else return end - pos2 = msg:find(':') - local s = msg:sub(1, pos2 - 1) - util.log('fname : ', s) - if vim.fn.filereadable(s) == 1 then - util.log('filename', s) + util.log('fname : ' .. (filename or 'nil') .. ':' .. (lnum or '-1')) + + if namepath[filename] then + -- if name is same, no need to update path + 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 - return + namepath[filename] = filename + return false, filename, lnum end - if not pos2 then - util.log('incorrect format', msg) - return + + if pkg_path then + 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 - 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]) - if namepath[fname] ~= nil then - return namepath[fname] - end 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 if vim.fn.executable('find') == 0 then - return + return false, fname, lnum end -- note: slow operations - local cmd = 'find ./ -type f -name ' .. fname + local cmd = 'find ./ -type f -name ' .. filename local path = vim.fn.systemlist(cmd) if vim.v.shell_error ~= 0 then util.warn('find failed ' .. cmd .. vim.inspect(path)) - return end for _, value in pairs(path) do - local st, _ = value:find(fname) + local st, _ = value:find(filename) if st then -- find cmd returns `./path/path2/filename.go`, the leading './' is not needed for quickfix local p = value:sub(1, st - 1) util.log(value, st, p) - namepath[st] = p - return p + namepath[filename] = p + return true, p, lnum end end + -- nothing... we will not check this file again + namepath[filename] = filename end return util