1
0
Fork 0
mirror of synced 2024-11-16 05:55:35 -05:00
ultimate-vim/sources_non_forked/vim-go/autoload/go/lint.vim

287 lines
8 KiB
VimL
Raw Normal View History

2018-12-17 06:28:27 -05:00
" don't spam the user when Vim is started in Vi compatibility mode
let s:cpo_save = &cpo
set cpo&vim
function! go#lint#Gometa(bang, autosave, ...) abort
2016-06-26 07:12:36 -04:00
if a:0 == 0
2018-02-04 06:35:08 -05:00
let goargs = [expand('%:p:h')]
2016-06-26 07:12:36 -04:00
else
2018-02-04 06:35:08 -05:00
let goargs = a:000
2016-06-26 07:12:36 -04:00
endif
2019-03-27 11:08:56 -04:00
let l:metalinter = go#config#MetalinterCommand()
if l:metalinter == 'gometalinter' || l:metalinter == 'golangci-lint'
let cmd = s:metalintercmd(l:metalinter)
if empty(cmd)
2019-01-08 05:11:54 -05:00
return
endif
2015-12-08 08:20:04 -05:00
2016-06-26 07:12:36 -04:00
" linters
2018-06-14 06:31:12 -04:00
let linters = a:autosave ? go#config#MetalinterAutosaveEnabled() : go#config#MetalinterEnabled()
2016-06-26 07:12:36 -04:00
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
2018-06-14 06:31:12 -04:00
for linter in go#config#MetalinterDisabled()
2018-02-04 06:35:08 -05:00
let cmd += ["--disable=".linter]
2017-05-02 08:42:08 -04:00
endfor
2016-06-26 07:12:36 -04:00
else
" the user wants something else, let us use it.
2019-01-08 05:11:54 -05:00
let cmd = split(go#config#MetalinterCommand(), " ")
2016-12-27 09:46:49 -05:00
endif
2018-02-04 06:35:08 -05:00
if a:autosave
" redraw so that any messages that were displayed while writing the file
" will be cleared
redraw
2019-03-27 11:08:56 -04:00
if l:metalinter == "gometalinter"
" Include only messages for the active buffer for autosave.
let include = [printf('--include=^%s:.*$', fnamemodify(expand('%:p'), ":."))]
if go#util#has_job()
let include = [printf('--include=^%s:.*$', expand('%:p:t'))]
endif
let cmd += include
elseif l:metalinter == "golangci-lint"
let goargs[0] = expand('%:p')
2018-08-25 12:13:42 -04:00
endif
2018-02-04 06:35:08 -05:00
endif
2019-03-27 11:08:56 -04:00
" Call metalinter asynchronously.
2018-06-14 06:31:12 -04:00
let deadline = go#config#MetalinterDeadline()
if deadline != ''
let cmd += ["--deadline=" . deadline]
endif
2017-02-11 08:01:38 -05:00
2018-06-14 06:31:12 -04:00
let cmd += goargs
2018-02-04 06:35:08 -05:00
2019-03-27 11:08:56 -04:00
if l:metalinter == "gometalinter"
" Gometalinter can output one of the two, so we look for both:
" <file>:<line>:<column>:<severity>: <message> (<linter>)
" <file>:<line>::<severity>: <message> (<linter>)
" This can be defined by the following errorformat:
let errformat = "%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m"
else
" Golangci-lint can output the following:
" <file>:<line>:<column>: <message> (<linter>)
" This can be defined by the following errorformat:
let errformat = "%f:%l:%c:\ %m"
endif
2018-09-24 20:40:17 -04:00
if go#util#has_job()
2019-03-27 11:08:56 -04:00
call s:lint_job({'cmd': cmd, 'statustype': l:metalinter, 'errformat': errformat}, a:bang, a:autosave)
2016-12-27 09:46:49 -05:00
return
endif
2018-02-04 06:35:08 -05:00
let [l:out, l:err] = go#util#Exec(cmd)
2016-12-27 09:46:49 -05:00
2018-02-04 06:35:08 -05:00
if a:autosave
let l:listtype = go#list#Type("GoMetaLinterAutoSave")
else
let l:listtype = go#list#Type("GoMetaLinter")
endif
2016-06-26 07:12:36 -04:00
2018-02-04 06:35:08 -05:00
if l:err == 0
2016-06-26 07:12:36 -04:00
call go#list#Clean(l:listtype)
echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None
else
2019-05-17 10:09:13 -04:00
let l:winid = win_getid(winnr())
2016-06-26 07:12:36 -04:00
" 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))
2019-05-17 10:09:13 -04:00
if a:autosave || a:bang
call win_gotoid(l:winid)
return
2015-12-08 08:20:04 -05:00
endif
2019-05-17 10:09:13 -04:00
call go#list#JumpToFirst(l:listtype)
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
2018-12-17 06:28:27 -05:00
function! go#lint#Golint(bang, ...) abort
2016-06-26 07:12:36 -04:00
if a:0 == 0
2018-06-14 06:31:12 -04:00
let [l:out, l:err] = go#util#Exec([go#config#GolintBin(), go#package#ImportPath()])
2016-06-26 07:12:36 -04:00
else
2018-06-14 06:31:12 -04:00
let [l:out, l:err] = go#util#Exec([go#config#GolintBin()] + a:000)
2016-06-26 07:12:36 -04:00
endif
2018-06-14 06:31:12 -04:00
if empty(l:out)
call go#util#EchoSuccess('[lint] PASS')
2016-06-26 07:12:36 -04:00
return
endif
2019-05-17 10:09:13 -04:00
let l:winid = win_getid(winnr())
let l:listtype = go#list#Type("GoLint")
2018-06-14 06:31:12 -04:00
call go#list#Parse(l:listtype, l:out, "GoLint")
let l:errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(l:errors))
2019-05-17 10:09:13 -04:00
if a:bang
call win_gotoid(l:winid)
return
2018-12-17 06:28:27 -05:00
endif
2019-05-17 10:09:13 -04:00
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()
2018-06-14 06:31:12 -04:00
2019-01-08 05:11:54 -05:00
if go#config#EchoCommandInfo()
call go#util#EchoProgress('calling vet...')
endif
2018-06-14 06:31:12 -04:00
2016-06-26 07:12:36 -04:00
if a:0 == 0
2018-06-14 06:31:12 -04:00
let [l:out, l:err] = go#util#Exec(['go', 'vet', go#package#ImportPath()])
2016-06-26 07:12:36 -04:00
else
2018-06-14 06:31:12 -04:00
let [l:out, l:err] = go#util#Exec(['go', 'tool', 'vet'] + a:000)
2016-06-26 07:12:36 -04:00
endif
let l:listtype = go#list#Type("GoVet")
2018-06-14 06:31:12 -04:00
if l:err != 0
2019-05-17 10:09:13 -04:00
let l:winid = win_getid(winnr())
2018-06-14 06:31:12 -04:00
let errorformat = "%-Gexit status %\\d%\\+," . &errorformat
2018-03-31 10:56:26 -04:00
call go#list#ParseFormat(l:listtype, l:errorformat, out, "GoVet")
let errors = go#list#Get(l:listtype)
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)
2019-05-17 10:09:13 -04:00
else
call win_gotoid(l:winid)
2015-12-08 08:20:04 -05:00
endif
2016-06-26 07:12:36 -04:00
else
call go#list#Clean(l:listtype)
2018-06-14 06:31:12 -04:00
call go#util#EchoSuccess('[vet] PASS')
2016-06-26 07:12:36 -04:00
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
2018-12-17 06:28:27 -05:00
function! go#lint#Errcheck(bang, ...) abort
2016-06-26 07:12:36 -04:00
if a:0 == 0
2018-06-14 06:31:12 -04:00
let l:import_path = go#package#ImportPath()
2017-07-06 08:57:35 -04:00
if import_path == -1
2018-06-14 06:31:12 -04:00
call go#util#EchoError('package is not inside GOPATH src')
2016-06-26 07:12:36 -04:00
return
2015-12-08 08:20:04 -05:00
endif
2016-06-26 07:12:36 -04:00
else
2018-06-14 06:31:12 -04:00
let l:import_path = join(a:000, ' ')
2016-06-26 07:12:36 -04:00
endif
2015-12-08 08:20:04 -05:00
2018-06-14 06:31:12 -04:00
call go#util#EchoProgress('[errcheck] analysing ...')
2016-06-26 07:12:36 -04:00
redraw
2018-06-14 06:31:12 -04:00
let [l:out, l:err] = go#util#Exec([go#config#ErrcheckBin(), '-abspath', l:import_path])
2016-06-26 07:12:36 -04:00
let l:listtype = go#list#Type("GoErrCheck")
2018-06-14 06:31:12 -04:00
if l:err != 0
2019-05-17 10:09:13 -04:00
let l:winid = win_getid(winnr())
2016-06-26 07:12:36 -04:00
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
2018-06-14 06:31:12 -04:00
let l:errors = go#list#Get(l:listtype)
if empty(l:errors)
call go#util#EchoError(l:out)
2016-06-26 07:12:36 -04:00
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))
2018-12-17 06:28:27 -05:00
if !a:bang
2016-06-26 07:12:36 -04:00
call go#list#JumpToFirst(l:listtype)
2019-05-17 10:09:13 -04:00
else
call win_gotoid(l:winid)
2016-06-26 07:12:36 -04:00
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)
2018-06-14 06:31:12 -04:00
call go#util#EchoSuccess('[errcheck] PASS')
2016-06-26 07:12:36 -04:00
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
2018-06-14 06:31:12 -04:00
if go#config#MetalinterAutosave()
call go#config#SetMetalinterAutosave(0)
2016-08-02 08:48:32 -04:00
call go#util#EchoProgress("auto metalinter disabled")
return
end
2018-06-14 06:31:12 -04:00
call go#config#SetMetalinterAutosave(1)
2016-08-02 08:48:32 -04:00
call go#util#EchoProgress("auto metalinter enabled")
endfunction
2018-12-17 06:28:27 -05:00
function! s:lint_job(args, bang, autosave)
2018-08-25 12:13:42 -04:00
let l:opts = {
2019-03-27 11:08:56 -04:00
\ 'statustype': a:args.statustype,
\ 'errorformat': a:args.errformat,
2018-08-25 12:13:42 -04:00
\ 'for': "GoMetaLinter",
2018-12-17 06:28:27 -05:00
\ 'bang': a:bang,
2018-08-25 12:13:42 -04:00
\ }
2016-12-27 09:46:49 -05:00
2018-02-04 06:35:08 -05:00
if a:autosave
2018-08-25 12:13:42 -04:00
let l:opts.for = "GoMetaLinterAutoSave"
2018-02-04 06:35:08 -05:00
endif
2016-12-27 09:46:49 -05:00
2018-08-25 12:13:42 -04:00
" autowrite is not enabled for jobs
call go#cmd#autowrite()
2018-09-24 20:40:17 -04:00
call go#job#Spawn(a:args.cmd, l:opts)
2016-12-27 09:46:49 -05:00
endfunction
2019-03-27 11:08:56 -04:00
function! s:metalintercmd(metalinter)
let l:cmd = []
let bin_path = go#path#CheckBinPath(a:metalinter)
if !empty(bin_path)
if a:metalinter == "gometalinter"
let l:cmd = s:gometalintercmd(bin_path)
elseif a:metalinter == "golangci-lint"
let l:cmd = s:golangcilintcmd(bin_path)
endif
endif
return cmd
endfunction
function! s:gometalintercmd(bin_path)
let cmd = [a:bin_path]
let cmd += ["--disable-all"]
" gometalinter has a --tests flag to tell its linters whether to run
" against tests. While not all of its linters respect this flag, for those
" that do, it means if we don't pass --tests, the linter won't run against
" test files. One example of a linter that will not run against tests if
" we do not specify this flag is errcheck.
let cmd += ["--tests"]
return cmd
endfunction
function! s:golangcilintcmd(bin_path)
let cmd = [a:bin_path]
let cmd += ["run"]
let cmd += ["--print-issued-lines=false"]
2019-05-17 10:09:13 -04:00
let cmd += ['--build-tags', go#config#BuildTags()]
2019-03-27 11:08:56 -04:00
let cmd += ["--disable-all"]
" do not use the default exclude patterns, because doing so causes golint
" problems about missing doc strings to be ignored and other things that
" golint identifies.
let cmd += ["--exclude-use-default=false"]
2019-05-17 10:09:13 -04:00
2019-03-27 11:08:56 -04:00
return cmd
endfunction
2018-12-17 06:28:27 -05:00
" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save
2016-06-26 07:12:36 -04:00
" vim: sw=2 ts=2 et