Skip to content

Commit

Permalink
test.vim: refactor to use its own parse function
Browse files Browse the repository at this point in the history
  • Loading branch information
fatih committed Jun 2, 2017
1 parent 76044c0 commit d2ff39c
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 37 deletions.
2 changes: 1 addition & 1 deletion autoload/go/list.vim
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function! go#list#PopulateWin(winnr, items) abort
call setloclist(a:winnr, a:items, 'r')
endfunction

" Parse parses the given items based on the specified errorformat nad
" Parse parses the given items based on the specified errorformat and
" populates the location list.
function! go#list#ParseFormat(listtype, errformat, items, title) abort
let l:listtype = go#list#Type(a:listtype)
Expand Down
4 changes: 2 additions & 2 deletions autoload/go/statusline.vim
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ function! go#statusline#Show() abort

" only update highlight if status has changed.
if status_text != s:last_status
if status.state =~ "success" || status.state =~ "finished"
if status.state =~ "success" || status.state =~ "finished" || status.state =~ "pass"
hi goStatusLineColor cterm=bold ctermbg=76 ctermfg=22
elseif status.state =~ "started" || status.state =~ "analysing"
elseif status.state =~ "started" || status.state =~ "analysing" || status.state =~ "compiling"
hi goStatusLineColor cterm=bold ctermbg=208 ctermfg=88
elseif status.state =~ "failed"
hi goStatusLineColor cterm=bold ctermbg=196 ctermfg=52
Expand Down
157 changes: 123 additions & 34 deletions autoload/go/test.vim
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,13 @@ function! go#test#Test(bang, compile, ...) abort
let job_args = {
\ 'cmd': ['go'] + args,
\ 'bang': a:bang,
\ 'winnr': winnr(),
\ 'dir': getcwd(),
\ 'jobdir': fnameescape(expand("%:p:h")),
\ }

if a:compile
let job_args['custom_cb'] = function('s:test_compile', [compile_file])
let job_args['compile_cb'] = function('s:test_compile', [compile_file])
endif

call s:test_job(job_args)
Expand Down Expand Up @@ -134,49 +137,46 @@ function! go#test#Func(bang, ...) abort
call extend(args, a:000)
endif

call call('go#cmd#Test', args)
endfunction

" test_compile is called when a GoTestCompile call is finished
function! s:test_compile(test_file, job, exit_status, data) abort
call delete(a:test_file)
endfunction

" -----------------------
" | Neovim job handlers |
" -----------------------
let s:test_compile_handlers = {}

function! s:test_compile_handler(job, exit_status, data) abort
if !has_key(s:test_compile_handlers, a:job.id)
return
endif
let l:compile_file = s:test_compile_handlers[a:job.id]
call delete(l:compile_file)
unlet s:test_compile_handlers[a:job.id]
call call('go#test#Test', args)
endfunction

function s:test_job(args) abort
let status_dir = expand('%:p:h')
let started_at = reltime()

call go#statusline#Update(status_dir, {
\ 'desc': "current status",
\ 'type': a:args.cmd[1],
let status = {
\ 'desc': 'current status',
\ 'type': "test",
\ 'state': "started",
\})
\ }

if has_key(a:args, 'compile_cb')
let status.state = "compiling"
endif

call go#statusline#Update(status_dir, status)

" autowrite is not enabled for jobs
call go#cmd#autowrite()

function! s:error_info_cb(job, exit_status, data) closure abort
let messages = []
function! s:callback(chan, msg) closure
call add(messages, a:msg)
endfunction

function! s:exit_cb(job, exitval) closure
let status = {
\ 'desc': 'last status',
\ 'type': a:args.cmd[1],
\ 'state': "success",
\ 'type': "test",
\ 'state': "pass",
\ }

if a:exit_status
if has_key(a:args, 'compile_cb')
call a:args.compile_cb(a:job, a:exitval, messages)
let status.state = "success"
endif

if a:exitval
let status.state = "failed"
endif

Expand All @@ -186,14 +186,20 @@ function s:test_job(args) abort
let status.state .= printf(" (%ss)", elapsed_time)

call go#statusline#Update(status_dir, status)
endfunction

let a:args.error_info_cb = funcref('s:error_info_cb')
let callbacks = go#job#Spawn(a:args)
let l:listtype = go#list#Type("quickfix")
if a:exitval == 0
call go#list#Clean(l:listtype)
call go#list#Window(l:listtype)
return
endif

call s:show_errors(a:args, a:exitval, messages)
endfunction

let start_options = {
\ 'callback': callbacks.callback,
\ 'exit_cb': callbacks.exit_cb,
\ 'callback': funcref("s:callback"),
\ 'exit_cb': funcref("s:exit_cb"),
\ }

" modify GOPATH if needed
Expand All @@ -213,5 +219,88 @@ function s:test_job(args) abort
let $GOPATH = old_gopath
endfunction

" show_errors parses the given list of lines of a 'go test' output and returns
" a quickfix compatible list of errors. It's intended to be used only for go
" test output.
function! s:show_errors(args, exit_val, messages) abort
let l:listtype = go#list#Type("quickfix")

let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
try
execute cd a:args.jobdir
let errors = s:parse_errors(a:messages)
let errors = go#tool#FilterValids(errors)
finally
execute cd . fnameescape(a:args.dir)
endtry

if !len(errors)
" failed to parse errors, output the original content
call go#util#EchoError(join(a:messages, " "))
call go#util#EchoError(a:args.dir)
return
endif

if a:args.winnr == winnr()
call go#list#Populate(l:listtype, errors, join(a:args.cmd))
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:args.bang
call go#list#JumpToFirst(l:listtype)
endif
endif
endfunction

function! s:parse_errors(lines) abort
let errors = []

" NOTE(arslan): once we get JSON output everything will be easier :)
" https://github.com/golang/go/issues/2981
for line in a:lines
let fatalerrors = matchlist(line, '^\(fatal error:.*\)$')
let tokens = matchlist(line, '^\s*\(.\{-}\):\(\d\+\):\s*\(.*\)')

if !empty(fatalerrors)
call add(errors, {"text": fatalerrors[1]})
elseif !empty(tokens)
" strip endlines of form ^M
let out = substitute(tokens[3], '\r$', '', '')

call add(errors, {
\ "filename" : fnamemodify(tokens[1], ':p'),
\ "lnum" : tokens[2],
\ "text" : out,
\ })
elseif !empty(errors)
" Preserve indented lines.
" This comes up especially with multi-line test output.
if match(line, '^\s') >= 0
call add(errors, {"text": line})
endif
endif
endfor

return errors
endfunction

" test_compile is called when a GoTestCompile call is finished
function! s:test_compile(test_file, job, exit_status, data) abort
call delete(a:test_file)
endfunction

" -----------------------
" | Neovim job handlers |
" -----------------------
let s:test_compile_handlers = {}

function! s:test_compile_handler(job, exit_status, data) abort
if !has_key(s:test_compile_handlers, a:job.id)
return
endif
let l:compile_file = s:test_compile_handlers[a:job.id]
call delete(l:compile_file)
unlet s:test_compile_handlers[a:job.id]
endfunction


" vim: sw=2 ts=2 et
"

0 comments on commit d2ff39c

Please sign in to comment.