1
0
mirror of https://github.com/amix/vimrc synced 2025-06-30 20:05:01 +08:00

Updated plugins

This commit is contained in:
Amir Salihefendic
2019-11-16 16:28:42 +01:00
parent 96e10ed101
commit 72bdaba47e
204 changed files with 5936 additions and 1666 deletions

View File

@ -32,22 +32,68 @@ function! go#auto#echo_go_info()
redraws! | echo "vim-go: " | echohl Function | echon item.info | echohl None
endfunction
function! go#auto#auto_type_info()
if !go#config#AutoTypeInfo() || !isdirectory(expand('%:p:h'))
let s:timer_id = 0
" go#auto#update_autocmd() will be called on BufEnter,CursorHold. This
" configures the augroup according to conditions below.
"
" | # | has_timer | should_enable | do |
" |---|-----------|---------------|------------------------------------|
" | 1 | false | false | return early |
" | 2 | true | true | return early |
" | 3 | true | false | clear the group and stop the timer |
" | 4 | false | true | configure the group |
function! go#auto#update_autocmd()
let has_timer = get(b:, 'has_timer')
let should_enable = go#config#AutoTypeInfo() || go#config#AutoSameids()
if (!has_timer && !should_enable) || (has_timer && should_enable)
return
endif
" GoInfo automatic update
call go#tool#Info(0)
if has_timer
augroup vim-go-buffer-auto
autocmd! * <buffer>
augroup END
let b:has_timer = 0
call s:timer_stop()
return
endif
augroup vim-go-buffer-auto
autocmd! * <buffer>
autocmd CursorMoved <buffer> call s:timer_restart()
autocmd BufLeave <buffer> call s:timer_stop()
augroup END
let b:has_timer = 1
call s:timer_start()
endfunction
function! go#auto#auto_sameids()
if !go#config#AutoSameids() || !isdirectory(expand('%:p:h'))
return
function! s:timer_restart()
if isdirectory(expand('%:p:h'))
call s:timer_stop()
call s:timer_start()
endif
endfunction
" GoSameId automatic update
call go#guru#SameIds(0)
function! s:timer_stop()
if s:timer_id
call timer_stop(s:timer_id)
let s:timer_id = 0
endif
endfunction
function! s:timer_start()
let s:timer_id = timer_start(go#config#Updatetime(), function('s:handler'))
endfunction
function! s:handler(timer_id)
if go#config#AutoTypeInfo()
call go#tool#Info(0)
endif
if go#config#AutoSameids()
call go#guru#SameIds(0)
endif
let s:timer_id = 0
endfunction
function! go#auto#fmt_autosave()

View File

@ -32,7 +32,7 @@ function! go#cmd#Build(bang, ...) abort
\ map(copy(a:000), "expand(v:val)") +
\ [".", "errors"]
" Vim and Neovim async.
" Vim and Neovim async
if go#util#has_job()
call s:cmd_job({
\ 'cmd': ['go'] + args,
@ -41,8 +41,15 @@ function! go#cmd#Build(bang, ...) abort
\ 'statustype': 'build'
\})
" Vim 7.4 without async
" Vim without async
else
let l:status = {
\ 'desc': 'current status',
\ 'type': 'build',
\ 'state': "started",
\ }
call go#statusline#Update(expand('%:p:h'), l:status)
let default_makeprg = &makeprg
let &makeprg = "go " . join(go#util#Shelllist(args), ' ')
@ -68,10 +75,16 @@ function! go#cmd#Build(bang, ...) abort
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:bang
call go#list#JumpToFirst(l:listtype)
let l:status.state = 'failed'
else
call go#util#EchoSuccess("[build] SUCCESS")
let l:status.state = 'success'
if go#config#EchoCommandInfo()
call go#util#EchoSuccess("[build] SUCCESS")
endif
endif
call go#statusline#Update(expand('%:p:h'), l:status)
endif
endfunction
@ -134,6 +147,14 @@ function! go#cmd#Run(bang, ...) abort
" anything. Once this is implemented we're going to make :GoRun async
endif
let l:status = {
\ 'desc': 'current status',
\ 'type': 'run',
\ 'state': "started",
\ }
call go#statusline#Update(expand('%:p:h'), l:status)
let cmd = "go run "
let tags = go#config#BuildTags()
if len(tags) > 0
@ -147,12 +168,21 @@ function! go#cmd#Run(bang, ...) abort
exec '!' . cmd . go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1)
endif
let l:status.state = 'success'
if v:shell_error
redraws! | echon "vim-go: [run] " | echohl ErrorMsg | echon "FAILED"| echohl None
let l:status.state = 'failed'
if go#config#EchoCommandInfo()
redraws!
call go#util#EchoError('[run] FAILED')
endif
else
redraws! | echon "vim-go: [run] " | echohl Function | echon "SUCCESS"| echohl None
if go#config#EchoCommandInfo()
redraws!
call go#util#EchoSuccess('[run] SUCCESS')
endif
endif
call go#statusline#Update(expand('%:p:h'), l:status)
return
endif
@ -166,8 +196,8 @@ function! go#cmd#Run(bang, ...) abort
let l:listtype = go#list#Type("GoRun")
let l:status.state = 'success'
try
" backup user's errorformat, will be restored once we are finished
let l:old_errorformat = &errorformat
let &errorformat = s:runerrorformat()
@ -185,10 +215,13 @@ function! go#cmd#Run(bang, ...) abort
let l:errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(l:errors))
if !empty(l:errors) && !a:bang
call go#list#JumpToFirst(l:listtype)
if !empty(l:errors)
let l:status.state = 'failed'
if !a:bang
call go#list#JumpToFirst(l:listtype)
endif
endif
call go#statusline#Update(expand('%:p:h'), l:status)
endfunction
" Install installs the package by simple calling 'go install'. If any argument
@ -255,9 +288,18 @@ function! go#cmd#Generate(bang, ...) abort
let &makeprg = "go generate " . goargs . ' ' . gofiles
endif
let l:listtype = go#list#Type("GoGenerate")
let l:status = {
\ 'desc': 'current status',
\ 'type': 'generate',
\ 'state': "started",
\ }
call go#statusline#Update(expand('%:p:h'), l:status)
echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None
if go#config#EchoCommandInfo()
call go#util#EchoProgress('generating ...')
endif
let l:listtype = go#list#Type("GoGenerate")
try
if l:listtype == "locationlist"
@ -273,13 +315,18 @@ function! go#cmd#Generate(bang, ...) abort
let errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(errors))
if !empty(errors)
let l:status.status = 'failed'
if !a:bang
call go#list#JumpToFirst(l:listtype)
endif
else
redraws! | echon "vim-go: " | echohl Function | echon "[generate] SUCCESS"| echohl None
let l:status.status = 'success'
if go#config#EchoCommandInfo()
redraws!
call go#util#EchoSuccess('[generate] SUCCESS')
endif
endif
call go#statusline#Update(expand(':%:p:h'), l:status)
endfunction
function! s:runerrorformat()

View File

@ -221,7 +221,6 @@ function! s:info_complete(echo, result) abort
endfunction
function! s:trim_bracket(val) abort
echom a:val
let a:val.word = substitute(a:val.word, '[(){}\[\]]\+$', '', '')
return a:val
endfunction
@ -293,11 +292,11 @@ function! go#complete#ToggleAutoTypeInfo() abort
if go#config#AutoTypeInfo()
call go#config#SetAutoTypeInfo(0)
call go#util#EchoProgress("auto type info disabled")
return
end
call go#config#SetAutoTypeInfo(1)
call go#util#EchoProgress("auto type info enabled")
else
call go#config#SetAutoTypeInfo(1)
call go#util#EchoProgress("auto type info enabled")
endif
call go#auto#update_autocmd()
endfunction
" restore Vi compatibility settings

View File

@ -23,12 +23,15 @@ endfunction
func! s:getinfo()
let l:filename = 'complete/complete.go'
let l:tmp = gotest#load_fixture(l:filename)
try
call cursor(8, 3)
call cursor(8, 3)
let expected = 'func Example(s string)'
let actual = go#complete#GetInfo()
call assert_equal(expected, actual)
let expected = 'func Example(s string)'
let actual = go#complete#GetInfo()
call assert_equal(expected, actual)
finally
call delete(l:tmp, 'rf')
endtry
endfunction
" restore Vi compatibility settings

View File

@ -205,9 +205,10 @@ endfunction
function! go#config#DebugWindows() abort
return get(g:, 'go_debug_windows', {
\ 'stack': 'leftabove 20vnew',
\ 'out': 'botright 10new',
\ 'vars': 'leftabove 30vnew',
\ 'stack': 'leftabove 20new',
\ 'goroutines': 'botright 10new',
\ 'out': 'botright 5new',
\ }
\ )
@ -224,7 +225,7 @@ function! go#config#DebugCommands() abort
endfunction
function! go#config#DebugLogOutput() abort
return get(g:, 'go_debug_log_output', 'debugger, rpc')
return get(g:, 'go_debug_log_output', 'debugger,rpc')
endfunction
function! go#config#LspLog() abort
@ -258,7 +259,7 @@ function! go#config#SetTemplateAutocreate(value) abort
endfunction
function! go#config#MetalinterCommand() abort
return get(g:, "go_metalinter_command", "gometalinter")
return get(g:, "go_metalinter_command", "golangci-lint")
endfunction
function! go#config#MetalinterAutosaveEnabled() abort
@ -365,6 +366,11 @@ function! go#config#PlayOpenBrowser() abort
return get(g:, "go_play_open_browser", 1)
endfunction
function! go#config#GorenameCommand() abort
" delegate to go#config#GorenameBin for backwards compatability.
return get(g:, "go_gorename_command", go#config#GorenameBin())
endfunction
function! go#config#GorenameBin() abort
return get(g:, "go_gorename_bin", "gorename")
endfunction
@ -460,6 +466,14 @@ function! go#config#HighlightVariableDeclarations() abort
return get(g:, 'go_highlight_variable_declarations', 0)
endfunction
function! go#config#HighlightDiagnosticErrors() abort
return get(g:, 'go_highlight_diagnostic_errors', 1)
endfunction
function! go#config#HighlightDiagnosticWarnings() abort
return get(g:, 'go_highlight_diagnostic_warnings', 1)
endfunction
function! go#config#HighlightDebug() abort
return get(g:, 'go_highlight_debug', 1)
endfunction
@ -479,6 +493,31 @@ function! go#config#CodeCompletionEnabled() abort
return get(g:, "go_code_completion_enabled", 1)
endfunction
function! go#config#Updatetime() abort
let go_updatetime = get(g:, 'go_updatetime', 800)
return go_updatetime == 0 ? &updatetime : go_updatetime
endfunction
function! go#config#ReferrersMode() abort
return get(g:, 'go_referrers_mode', 'gopls')
endfunction
function! go#config#GoplsCompleteUnimported() abort
return get(g:, 'go_gopls_complete_unimported', 0)
endfunction
function! go#config#GoplsDeepCompletion() abort
return get(g:, 'go_gopls_deep_completion', 1)
endfunction
function! go#config#GoplsFuzzyMatching() abort
return get(g:, 'go_gopls_fuzzy_matching', 1)
endfunction
function! go#config#GoplsUsePlaceholders() abort
return get(g:, 'go_gopls_use_placeholders', 0)
endfunction
" Set the default value. A value of "1" is a shortcut for this, for
" compatibility reasons.
if exists("g:go_gorename_prefill") && g:go_gorename_prefill == 1

View File

@ -0,0 +1,86 @@
" don't spam the user when Vim is started in Vi compatibility mode
let s:cpo_save = &cpo
set cpo&vim
scriptencoding utf-8
func! Test_SetBuildTags() abort
if !go#util#has_job()
return
endif
try
let g:go_def_mode = 'gopls'
let l:dir = 'test-fixtures/config/buildtags'
let l:jumpstart = [0, 4, 2, 0]
execute 'e ' . printf('%s/buildtags.go', l:dir)
let l:jumpstartbuf = bufnr('')
call setpos('.', [l:jumpstartbuf, l:jumpstart[1], l:jumpstart[2], 0])
let l:expectedfilename = printf('%s/foo.go', l:dir)
let l:expected = [0, 5, 1, 0]
call assert_notequal(l:expected, l:jumpstart)
call go#def#Jump('', 0)
let l:start = reltime()
while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10
sleep 100m
endwhile
call assert_equal(l:expectedfilename, bufname("%"))
call assert_equal(l:expected, getpos('.'))
execute 'e ' . printf('%s/buildtags.go', l:dir)
" prepare to wait for the workspace/configuration request
let g:go_debug=['lsp']
" set the build constraint
call go#config#SetBuildTags('constrained')
" wait for the workspace/configuration request
let l:lsplog = getbufline('__GOLSP_LOG__', 1, '$')
let l:start = reltime()
while match(l:lsplog, 'workspace/configuration') == -1 && reltimefloat(reltime(l:start)) < 10
sleep 50m
let l:lsplog = getbufline('__GOLSP_LOG__', 1, '$')
endwhile
unlet g:go_debug
" close the __GOLSP_LOG__ window
only
" verify the cursor position within buildtags.go
call setpos('.', [l:jumpstartbuf, l:jumpstart[1], l:jumpstart[2], 0])
call assert_equal(l:jumpstart, getpos('.'))
let l:expectedfilename = printf('%s/constrainedfoo.go', l:dir)
let l:expected = [0, 6, 1, 0]
call assert_notequal(l:expected, l:jumpstart)
call go#def#Jump('', 0)
let l:start = reltime()
while getpos('.') != l:expected && reltimefloat(reltime(l:start)) < 10
sleep 100m
endwhile
call assert_equal(l:expectedfilename, bufname("%"))
call assert_equal(l:expected, getpos('.'))
let l:lsplog = getbufline('__GOLSP_LOG__', 1, '$')
finally
call go#config#SetBuildTags('')
unlet g:go_def_mode
endtry
endfunc
" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: sw=2 ts=2 et

View File

@ -25,10 +25,10 @@ endfunction
" the code. Calling it again reruns the tests and shows the last updated
" coverage.
function! go#coverage#Buffer(bang, ...) abort
" we use matchaddpos() which was introduce with 7.4.330, be sure we have
" it: http://ftp.vim.org/vim/patches/7.4/7.4.330
" check if the version of Vim being tested supports matchaddpos()
if !exists("*matchaddpos")
call go#util#EchoError("GoCoverage is supported with Vim version 7.4-330 or later")
call go#util#EchoError("GoCoverage is not supported by your version of Vim.")
return -1
endif

View File

@ -23,7 +23,7 @@ if !exists('s:start_args')
let s:start_args = []
endif
function! s:groutineID() abort
function! s:goroutineID() abort
return s:state['currentThread'].goroutineID
endfunction
@ -82,7 +82,7 @@ endfunction
function! s:call_jsonrpc(method, ...) abort
if go#util#HasDebug('debugger-commands')
echom 'sending to dlv ' . a:method
call go#util#EchoInfo('sending to dlv ' . a:method)
endif
let l:args = a:000
@ -160,7 +160,7 @@ endfunction
" Populate the stacktrace window.
function! s:show_stacktrace(res) abort
if !has_key(a:res, 'result')
if type(a:res) isnot type({}) || !has_key(a:res, 'result') || empty(a:res.result)
return
endif
@ -279,6 +279,7 @@ function! go#debug#Stop() abort
silent! exe bufwinnr(bufnr('__GODEBUG_STACKTRACE__')) 'wincmd c'
silent! exe bufwinnr(bufnr('__GODEBUG_VARIABLES__')) 'wincmd c'
silent! exe bufwinnr(bufnr('__GODEBUG_OUTPUT__')) 'wincmd c'
silent! exe bufwinnr(bufnr('__GODEBUG_GOROUTINES__')) 'wincmd c'
if has('balloon_eval')
let &ballooneval=s:ballooneval
@ -325,10 +326,10 @@ endfunction
function! s:expand_var() abort
" Get name from struct line.
let name = matchstr(getline('.'), '^[^:]\+\ze: [a-zA-Z0-9\.·]\+{\.\.\.}$')
let name = matchstr(getline('.'), '^[^:]\+\ze: \*\?[a-zA-Z0-9-_/\.]\+\({\.\.\.}\)\?$')
" Anonymous struct
if name == ''
let name = matchstr(getline('.'), '^[^:]\+\ze: struct {.\{-}}$')
let name = matchstr(getline('.'), '^[^:]\+\ze: \*\?struct {.\{-}}$')
endif
if name != ''
@ -418,23 +419,6 @@ function! s:start_cb() abort
endif
let debugwindows = go#config#DebugWindows()
if has_key(debugwindows, "stack") && debugwindows['stack'] != ''
exe 'silent ' . debugwindows['stack']
silent file `='__GODEBUG_STACKTRACE__'`
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
setlocal filetype=godebugstacktrace
nmap <buffer> <cr> :<c-u>call <SID>goto_file()<cr>
nmap <buffer> q <Plug>(go-debug-stop)
endif
if has_key(debugwindows, "out") && debugwindows['out'] != ''
exe 'silent ' . debugwindows['out']
silent file `='__GODEBUG_OUTPUT__'`
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
setlocal filetype=godebugoutput
nmap <buffer> q <Plug>(go-debug-stop)
endif
if has_key(debugwindows, "vars") && debugwindows['vars'] != ''
exe 'silent ' . debugwindows['vars']
silent file `='__GODEBUG_VARIABLES__'`
@ -445,6 +429,33 @@ function! s:start_cb() abort
nmap <buffer> q <Plug>(go-debug-stop)
endif
if has_key(debugwindows, "stack") && debugwindows['stack'] != ''
exe 'silent ' . debugwindows['stack']
silent file `='__GODEBUG_STACKTRACE__'`
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
setlocal filetype=godebugstacktrace
nmap <buffer> <cr> :<c-u>call <SID>goto_file()<cr>
nmap <buffer> q <Plug>(go-debug-stop)
endif
if has_key(debugwindows, "goroutines") && debugwindows['goroutines'] != ''
exe 'silent ' . debugwindows['goroutines']
silent file `='__GODEBUG_GOROUTINES__'`
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
setlocal filetype=godebugvariables
call append(0, ["# Goroutines"])
nmap <buffer> <silent> <cr> :<c-u>call go#debug#Goroutine()<cr>
endif
if has_key(debugwindows, "out") && debugwindows['out'] != ''
exe 'silent ' . debugwindows['out']
silent file `='__GODEBUG_OUTPUT__'`
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
setlocal filetype=godebugoutput
nmap <buffer> q <Plug>(go-debug-stop)
endif
call win_gotoid(l:winid)
silent! delcommand GoDebugStart
silent! delcommand GoDebugTest
command! -nargs=0 GoDebugContinue call go#debug#Stack('continue')
@ -459,7 +470,7 @@ function! s:start_cb() abort
nnoremap <silent> <Plug>(go-debug-breakpoint) :<C-u>call go#debug#Breakpoint()<CR>
nnoremap <silent> <Plug>(go-debug-next) :<C-u>call go#debug#Stack('next')<CR>
nnoremap <silent> <Plug>(go-debug-step) :<C-u>call go#debug#Stack('step')<CR>
nnoremap <silent> <Plug>(go-debug-stepout) :<C-u>call go#debug#Stack('stepout')<CR>
nnoremap <silent> <Plug>(go-debug-stepout) :<C-u>call go#debug#Stack('stepOut')<CR>
nnoremap <silent> <Plug>(go-debug-continue) :<C-u>call go#debug#Stack('continue')<CR>
nnoremap <silent> <Plug>(go-debug-stop) :<C-u>call go#debug#Stop()<CR>
nnoremap <silent> <Plug>(go-debug-print) :<C-u>call go#debug#Print(expand('<cword>'))<CR>
@ -472,8 +483,6 @@ function! s:start_cb() abort
set ballooneval
endif
call win_gotoid(l:winid)
augroup vim-go-debug
autocmd! * <buffer>
autocmd FileType go nmap <buffer> <F5> <Plug>(go-debug-continue)
@ -487,7 +496,7 @@ endfunction
function! s:err_cb(ch, msg) abort
if get(s:state, 'ready', 0) != 0
call call('s:logger', ['ERR: ', a:ch, a:msg])
call s:logger('ERR: ', a:ch, a:msg)
return
endif
@ -496,7 +505,7 @@ endfunction
function! s:out_cb(ch, msg) abort
if get(s:state, 'ready', 0) != 0
call call('s:logger', ['OUT: ', a:ch, a:msg])
call s:logger('OUT: ', a:ch, a:msg)
return
endif
@ -771,6 +780,92 @@ function! go#debug#Print(arg) abort
endtry
endfunction
function! s:update_goroutines() abort
try
let l:res = s:call_jsonrpc('RPCServer.State')
let l:currentGoroutineID = 0
try
if type(l:res) is type({}) && has_key(l:res, 'result') && !empty(l:res['result'])
let l:currentGoroutineID = l:res["result"]["State"]["currentGoroutine"]["id"]
endif
catch
call go#util#EchoWarning("current goroutine not found...")
endtry
let l:res = s:call_jsonrpc('RPCServer.ListGoroutines')
call s:show_goroutines(l:currentGoroutineID, l:res)
catch
call go#util#EchoError(v:exception)
endtry
endfunction
function! s:show_goroutines(currentGoroutineID, res) abort
let l:goroutines_winid = bufwinid('__GODEBUG_GOROUTINES__')
if l:goroutines_winid == -1
return
endif
let l:winid = win_getid()
call win_gotoid(l:goroutines_winid)
try
setlocal modifiable
silent %delete _
let v = ['# Goroutines']
if type(a:res) isnot type({}) || !has_key(a:res, 'result') || empty(a:res['result'])
call setline(1, v)
return
endif
let l:goroutines = a:res["result"]["Goroutines"]
if len(l:goroutines) == 0
call go#util#EchoWarning("No Goroutines Running Now...")
call setline(1, v)
return
endif
for l:idx in range(len(l:goroutines))
let l:goroutine = l:goroutines[l:idx]
let l:goroutineType = ""
let l:loc = 0
if l:goroutine.startLoc.file != ""
let l:loc = l:goroutine.startLoc
let l:goroutineType = "Start"
endif
if l:goroutine.goStatementLoc.file != ""
let l:loc = l:goroutine.goStatementLoc
let l:goroutineType = "Go"
endif
if l:goroutine.currentLoc.file != ""
let l:loc = l:goroutine.currentLoc
let l:goroutineType = "Runtime"
endif
if l:goroutine.userCurrentLoc.file != ""
let l:loc=l:goroutine.userCurrentLoc
let l:goroutineType = "User"
endif
" The current goroutine can be changed by pressing enter on one of the
" lines listing a non-active goroutine. If the format of either of these
" lines is modified, then make sure that go#debug#Goroutine is also
" changed if needed.
if l:goroutine.id == a:currentGoroutineID
let l:g = printf("* Goroutine %s - %s: %s:%s %s (thread: %s)", l:goroutine.id, l:goroutineType, l:loc.file, l:loc.line, l:loc.function.name, l:goroutine.threadID)
else
let l:g = printf(" Goroutine %s - %s: %s:%s %s (thread: %s)", l:goroutine.id, l:goroutineType, l:loc.file, l:loc.line, l:loc.function.name, l:goroutine.threadID)
endif
let v += [l:g]
endfor
call setline(1, v)
finally
setlocal nomodifiable
call win_gotoid(l:winid)
endtry
endfunction
function! s:update_variables() abort
" FollowPointers requests pointers to be automatically dereferenced.
" MaxVariableRecurse is how far to recurse when evaluating nested types.
@ -778,20 +873,27 @@ function! s:update_variables() abort
" MaxArrayValues is the maximum number of elements read from an array, a slice or a map.
" MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields.
let l:cfg = {
\ 'scope': {'GoroutineID': s:groutineID()},
\ 'scope': {'GoroutineID': s:goroutineID()},
\ 'cfg': {'MaxStringLen': 20, 'MaxArrayValues': 20}
\ }
try
let res = s:call_jsonrpc('RPCServer.ListLocalVars', l:cfg)
let s:state['localVars'] = res.result['Variables']
let s:state['localVars'] = {}
if type(l:res) is type({}) && has_key(l:res, 'result') && !empty(l:res.result)
let s:state['localVars'] = l:res.result['Variables']
endif
catch
call go#util#EchoError(v:exception)
endtry
try
let res = s:call_jsonrpc('RPCServer.ListFunctionArgs', l:cfg)
let s:state['functionArgs'] = res.result['Args']
let s:state['functionArgs'] = {}
if type(l:res) is type({}) && has_key(l:res, 'result') && !empty(l:res.result)
let s:state['functionArgs'] = res.result['Args']
endif
catch
call go#util#EchoError(v:exception)
endtry
@ -816,7 +918,7 @@ endfunction
function! s:update_stacktrace() abort
try
let l:res = s:call_jsonrpc('RPCServer.Stacktrace', {'id': s:groutineID(), 'depth': 5})
let l:res = s:call_jsonrpc('RPCServer.Stacktrace', {'id': s:goroutineID(), 'depth': 5})
call s:show_stacktrace(l:res)
catch
call go#util#EchoError(v:exception)
@ -826,10 +928,12 @@ endfunction
function! s:stack_cb(res) abort
let s:stack_name = ''
if empty(a:res) || !has_key(a:res, 'result')
if type(a:res) isnot type({}) || !has_key(a:res, 'result') || empty(a:res.result)
return
endif
call s:update_breakpoint(a:res)
call s:update_goroutines()
call s:update_stacktrace()
call s:update_variables()
endfunction
@ -861,8 +965,20 @@ function! go#debug#Stack(name) abort
endif
let s:stack_name = l:name
try
let res = s:call_jsonrpc('RPCServer.Command', {'name': l:name})
call s:stack_cb(res)
let l:res = s:call_jsonrpc('RPCServer.Command', {'name': l:name})
if l:name is# 'next'
let l:res2 = l:res
let l:w = 0
while l:w < 1
if l:res2.result.State.NextInProgress == v:true
let l:res2 = s:call_jsonrpc('RPCServer.Command', {'name': 'continue'})
else
break
endif
endwhile
endif
call s:stack_cb(l:res)
catch
call go#util#EchoError(v:exception)
call s:clearState()
@ -899,6 +1015,23 @@ function! s:isActive()
return len(s:state['message']) > 0
endfunction
" Change Goroutine
function! go#debug#Goroutine() abort
let l:goroutineID = substitute(getline('.'), '^ Goroutine \(.\{-1,\}\) - .*', '\1', 'g')
if l:goroutineID <= 0
return
endif
try
let l:res = s:call_jsonrpc('RPCServer.Command', {'Name': 'switchGoroutine', 'GoroutineID': str2nr(l:goroutineID)})
call s:stack_cb(l:res)
call go#util#EchoInfo("Switched goroutine to: " . l:goroutineID)
catch
call go#util#EchoError(v:exception)
endtry
endfunction
" Toggle breakpoint. Returns 0 on success and 1 on failure.
function! go#debug#Breakpoint(...) abort
let l:filename = fnamemodify(expand('%'), ':p:gs!\\!/!')

View File

@ -24,14 +24,15 @@ function! Test_GoDebugStart_Errors() abort
endif
try
let l:tmp = gotest#load_fixture('debug/compilerror/main.go')
let l:expected = [
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 0, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': '# debug/compilerror'},
\ {'lnum': 6, 'bufnr': 7, 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ' syntax error: unexpected newline, expecting comma or )'},
\ {'lnum': 6, 'bufnr': bufnr('%'), 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': ' syntax error: unexpected newline, expecting comma or )'},
\ {'lnum': 0, 'bufnr': 0, 'col': 0, 'valid': 0, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exit status 2'}
\]
call setqflist([], 'r')
let l:tmp = gotest#load_fixture('debug/compilerror/main.go')
call assert_false(exists(':GoDebugStop'))
let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'

View File

@ -162,9 +162,9 @@ function! go#def#jump_to_declaration(out, mode, bin_name) abort
if filename != fnamemodify(expand("%"), ':p:gs?\\?/?')
" jump to existing buffer if, 1. we have enabled it, 2. the buffer is loaded
" and 3. there is buffer window number we switch to
if go#config#DefReuseBuffer() && bufloaded(filename) != 0 && bufwinnr(filename) != -1
" jumpt to existing buffer if it exists
execute bufwinnr(filename) . 'wincmd w'
if go#config#DefReuseBuffer() && bufwinnr(filename) != -1
" jump to existing buffer if it exists
call win_gotoid(bufwinnr(filename))
else
if &modified
let cmd = 'hide edit'
@ -186,7 +186,13 @@ function! go#def#jump_to_declaration(out, mode, bin_name) abort
endif
" open the file and jump to line and column
exec cmd fnameescape(fnamemodify(filename, ':.'))
try
exec cmd fnameescape(fnamemodify(filename, ':.'))
catch
if stridx(v:exception, ':E325:') < 0
call go#util#EchoError(v:exception)
endif
endtry
endif
endif
call cursor(line, col)

View File

@ -77,14 +77,50 @@ endfunction
function! s:GodocView(newposition, position, content) abort
" popup window
if go#config#DocPopupWindow() && exists('*popup_atcursor') && exists('*popup_clear')
call popup_clear()
if go#config#DocPopupWindow()
if exists('*popup_atcursor') && exists('*popup_clear')
call popup_clear()
call popup_atcursor(split(a:content, '\n'), {
\ 'padding': [1, 1, 1, 1],
\ 'borderchars': ['-','|','-','|','+','+','+','+'],
\ "border": [1, 1, 1, 1],
\ })
call popup_atcursor(split(a:content, '\n'), {
\ 'padding': [1, 1, 1, 1],
\ 'borderchars': ['-','|','-','|','+','+','+','+'],
\ "border": [1, 1, 1, 1],
\ })
elseif has('nvim') && exists('*nvim_open_win')
let lines = split(a:content, '\n')
let height = 0
let width = 0
for line in lines
let lw = strdisplaywidth(line)
if lw > width
let width = lw
endif
let height += 1
endfor
let width += 1 " right margin
let max_height = go#config#DocMaxHeight()
if height > max_height
let height = max_height
endif
let buf = nvim_create_buf(v:false, v:true)
call nvim_buf_set_lines(buf, 0, -1, v:true, lines)
let opts = {
\ 'relative': 'cursor',
\ 'row': 1,
\ 'col': 0,
\ 'width': width,
\ 'height': height,
\ 'style': 'minimal',
\ }
call nvim_open_win(buf, v:true, opts)
setlocal nomodified nomodifiable filetype=godoc
" close easily with CR, Esc and q
noremap <buffer> <silent> <CR> :<C-U>close<CR>
noremap <buffer> <silent> <Esc> :<C-U>close<CR>
noremap <buffer> <silent> q :<C-U>close<CR>
endif
return
endif

View File

@ -62,7 +62,7 @@ func! Test_fillstruct_two_line() abort
\ '\tAddress: "",',
\ '}) }'])
finally
"call delete(l:tmp, 'rf')
call delete(l:tmp, 'rf')
endtry
endfunc

View File

@ -120,18 +120,11 @@ function! go#fmt#update_file(source, target)
let l:listtype = go#list#Type("GoFmt")
" the title information was introduced with 7.4-2200
" https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640
if has('patch-7.4.2200')
" clean up previous list
if l:listtype == "quickfix"
let l:list_title = getqflist({'title': 1})
else
let l:list_title = getloclist(0, {'title': 1})
endif
" clean up previous list
if l:listtype == "quickfix"
let l:list_title = getqflist({'title': 1})
else
" can't check the title, so assume that the list was for go fmt.
let l:list_title = {'title': 'Format'}
let l:list_title = getloclist(0, {'title': 1})
endif
if has_key(l:list_title, "title") && l:list_title['title'] == "Format"
@ -196,7 +189,6 @@ function! s:show_errors(errors) abort
let l:listtype = go#list#Type("GoFmt")
if !empty(a:errors)
call go#list#Populate(l:listtype, a:errors, 'Format')
echohl Error | echomsg "Gofmt returned error" | echohl None
endif
" this closes the window if there are no errors or it opens

View File

@ -232,11 +232,10 @@ function! go#guru#Describe(selected) abort
endfunction
function! go#guru#DescribeInfo(showstatus) abort
" json_encode() and friends are introduced with this patch (7.4.1304)
" vim: https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ
" nvim: https://github.com/neovim/neovim/pull/4131
" check if the version of Vim being tested supports json_decode()
if !exists("*json_decode")
call go#util#EchoError("requires 'json_decode'. Update your Vim/Neovim version.")
call go#util#EchoError("GoDescribeInfo requires 'json_decode'. Update your Vim/Neovim version.")
return
endif
@ -405,44 +404,45 @@ endfunction
" Show all refs to entity denoted by selected identifier
function! go#guru#Referrers(selected) abort
let args = {
\ 'mode': 'referrers',
\ 'format': 'plain',
\ 'selected': a:selected,
\ 'needs_scope': 0,
\ }
let l:mode = go#config#ReferrersMode()
if l:mode == 'guru'
let args = {
\ 'mode': 'referrers',
\ 'format': 'plain',
\ 'selected': a:selected,
\ 'needs_scope': 0,
\ }
call s:run_guru(args)
call s:run_guru(args)
return
elseif l:mode == 'gopls'
let [l:line, l:col] = getpos('.')[1:2]
let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col)
let l:fname = expand('%:p')
call go#lsp#Referrers(l:fname, l:line, l:col, funcref('s:parse_guru_output'))
return
else
call go#util#EchoWarning('unknown value for g:go_referrers_mode')
endif
endfunction
function! go#guru#SameIds(showstatus) abort
" we use matchaddpos() which was introduce with 7.4.330, be sure we have
" it: http://ftp.vim.org/vim/patches/7.4/7.4.330
" check if the version of Vim being tested supports matchaddpos()
if !exists("*matchaddpos")
call go#util#EchoError("GoSameIds requires 'matchaddpos'. Update your Vim/Neovim version.")
return
endif
" json_encode() and friends are introduced with this patch (7.4.1304)
" vim: https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ
" nvim: https://github.com/neovim/neovim/pull/4131
" check if the version of Vim being tested supports json_decode()
if !exists("*json_decode")
call go#util#EchoError("GoSameIds requires 'json_decode'. Update your Vim/Neovim version.")
return
endif
let args = {
\ 'mode': 'what',
\ 'format': 'json',
\ 'selected': -1,
\ 'needs_scope': 0,
\ 'custom_parse': function('s:same_ids_highlight'),
\ }
if !a:showstatus
let args.disable_progress = 1
endif
call s:run_guru(args)
let [l:line, l:col] = getpos('.')[1:2]
let [l:line, l:col] = go#lsp#lsp#Position(l:line, l:col)
call go#lsp#SameIDs(0, expand('%:p'), l:line, l:col, funcref('s:same_ids_highlight'))
endfunction
function! s:same_ids_highlight(exit_val, output, mode) abort
@ -482,12 +482,16 @@ function! s:same_ids_highlight(exit_val, output, mode) abort
endif
let same_ids = result['sameids']
" highlight the lines
let l:matches = []
for item in same_ids
let pos = split(item, ':')
call matchaddpos('goSameId', [[str2nr(pos[-2]), str2nr(pos[-1]), str2nr(poslen)]])
let l:matches = add(l:matches, [str2nr(pos[-2]), str2nr(pos[-1]), str2nr(poslen)])
endfor
call matchaddpos('goSameId', l:matches)
if go#config#AutoSameids()
" re-apply SameIds at the current cursor position at the time the buffer
" is redisplayed: e.g. :edit, :GoRename, etc.
@ -501,15 +505,7 @@ endfunction
" ClearSameIds returns 0 when it removes goSameId groups and non-zero if no
" goSameId groups are found.
function! go#guru#ClearSameIds() abort
let l:cleared = 0
let m = getmatches()
for item in m
if item['group'] == 'goSameId'
call matchdelete(item['id'])
let l:cleared = 1
endif
endfor
let l:cleared = go#util#ClearGroupFromMatches('goSameId')
if !l:cleared
return 1
@ -534,11 +530,11 @@ function! go#guru#AutoToggleSameIds() abort
call go#util#EchoProgress("sameids auto highlighting disabled")
call go#guru#ClearSameIds()
call go#config#SetAutoSameids(0)
return
else
call go#util#EchoSuccess("sameids auto highlighting enabled")
call go#config#SetAutoSameids(1)
endif
call go#util#EchoSuccess("sameids auto highlighting enabled")
call go#config#SetAutoSameids(1)
call go#auto#update_autocmd()
endfunction
@ -602,11 +598,9 @@ function! go#guru#DescribeBalloon() abort
return
endif
" json_encode() and friends are introduced with this patch (7.4.1304)
" vim: https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ
" nvim: https://github.com/neovim/neovim/pull/4131
" check if the version of Vim being tested supports json_decode()
if !exists("*json_decode")
call go#util#EchoError("requires 'json_decode'. Update your Vim/Neovim version.")
call go#util#EchoError("GoDescribeBalloon requires 'json_decode'. Update your Vim/Neovim version.")
return
endif

View File

@ -98,6 +98,46 @@ function! Test_gomodVersion_incompatible_highlight() abort
endtry
endfunc
function! Test_numeric_literal_highlight() abort
syntax on
let tests = {
\ 'lone zero': {'group': 'goDecimalInt', 'value': '0'},
\ 'integer': {'group': 'goDecimalInt', 'value': '1234567890'},
\ 'hexadecimal': {'group': 'goHexadecimalInt', 'value': '0x0123456789abdef'},
\ 'hexadecimalErrorLeading': {'group': 'goHexadecimalError', 'value': '0xg0123456789abdef'},
\ 'hexadecimalErrorTrailing': {'group': 'goHexadecimalError', 'value': '0x0123456789abdefg'},
\ 'heXadecimal': {'group': 'goHexadecimalInt', 'value': '0X0123456789abdef'},
\ 'heXadecimalErrorLeading': {'group': 'goHexadecimalError', 'value': '0Xg0123456789abdef'},
\ 'heXadecimalErrorTrailing': {'group': 'goHexadecimalError', 'value': '0X0123456789abdefg'},
\ 'octal': {'group': 'goOctalInt', 'value': '01234567'},
\ 'octalErrorLeading': {'group': 'goOctalError', 'value': '081234567'},
\ 'octalErrorTrailing': {'group': 'goOctalError', 'value': '012345678'},
\ 'binaryInt': {'group': 'goBinaryInt', 'value': '0b0101'},
\ 'binaryErrorLeading': {'group': 'goBinaryError', 'value': '0b20101'},
\ 'binaryErrorTrailing': {'group': 'goBinaryError', 'value': '0b01012'},
\ 'BinaryInt': {'group': 'goBinaryInt', 'value': '0B0101'},
\ 'BinaryErrorLeading': {'group': 'goBinaryError', 'value': '0B20101'},
\ 'BinaryErrorTrailing': {'group': 'goBinaryError', 'value': '0B01012'},
\ }
for kv in items(tests)
let l:dir = gotest#write_file(printf('numeric/%s.go', kv[0]), [
\ 'package numeric',
\ '',
\ printf("var v = %s\x1f", kv[1].value),
\ ])
try
let l:pos = getcurpos()
let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')
call assert_equal(kv[1].group, l:actual, kv[0])
finally
" call delete(l:dir, 'rf')
endtry
endfor
endfunction
" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save

View File

@ -61,7 +61,7 @@ function! go#job#Options(args)
let state = {
\ 'winid': win_getid(winnr()),
\ 'dir': getcwd(),
\ 'jobdir': fnameescape(expand("%:p:h")),
\ 'jobdir': expand("%:p:h"),
\ 'messages': [],
\ 'bang': 0,
\ 'for': "_job",
@ -72,9 +72,7 @@ function! go#job#Options(args)
\ 'statustype' : ''
\ }
if has("patch-8.0.0902") || has('nvim')
let cbs.cwd = state.jobdir
endif
let cbs.cwd = state.jobdir
if has_key(a:args, 'bang')
let state.bang = a:args.bang
@ -195,7 +193,7 @@ function! go#job#Options(args)
let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
try
" parse the errors relative to self.jobdir
execute l:cd self.jobdir
execute l:cd fnameescape(self.jobdir)
call go#list#ParseFormat(l:listtype, self.errorformat, out, self.for)
let errors = go#list#Get(l:listtype)
finally
@ -295,11 +293,6 @@ function! go#job#Start(cmd, options)
let l:manualcd = 1
let dir = getcwd()
execute l:cd fnameescape(filedir)
elseif !(has("patch-8.0.0902") || has('nvim'))
let l:manualcd = 1
let l:dir = l:options.cwd
execute l:cd fnameescape(l:dir)
call remove(l:options, 'cwd')
endif
if has_key(l:options, '_start')

View File

@ -0,0 +1,53 @@
" don't spam the user when Vim is started in Vi compatibility mode
let s:cpo_save = &cpo
set cpo&vim
func! Test_JobDirWithSpaces()
if !go#util#has_job()
return
endif
try
let l:filename = 'job/dir has spaces/main.go'
let l:tmp = gotest#load_fixture(l:filename)
exe 'cd ' . fnameescape(l:tmp . '/src/job/dir has spaces')
" set the compiler type so that the errorformat option will be set
" correctly.
compiler go
let expected = [{'lnum': 4, 'bufnr': bufnr('%'), 'col': 2, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'undefined: notafunc'}]
" clear the quickfix lists
call setqflist([], 'r')
" go build discards any results when it compiles multiple packages. So we
" pass the `errors` package just as a placeholder with the current folder
" (indicated with '.').
let l:cmd = ['go', 'build', '.', 'errors']
let l:complete = go#promise#New(function('s:complete'), 10000, '')
call go#job#Spawn(l:cmd, {
\ 'for': 'GoBuild',
\ 'complete': l:complete.wrapper,
\ 'statustype': 'build'
\})
let l:out = l:complete.await()
let actual = getqflist()
call gotest#assert_quickfix(actual, l:expected)
finally
call delete(l:tmp, 'rf')
endtry
endfunc
func! s:complete(job, exit_code, messages)
return a:messages
endfunc
" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: sw=2 ts=2 et

View File

@ -11,7 +11,7 @@ function! go#lint#Gometa(bang, autosave, ...) abort
let l:metalinter = go#config#MetalinterCommand()
if l:metalinter == 'gometalinter' || l:metalinter == 'golangci-lint'
if l:metalinter == 'golangci-lint'
let cmd = s:metalintercmd(l:metalinter)
if empty(cmd)
return
@ -32,14 +32,7 @@ function! go#lint#Gometa(bang, autosave, ...) abort
" will be cleared
redraw
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"
if l:metalinter == "golangci-lint"
let goargs[0] = expand('%:p:h')
endif
endif
@ -52,18 +45,10 @@ function! go#lint#Gometa(bang, autosave, ...) abort
let cmd += goargs
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
" 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"
if go#util#has_job()
call s:lint_job({'cmd': cmd, 'statustype': l:metalinter, 'errformat': errformat}, a:bang, a:autosave)
@ -80,7 +65,7 @@ function! go#lint#Gometa(bang, autosave, ...) abort
if l:err == 0
call go#list#Clean(l:listtype)
echon "vim-go: " | echohl Function | echon "[metalinter] PASS" | echohl None
call go#util#EchoSuccess('[metalinter] PASS')
else
let l:winid = win_getid(winnr())
" Parse and populate our location list
@ -143,17 +128,17 @@ function! go#lint#Vet(bang, ...) abort
if a:0 == 0
let [l:out, l:err] = go#util#Exec(['go', 'vet', go#package#ImportPath()])
else
let [l:out, l:err] = go#util#ExecInDir(['go', 'tool', 'vet'] + a:000)
let [l:out, l:err] = go#util#Exec(['go', 'vet'] + a:000 + [go#package#ImportPath()])
endif
let l:listtype = go#list#Type("GoVet")
if l:err != 0
let l:winid = win_getid(winnr())
let errorformat = "%-Gexit status %\\d%\\+," . &errorformat
let l:errorformat = "%-Gexit status %\\d%\\+," . &errorformat
call go#list#ParseFormat(l:listtype, l:errorformat, out, "GoVet")
let errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(errors))
if !empty(errors) && !a:bang
let l:errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(l:errors))
if !empty(l:errors) && !a:bang
call go#list#JumpToFirst(l:listtype)
else
call win_gotoid(l:winid)
@ -232,6 +217,7 @@ function! s:lint_job(args, bang, autosave)
if a:autosave
let l:opts.for = "GoMetaLinterAutoSave"
" s:metalinterautosavecomplete is really only needed for golangci-lint
let l:opts.complete = funcref('s:metalinterautosavecomplete', [expand('%:p:t')])
endif
@ -245,9 +231,7 @@ 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"
if a:metalinter == "golangci-lint"
let l:cmd = s:golangcilintcmd(bin_path)
endif
endif
@ -255,19 +239,6 @@ function! s:metalintercmd(metalinter)
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"]
@ -287,10 +258,14 @@ function! s:metalinterautosavecomplete(filepath, job, exit_code, messages)
return
endif
let l:file = expand('%:p:t')
let l:idx = len(a:messages) - 1
while l:idx >= 0
if a:messages[l:idx] !~# '^' . a:filepath . ':'
" Go 1.13 changed how go vet output is formatted by prepending a leading
" 'vet :', so account for that, too. This function is really needed for
" gometalinter at all, so the check for Go 1.13's go vet output shouldn't
" be neeeded, but s:lint_job hooks this up even when the
" g:go_metalinter_command is golangci-lint.
if a:messages[l:idx] !~# '^' . a:filepath . ':' && a:messages[l:idx] !~# '^vet: \.[\\/]' . a:filepath . ':'
call remove(a:messages, l:idx)
endif
let l:idx -= 1

View File

@ -2,10 +2,6 @@
let s:cpo_save = &cpo
set cpo&vim
func! Test_Gometa() abort
call s:gometa('gometalinter')
endfunc
func! Test_GometaGolangciLint() abort
call s:gometa('golangci-lint')
endfunc
@ -21,7 +17,7 @@ func! s:gometa(metalinter) abort
\ ]
if a:metalinter == 'golangci-lint'
let expected = [
\ {'lnum': 5, 'bufnr': bufnr('%')+1, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exported function `MissingFooDoc` should have comment or be unexported (golint)'}
\ {'lnum': 5, 'bufnr': bufnr('%')+2, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exported function `MissingFooDoc` should have comment or be unexported (golint)'}
\ ]
endif
@ -46,10 +42,6 @@ func! s:gometa(metalinter) abort
endtry
endfunc
func! Test_GometaAutoSave() abort
call s:gometaautosave('gometalinter')
endfunc
func! Test_GometaAutoSaveGolangciLint() abort
call s:gometaautosave('golangci-lint')
endfunc
@ -122,6 +114,35 @@ func! Test_Vet() abort
endtry
endfunc
func! Test_Vet_compilererror() abort
let l:tmp = gotest#load_fixture('lint/src/vet/compilererror/compilererror.go')
try
let expected = [
\ {'lnum': 6, 'bufnr': bufnr('%'), 'col': 22, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': "missing ',' before newline in argument list (and 1 more errors)"}
\ ]
let winnr = winnr()
" clear the location lists
call setqflist([], 'r')
call go#lint#Vet(1)
let actual = getqflist()
let start = reltime()
while len(actual) == 0 && reltimefloat(reltime(start)) < 10
sleep 100m
let actual = getqflist()
endwhile
call gotest#assert_quickfix(actual, expected)
finally
call delete(l:tmp, 'rf')
endtry
endfunc
func! Test_Lint_GOPATH() abort
let RestoreGOPATH = go#util#SetEnv('GOPATH', fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint')

View File

@ -49,13 +49,10 @@ endfunction
function! go#list#Populate(listtype, items, title) abort
if a:listtype == "locationlist"
call setloclist(0, a:items, 'r')
" The last argument ({what}) is introduced with 7.4.2200:
" https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640
if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif
call setloclist(0, [], 'a', {'title': a:title})
else
call setqflist(a:items, 'r')
if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif
call setqflist([], 'a', {'title': a:title})
endif
endfunction
@ -80,10 +77,10 @@ endfunction
function! go#list#Parse(listtype, items, title) abort
if a:listtype == "locationlist"
lgetexpr a:items
if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif
call setloclist(0, [], 'a', {'title': a:title})
else
cgetexpr a:items
if has("patch-7.4.2200") | call setqflist([], 'a', {'title': a:title}) | endif
call setqflist([], 'a', {'title': a:title})
endif
endfunction

View File

@ -147,7 +147,10 @@ function! s:newlsp() abort
endfunction
function! l:lsp.handleNotification(req) dict abort
" TODO(bc): handle notifications (e.g. window/showMessage).
" TODO(bc): handle more notifications (e.g. window/showMessage).
if a:req.method == 'textDocument/publishDiagnostics'
call s:handleDiagnostics(a:req.params)
endif
endfunction
function! l:lsp.handleResponse(resp) dict abort
@ -296,6 +299,10 @@ function! s:newlsp() abort
endfunction
function! l:lsp.write(msg) dict abort
if empty(get(self, 'job', {}))
return
endif
let l:body = json_encode(a:msg)
let l:data = 'Content-Length: ' . strlen(l:body) . "\r\n\r\n" . l:body
@ -360,7 +367,7 @@ function! s:newlsp() abort
let l:bin_path = go#path#CheckBinPath("gopls")
if empty(l:bin_path)
return
return l:lsp
endif
let l:cmd = [l:bin_path]
@ -601,6 +608,114 @@ function! s:completionErrorHandler(next, error) abort dict
call call(a:next, [-1, []])
endfunction
" go#lsp#SameIDs calls gopls to get the references to the identifier at line
" and col in fname. handler should be a dictionary function that takes a list
" of strings in the form 'file:line:col: message'. handler will be attached to
" a dictionary that manages state (statuslines, sets the winid, etc.). handler
" should take three arguments: an exit_code, a JSON object encoded to a string
" that mimics guru's ouput for `what`, and third mode parameter that only
" exists for compatibility with the guru implementation of SameIDs.
" TODO(bc): refactor to not need the guru adapter.
function! go#lsp#SameIDs(showstatus, fname, line, col, handler) abort
call go#lsp#DidChange(a:fname)
let l:lsp = s:lspfactory.get()
let l:msg = go#lsp#message#References(a:fname, a:line, a:col)
if a:showstatus
let l:state = s:newHandlerState('same ids')
else
let l:state = s:newHandlerState('')
endif
let l:state.handleResult = funcref('s:sameIDsHandler', [function(a:handler, [], l:state)], l:state)
let l:state.error = funcref('s:noop')
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:sameIDsHandler(next, msg) abort dict
let l:furi = go#path#ToURI(expand('%:p'))
let l:result = {
\ 'sameids': [],
\ 'enclosing': [],
\ }
for l:loc in a:msg
if l:loc.uri !=# l:furi
continue
endif
if len(l:result.enclosing) == 0
let l:result.enclosing = [{
\ 'desc': 'identifier',
\ 'start': l:loc.range.start.character+1,
\ 'end': l:loc.range.end.character+1,
\ }]
endif
let l:result.sameids = add(l:result.sameids, printf('%s:%s:%s', go#path#FromURI(l:loc.uri), l:loc.range.start.line+1, l:loc.range.start.character+1))
endfor
call call(a:next, [0, json_encode(l:result), ''])
endfunction
" go#lsp#Referrers calls gopls to get the references to the identifier at line
" and col in fname. handler should be a dictionary function that takes a list
" of strings in the form 'file:line:col: message'. handler will be attached to
" a dictionary that manages state (statuslines, sets the winid, etc.). handler
" should take three arguments: an exit_code, a JSON object encoded to a string
" that mimics guru's ouput for `what`, and third mode parameter that only
" exists for compatibility with the guru implementation of SameIDs.
" TODO(bc): refactor to not need the guru adapter.
function! go#lsp#Referrers(fname, line, col, handler) abort
call go#lsp#DidChange(a:fname)
let l:lsp = s:lspfactory.get()
let l:msg = go#lsp#message#References(a:fname, a:line, a:col)
let l:state = s:newHandlerState('referrers')
let l:state.handleResult = funcref('s:referencesHandler', [function(a:handler, [], l:state)], l:state)
let l:state.error = funcref('s:noop')
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:referencesHandler(next, msg) abort dict
let l:result = []
call sort(a:msg, funcref('s:compareLocations'))
for l:loc in a:msg
let l:fname = go#path#FromURI(l:loc.uri)
let l:line = l:loc.range.start.line+1
let l:bufnr = bufnr(l:fname)
let l:bufinfo = getbufinfo(l:fname)
try
if l:bufnr == -1 || len(l:bufinfo) == 0 || l:bufinfo[0].loaded == 0
let l:filecontents = readfile(l:fname, '', l:line)
else
let l:filecontents = getbufline(l:fname, l:line)
endif
if len(l:filecontents) == 0
continue
endif
let l:content = l:filecontents[-1]
catch
call go#util#EchoError(printf('%s (line %s): %s at %s', l:fname, l:line, v:exception, v:throwpoint))
endtry
let l:item = printf('%s:%s:%s: %s', go#path#FromURI(l:loc.uri), l:line, go#lsp#lsp#PositionOf(l:content, l:loc.range.start.character), l:content)
let l:result = add(l:result, l:item)
endfor
call call(a:next, [0, l:result, ''])
endfunction
function! go#lsp#Hover(fname, line, col, handler) abort
call go#lsp#DidChange(a:fname)
@ -613,15 +728,19 @@ function! go#lsp#Hover(fname, line, col, handler) abort
endfunction
function! s:hoverHandler(next, msg) abort dict
let l:content = split(a:msg.contents.value, '; ')
if len(l:content) > 1
let l:curly = stridx(l:content[0], '{')
let l:content = extend([l:content[0][0:l:curly]], map(extend([l:content[0][l:curly+1:]], l:content[1:]), '"\t" . v:val'))
let l:content[len(l:content)-1] = '}'
endif
try
let l:content = split(a:msg.contents.value, '; ')
if len(l:content) > 1
let l:curly = stridx(l:content[0], '{')
let l:content = extend([l:content[0][0:l:curly]], map(extend([l:content[0][l:curly+1:]], l:content[1:]), '"\t" . v:val'))
let l:content[len(l:content)-1] = '}'
endif
let l:args = [l:content]
call call(a:next, l:args)
let l:args = [l:content]
call call(a:next, l:args)
catch
" TODO(bc): log the message and/or show an error message.
endtry
endfunction
function! go#lsp#Info(showstatus)
@ -746,13 +865,17 @@ function! go#lsp#CleanWorkspaces() abort
let l:missing = []
for l:dir in l:lsp.workspaceDirectories
if !isdirectory(l:dir)
let l:dir = add(l:missing, l:dir)
let l:missing = add(l:missing, l:dir)
call remove(l:lsp.workspaceDirectories, l:i)
continue
endif
let l:i += 1
endfor
if len(l:missing) == 0
return 0
endif
let l:state = s:newHandlerState('')
let l:state.handleResult = funcref('s:noop')
let l:msg = go#lsp#message#ChangeWorkspaceFolders([], l:missing)
@ -789,14 +912,26 @@ function! go#lsp#DebugBrowser() abort
call go#util#OpenBrowser(printf('http://localhost:%d', l:port))
endfunction
function! go#lsp#Exit() abort
call s:exit(0)
endfunction
function! go#lsp#Restart() abort
call s:exit(1)
endfunction
function! s:exit(restart) abort
if !go#util#has_job() || len(s:lspfactory) == 0 || !has_key(s:lspfactory, 'current')
return
endif
let l:lsp = s:lspfactory.get()
let l:lsp.restarting = 1
" reset the factory so that future requests don't use the same instance of
" gopls.
call s:lspfactory.reset()
let l:lsp.restarting = a:restart
let l:state = s:newHandlerState('exit')
@ -810,7 +945,7 @@ function! go#lsp#Restart() abort
return l:retval
endfunction
function! s:debug(event, data) abort
function! s:debugasync(event, data, timer) abort
if !go#util#HasDebug('lsp')
return
endif
@ -842,6 +977,84 @@ function! s:debug(event, data) abort
endtry
endfunction
function! s:debug(event, data, ...) abort
call timer_start(10, function('s:debugasync', [a:event, a:data]))
endfunction
function! s:compareLocations(left, right) abort
if a:left.uri < a:right.uri
return -1
endif
if a:left.uri == a:right.uri && a:left.range.start.line < a:right.range.start.line
return -1
endif
if a:left.uri == a:right.uri && a:left.range.start.line == a:right.range.start.line && a:left.range.start.character < a:right.range.start.character
return -1
endif
if a:left.uri == a:right.uri && a:left.range.start.line == a:right.range.start.line && a:left.range.start.character == a:right.range.start.character
return 0
endif
return 1
endfunction
function! s:handleDiagnostics(data) abort
if !exists("*matchaddpos")
return 0
endif
try
let l:fname = go#path#FromURI(a:data.uri)
if bufnr(l:fname) == bufnr('')
let l:errorMatches = []
let l:warningMatches = []
for l:diag in a:data.diagnostics
if !(l:diag.severity == 1 || l:diag.severity == 2)
continue
endif
let l:range = l:diag.range
if l:range.start.line != l:range.end.line
continue
endif
let l:line = l:range.start.line + 1
let l:col = go#lsp#lsp#PositionOf(getline(l:line), l:range.start.character)
let l:lastcol = go#lsp#lsp#PositionOf(getline(l:line), l:range.end.character)
let l:pos = [l:line, l:col, l:lastcol - l:col + 1]
if l:diag.severity == 1
let l:errorMatches = add(l:errorMatches, l:pos)
elseif l:diag.severity == 2
let l:warningMatches = add(l:warningMatches, l:pos)
endif
endfor
if hlexists('goDiagnosticError')
" clear the old matches just before adding the new ones to keep flicker
" to a minimum.
call go#util#ClearGroupFromMatches('goDiagnosticError')
if go#config#HighlightDiagnosticErrors()
call matchaddpos('goDiagnosticError', l:errorMatches)
endif
endif
if hlexists('goDiagnosticError')
" clear the old matches just before adding the new ones to keep flicker
" to a minimum.
call go#util#ClearGroupFromMatches('goDiagnosticWarning')
if go#config#HighlightDiagnosticWarnings()
call matchaddpos('goDiagnosticWarning', l:warningMatches)
endif
endif
endif
catch
call go#util#EchoError(v:exception)
endtry
endfunction
" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save

View File

@ -136,6 +136,22 @@ function! go#lsp#message#Completion(file, line, col) abort
\ }
endfunction
function! go#lsp#message#References(file, line, col) abort
return {
\ 'notification': 0,
\ 'method': 'textDocument/references',
\ 'params': {
\ 'textDocument': {
\ 'uri': go#path#ToURI(a:file)
\ },
\ 'position': s:position(a:line, a:col),
\ 'context': {
\ 'includeDeclaration': v:true,
\ },
\ }
\ }
endfunction
function! go#lsp#message#Hover(file, line, col) abort
return {
\ 'notification': 0,
@ -174,6 +190,10 @@ function! go#lsp#message#ConfigurationResult(items) abort
let l:config = {
\ 'buildFlags': [],
\ 'hoverKind': 'NoDocumentation',
\ 'deepCompletion': go#config#GoplsDeepCompletion() ? v:true : v:false,
\ 'fuzzyMatching': go#config#GoplsFuzzyMatching() ? v:true : v:false,
\ 'completeUnimported': go#config#GoplsCompleteUnimported() ? v:true : v:false,
\ 'usePlaceholders': go#config#GoplsUsePlaceholders() ? v:true : v:false,
\ }
let l:buildtags = go#config#BuildTags()
if buildtags isnot ''

View File

@ -37,7 +37,7 @@ function! s:getinfo(str, name)
let l:actual = go#lsp#GetInfo()
call assert_equal(l:expected, l:actual)
finally
"call delete(l:tmp, 'rf')
call delete(l:tmp, 'rf')
unlet g:go_info_mode
endtry
endfunction

View File

@ -83,18 +83,11 @@ function! go#mod#update_file(source, target)
let l:listtype = go#list#Type("GoModFmt")
" the title information was introduced with 7.4-2200
" https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640
if has('patch-7.4.2200')
" clean up previous list
if l:listtype == "quickfix"
let l:list_title = getqflist({'title': 1})
else
let l:list_title = getloclist(0, {'title': 1})
endif
" clean up previous list
if l:listtype == "quickfix"
let l:list_title = getqflist({'title': 1})
else
" can't check the title, so assume that the list was for go fmt.
let l:list_title = {'title': 'Format'}
let l:list_title = getloclist(0, {'title': 1})
endif
if has_key(l:list_title, "title") && l:list_title['title'] == "Format"

View File

@ -39,7 +39,7 @@ function! s:paths() abort
if executable('go')
let s:goroot = go#util#env("goroot")
if go#util#ShellError() != 0
echomsg '''go env GOROOT'' failed'
call go#util#EchoError('`go env GOROOT` failed')
endif
else
let s:goroot = $GOROOT

View File

@ -28,11 +28,11 @@ function! go#path#GoPath(...) abort
let s:initial_go_path = ""
endif
echon "vim-go: " | echohl Function | echon "GOPATH restored to ". $GOPATH | echohl None
call go#util#EchoInfo("GOPATH restored to ". $GOPATH)
return
endif
echon "vim-go: " | echohl Function | echon "GOPATH changed to ". a:1 | echohl None
call go#util#EchoInfo("GOPATH changed to ". a:1)
let s:initial_go_path = $GOPATH
let $GOPATH = a:1
endfunction

View File

@ -4,7 +4,7 @@ set cpo&vim
function! go#play#Share(count, line1, line2) abort
if !executable('curl')
echohl ErrorMsg | echomsg "vim-go: require 'curl' command" | echohl None
call go#util#EchoError('cannot share: curl cannot be found')
return
endif
@ -20,8 +20,7 @@ function! go#play#Share(count, line1, line2) abort
call delete(share_file)
if l:err != 0
echom 'A error has occurred. Run this command to see what the problem is:'
echom go#util#Shelljoin(l:cmd)
call go#util#EchoError(['A error has occurred. Run this command to see what the problem is:', go#util#Shelljoin(l:cmd)])
return
endif
@ -38,7 +37,7 @@ function! go#play#Share(count, line1, line2) abort
call go#util#OpenBrowser(url)
endif
echo "vim-go: snippet uploaded: ".url
call go#util#EchoInfo('snippet uploaded: ' . url)
endfunction

View File

@ -20,8 +20,10 @@ function! go#rename#Rename(bang, ...) abort
let to_identifier = a:1
endif
let l:bin = go#config#GorenameCommand()
" return with a warning if the bin doesn't exist
let bin_path = go#path#CheckBinPath(go#config#GorenameBin())
let bin_path = go#path#CheckBinPath(l:bin)
if empty(bin_path)
return
endif
@ -29,7 +31,18 @@ function! go#rename#Rename(bang, ...) abort
let fname = expand('%:p')
let pos = go#util#OffsetCursor()
let offset = printf('%s:#%d', fname, pos)
let cmd = [bin_path, "-offset", offset, "-to", to_identifier, '-tags', go#config#BuildTags()]
let args = []
if l:bin == 'gorename'
let l:args = extend(l:args, ['-tags', go#config#BuildTags(), '-offset', offset, '-to', to_identifier])
elseif l:bin == 'gopls'
" TODO(bc): use -tags when gopls supports it
let l:args = extend(l:args, ['rename', '-w', l:offset, to_identifier])
else
call go#util#EchoWarning('unexpected rename command')
endif
let l:cmd = extend([l:bin], l:args)
if go#util#has_job()
call s:rename_job({

View File

@ -96,6 +96,9 @@ function! s:on_stdout(job_id, data, event) dict abort
endfunction
function! s:on_exit(job_id, exit_status, event) dict abort
let l:winid = win_getid(winnr())
call win_gotoid(self.winid)
" change to directory where test were run. if we do not do this
" the quickfix items will have the incorrect paths.
" see: https://github.com/fatih/vim-go/issues/2400
@ -103,12 +106,11 @@ function! s:on_exit(job_id, exit_status, event) dict abort
let l:dir = getcwd()
execute l:cd . fnameescape(expand("%:p:h"))
let l:winid = win_getid(winnr())
call win_gotoid(self.winid)
let l:listtype = go#list#Type("_term")
if a:exit_status == 0
call go#list#Clean(l:listtype)
execute l:cd l:dir
call win_gotoid(l:winid)
return
endif
@ -132,6 +134,7 @@ function! s:on_exit(job_id, exit_status, event) dict abort
if empty(l:errors)
call go#util#EchoError( '[' . l:title . '] ' . "FAIL")
execute l:cd l:dir
call win_gotoid(l:winid)
return
endif
@ -143,6 +146,7 @@ function! s:on_exit(job_id, exit_status, event) dict abort
endif
if self.bang
execute l:cd l:dir
call win_gotoid(l:winid)
return
endif

View File

@ -0,0 +1,5 @@
package config
func Example() {
foo()
}

View File

@ -0,0 +1,8 @@
// +build constrained
package config
// foo is constrained and this comment exists to make the line numbers different than foo.go
func foo() {
println("foo")
}

View File

@ -0,0 +1,7 @@
// +build !constrained
package config
func foo() {
println("foo")
}

View File

@ -0,0 +1,3 @@
module config
go 1.13

View File

@ -0,0 +1,6 @@
package main
func main() {
notafunc()
println("vim-go")
}

View File

@ -0,0 +1,7 @@
package main
import "fmt"
func main() {
fmt.Println("vim-go"
}

View File

@ -62,18 +62,7 @@ endfunction
" The (optional) first parameter can be added to indicate the 'cwd' or 'env'
" parameters will be used, which wasn't added until a later version.
function! go#util#has_job(...) abort
if has('nvim')
return 1
endif
" cwd and env parameters to job_start was added in this version.
if a:0 > 0 && a:1 is 1
return has('job') && has("patch-8.0.0902")
endif
" job was introduced in 7.4.xxx however there are multiple bug fixes and one
" of the latest is 8.0.0087 which is required for a stable async API.
return has('job') && has("patch-8.0.0087")
return has('job') || has('nvim')
endfunction
let s:env_cache = {}
@ -556,15 +545,47 @@ function! go#util#SetEnv(name, value) abort
call execute('let $' . a:name . " = '" . a:value . "'")
if l:remove
function! s:remove(name) abort
call execute('unlet $' . a:name)
endfunction
return function('s:remove', [a:name], l:state)
return function('s:unset', [a:name], l:state)
endif
return function('go#util#SetEnv', [a:name, l:oldvalue], l:state)
endfunction
function! go#util#ClearGroupFromMatches(group) abort
if !exists("*matchaddpos")
return 0
endif
let l:cleared = 0
let m = getmatches()
for item in m
if item['group'] == a:group
call matchdelete(item['id'])
let l:cleared = 1
endif
endfor
return l:cleared
endfunction
function! s:unset(name) abort
try
" unlet $VAR was introducted in Vim 8.0.1832, which is newer than the
" minimal version that vim-go supports. Set the environment variable to
" the empty string in that case. It's not perfect, but it will work fine
" for most things, and is really the best alternative that's available.
if !has('patch-8.0.1832')
call go#util#SetEnv(a:name, '')
return
endif
call execute('unlet $' . a:name)
catch
call go#util#EchoError(printf('could not unset $%s: %s', a:name, v:exception))
endtry
endfunction
function! s:noop(...) abort dict
endfunction