mirror of
https://github.com/amix/vimrc
synced 2025-06-30 20:05:01 +08:00
Updated plugins
This commit is contained in:
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
86
sources_non_forked/vim-go/autoload/go/config_test.vim
Normal file
86
sources_non_forked/vim-go/autoload/go/config_test.vim
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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!\\!/!')
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -62,7 +62,7 @@ func! Test_fillstruct_two_line() abort
|
||||
\ '\tAddress: "",',
|
||||
\ '}) }'])
|
||||
finally
|
||||
"call delete(l:tmp, 'rf')
|
||||
call delete(l:tmp, 'rf')
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
53
sources_non_forked/vim-go/autoload/go/job_test.vim
Normal file
53
sources_non_forked/vim-go/autoload/go/job_test.vim
Normal 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
|
@ -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
|
||||
|
@ -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')
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ''
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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({
|
||||
|
@ -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
|
||||
|
@ -0,0 +1,5 @@
|
||||
package config
|
||||
|
||||
func Example() {
|
||||
foo()
|
||||
}
|
@ -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")
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// +build !constrained
|
||||
|
||||
package config
|
||||
|
||||
func foo() {
|
||||
println("foo")
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
module config
|
||||
|
||||
go 1.13
|
@ -0,0 +1,6 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
notafunc()
|
||||
println("vim-go")
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("vim-go"
|
||||
}
|
@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user