mirror of
1
0
Fork 0
ultimate-vim/sources_non_forked/vim-go/autoload/go/lint.vim

312 lines
8.5 KiB
VimL
Raw Normal View History

2015-12-08 08:20:04 -05:00
if !exists("g:go_metalinter_command")
2016-06-26 07:12:36 -04:00
let g:go_metalinter_command = ""
2015-12-08 08:20:04 -05:00
endif
if !exists("g:go_metalinter_autosave_enabled")
2016-06-26 07:12:36 -04:00
let g:go_metalinter_autosave_enabled = ['vet', 'golint']
2015-12-08 08:20:04 -05:00
endif
if !exists("g:go_metalinter_enabled")
2016-06-26 07:12:36 -04:00
let g:go_metalinter_enabled = ['vet', 'golint', 'errcheck']
2015-12-08 08:20:04 -05:00
endif
2017-05-02 08:42:08 -04:00
if !exists("g:go_metalinter_excludes")
let g:go_metalinter_excludes = []
endif
2014-10-31 17:30:24 -04:00
if !exists("g:go_golint_bin")
2016-06-26 07:12:36 -04:00
let g:go_golint_bin = "golint"
2014-10-31 17:30:24 -04:00
endif
2015-12-08 08:20:04 -05:00
if !exists("g:go_errcheck_bin")
2016-06-26 07:12:36 -04:00
let g:go_errcheck_bin = "errcheck"
2015-12-08 08:20:04 -05:00
endif
function! go#lint#Gometa(autosave, ...) abort
2016-06-26 07:12:36 -04:00
if a:0 == 0
let goargs = shellescape(expand('%:p:h'))
else
let goargs = go#util#Shelljoin(a:000)
endif
2016-12-27 09:46:49 -05:00
let bin_path = go#path#CheckBinPath("gometalinter")
if empty(bin_path)
return
endif
2015-12-08 08:20:04 -05:00
2016-12-27 09:46:49 -05:00
let cmd = [bin_path]
let cmd += ["--disable-all"]
2015-12-08 08:20:04 -05:00
2016-12-27 09:46:49 -05:00
if a:autosave || empty(g:go_metalinter_command)
2016-06-26 07:12:36 -04:00
" linters
let linters = a:autosave ? g:go_metalinter_autosave_enabled : g:go_metalinter_enabled
for linter in linters
2016-12-27 09:46:49 -05:00
let cmd += ["--enable=".linter]
2016-06-26 07:12:36 -04:00
endfor
2017-05-02 08:42:08 -04:00
for exclude in g:go_metalinter_excludes
let cmd += ["--exclude=".exclude]
endfor
2016-06-26 07:12:36 -04:00
" path
2016-12-27 09:46:49 -05:00
let cmd += [expand('%:p:h')]
2016-06-26 07:12:36 -04:00
else
" the user wants something else, let us use it.
2017-02-11 08:01:38 -05:00
let cmd += split(g:go_metalinter_command, " ")
2016-12-27 09:46:49 -05:00
endif
2017-02-11 08:01:38 -05:00
" gometalinter has a default deadline of 5 seconds.
"
" For async mode (s:lint_job), we want to override the default deadline only
" if we have a deadline configured.
"
" For sync mode (go#tool#ExecuteInDir), always explicitly pass the 5 seconds
" deadline if there is no other deadline configured. If a deadline is
" configured, then use it.
" Call gometalinter asynchronously.
2016-12-27 09:46:49 -05:00
if go#util#has_job() && has('lambda')
2017-02-11 08:01:38 -05:00
let deadline = get(g:, 'go_metalinter_deadline', 0)
if deadline != 0
let cmd += ["--deadline=" . deadline]
endif
2016-12-27 09:46:49 -05:00
call s:lint_job({'cmd': cmd})
return
endif
2017-02-11 08:01:38 -05:00
" We're calling gometalinter synchronously.
let cmd += ["--deadline=" . get(g:, 'go_metalinter_deadline', "5s")]
2016-12-27 09:46:49 -05:00
if a:autosave
" include only messages for the active buffer
let cmd += ["--include='^" . expand('%:p') . ".*$'"]
2016-06-26 07:12:36 -04:00
endif
2016-12-27 09:46:49 -05:00
let meta_command = join(cmd, " ")
2016-06-26 07:12:36 -04:00
let out = go#tool#ExecuteInDir(meta_command)
let l:listtype = "quickfix"
if go#util#ShellError() == 0
redraw | echo
call go#list#Clean(l:listtype)
call go#list#Window(l:listtype)
echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None
else
" GoMetaLinter can output one of the two, so we look for both:
" <file>:<line>:[<column>]: <message> (<linter>)
" <file>:<line>:: <message> (<linter>)
" This can be defined by the following errorformat:
let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m"
" Parse and populate our location list
2016-12-27 09:46:49 -05:00
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'GoMetaLinter')
2016-06-26 07:12:36 -04:00
let errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(errors))
if !a:autosave
call go#list#JumpToFirst(l:listtype)
2015-12-08 08:20:04 -05:00
endif
2016-06-26 07:12:36 -04:00
endif
2015-12-08 08:20:04 -05:00
endfunction
" Golint calls 'golint' on the current directory. Any warnings are populated in
" the location list
function! go#lint#Golint(...) abort
2017-03-07 12:04:28 -05:00
let bin_path = go#path#CheckBinPath(g:go_golint_bin)
if empty(bin_path)
return
2016-06-26 07:12:36 -04:00
endif
if a:0 == 0
let goargs = shellescape(expand('%'))
else
let goargs = go#util#Shelljoin(a:000)
endif
let out = go#util#System(bin_path . " " . goargs)
if empty(out)
echon "vim-go: " | echohl Function | echon "[lint] PASS" | echohl None
return
endif
let l:listtype = "quickfix"
call go#list#Parse(l:listtype, out)
let errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(errors))
call go#list#JumpToFirst(l:listtype)
2015-12-08 08:20:04 -05:00
endfunction
" Vet calls 'go vet' on the current directory. Any warnings are populated in
" the location list
2016-12-27 09:46:49 -05:00
function! go#lint#Vet(bang, ...) abort
2016-06-26 07:12:36 -04:00
call go#cmd#autowrite()
echon "vim-go: " | echohl Identifier | echon "calling vet..." | echohl None
if a:0 == 0
let out = go#tool#ExecuteInDir('go vet')
else
let out = go#tool#ExecuteInDir('go tool vet ' . go#util#Shelljoin(a:000))
endif
let l:listtype = "quickfix"
if go#util#ShellError() != 0
let errors = go#tool#ParseErrors(split(out, '\n'))
2016-12-27 09:46:49 -05:00
call go#list#Populate(l:listtype, errors, 'Vet')
2016-06-26 07:12:36 -04:00
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:bang
call go#list#JumpToFirst(l:listtype)
2015-12-08 08:20:04 -05:00
endif
2016-06-26 07:12:36 -04:00
echon "vim-go: " | echohl ErrorMsg | echon "[vet] FAIL" | echohl None
else
call go#list#Clean(l:listtype)
call go#list#Window(l:listtype)
redraw | echon "vim-go: " | echohl Function | echon "[vet] PASS" | echohl None
endif
2014-10-31 17:30:24 -04:00
endfunction
2015-12-08 08:20:04 -05:00
" ErrCheck calls 'errcheck' for the given packages. Any warnings are populated in
" the location list
function! go#lint#Errcheck(...) abort
2016-06-26 07:12:36 -04:00
if a:0 == 0
let goargs = go#package#ImportPath(expand('%:p:h'))
if goargs == -1
echohl Error | echomsg "vim-go: package is not inside GOPATH src" | echohl None
return
2015-12-08 08:20:04 -05:00
endif
2016-06-26 07:12:36 -04:00
else
let goargs = go#util#Shelljoin(a:000)
endif
2015-12-08 08:20:04 -05:00
2016-06-26 07:12:36 -04:00
let bin_path = go#path#CheckBinPath(g:go_errcheck_bin)
if empty(bin_path)
return
endif
echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None
redraw
let command = bin_path . ' -abspath ' . goargs
let out = go#tool#ExecuteInDir(command)
let l:listtype = "quickfix"
if go#util#ShellError() != 0
let errformat = "%f:%l:%c:\ %m, %f:%l:%c\ %#%m"
" Parse and populate our location list
2016-12-27 09:46:49 -05:00
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'Errcheck')
2016-06-26 07:12:36 -04:00
let errors = go#list#Get(l:listtype)
if empty(errors)
echohl Error | echomsg "GoErrCheck returned error" | echohl None
echo out
return
2015-12-08 08:20:04 -05:00
endif
2016-06-26 07:12:36 -04:00
if !empty(errors)
2016-12-27 09:46:49 -05:00
call go#list#Populate(l:listtype, errors, 'Errcheck')
2016-06-26 07:12:36 -04:00
call go#list#Window(l:listtype, len(errors))
if !empty(errors)
call go#list#JumpToFirst(l:listtype)
endif
2015-12-08 08:20:04 -05:00
endif
2016-06-26 07:12:36 -04:00
else
call go#list#Clean(l:listtype)
call go#list#Window(l:listtype)
echon "vim-go: " | echohl Function | echon "[errcheck] PASS" | echohl None
endif
2015-12-08 08:20:04 -05:00
endfunction
2014-10-31 17:30:24 -04:00
2016-12-27 09:46:49 -05:00
function! go#lint#ToggleMetaLinterAutoSave() abort
2016-08-02 08:48:32 -04:00
if get(g:, "go_metalinter_autosave", 0)
let g:go_metalinter_autosave = 0
call go#util#EchoProgress("auto metalinter disabled")
return
end
let g:go_metalinter_autosave = 1
call go#util#EchoProgress("auto metalinter enabled")
endfunction
2016-12-27 09:46:49 -05:00
function s:lint_job(args)
let status_dir = expand('%:p:h')
let started_at = reltime()
call go#statusline#Update(status_dir, {
\ 'desc': "current status",
\ 'type': "gometalinter",
\ 'state': "analysing",
\})
" autowrite is not enabled for jobs
call go#cmd#autowrite()
let l:listtype = go#list#Type("quickfix")
let l:errformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m'
function! s:callback(chan, msg) closure
let old_errorformat = &errorformat
let &errorformat = l:errformat
caddexpr a:msg
let &errorformat = old_errorformat
" TODO(arslan): cursor still jumps to first error even If I don't want
" it. Seems like there is a regression somewhere, but not sure where.
copen
endfunction
2017-05-02 08:42:08 -04:00
function! s:exit_cb(job, exitval) closure
2016-12-27 09:46:49 -05:00
let status = {
\ 'desc': 'last status',
\ 'type': "gometaliner",
\ 'state': "finished",
\ }
2017-05-02 08:42:08 -04:00
if a:exitval
2016-12-27 09:46:49 -05:00
let status.state = "failed"
endif
let elapsed_time = reltimestr(reltime(started_at))
" strip whitespace
let elapsed_time = substitute(elapsed_time, '^\s*\(.\{-}\)\s*$', '\1', '')
let status.state .= printf(" (%ss)", elapsed_time)
call go#statusline#Update(status_dir, status)
let errors = go#list#Get(l:listtype)
2017-03-07 12:04:28 -05:00
if empty(errors)
2016-12-27 09:46:49 -05:00
call go#list#Window(l:listtype, len(errors))
elseif has("patch-7.4.2200")
if l:listtype == 'quickfix'
call setqflist([], 'a', {'title': 'GoMetaLinter'})
else
call setloclist(0, [], 'a', {'title': 'GoMetaLinter'})
endif
endif
if get(g:, 'go_echo_command_info', 1)
call go#util#EchoSuccess("linting finished")
endif
endfunction
let start_options = {
2017-02-11 08:01:38 -05:00
\ 'callback': funcref("s:callback"),
2017-05-02 08:42:08 -04:00
\ 'exit_cb': funcref("s:exit_cb"),
2016-12-27 09:46:49 -05:00
\ }
call job_start(a:args.cmd, start_options)
call go#list#Clean(l:listtype)
if get(g:, 'go_echo_command_info', 1)
call go#util#EchoProgress("linting started ...")
endif
endfunction
2016-06-26 07:12:36 -04:00
" vim: sw=2 ts=2 et