1
0
mirror of https://github.com/amix/vimrc synced 2025-07-04 15:04:59 +08:00

Update plugins using update_plugins.py

This commit is contained in:
Geezus
2019-07-08 11:44:45 -05:00
parent a25315c274
commit 0502b849ed
115 changed files with 3723 additions and 1662 deletions

View File

@ -1,5 +1,9 @@
## unplanned
BACKWARDS INCOMPATABILITIES:
* `g:go_metalinter_disabled` has been removed.
[[GH-2375]](https://github.com/fatih/vim-go/pull/2117)
IMPROVEMENTS:
* Add a new option, `g:go_code_completion_enabled`, to control whether omnifunc
is set.
@ -14,11 +18,32 @@ IMPROVEMENTS:
[[GH-2289]](https://github.com/fatih/vim-go/pull/2289)
* Improve the user experience when using null modules.
[[GH-2300]](https://github.com/fatih/vim-go/pull/2300)
* Add option, `g:go_null_module_warning` to silence the warning when trying to
use gopls with a null module.
* Add a new option, `g:go_null_module_warning` to silence the warning when
trying to use gopls with a null module.
[[GH-2309]](https://github.com/fatih/vim-go/pull/2309)
* Modify `:GoReportGitHubIssue` to include vim-go configuration values
[[GH-2323]](https://github.com/fatih/vim-go/pull/2323)
* Respect `g:go_info_mode='gopls'` in go#complete#GetInfo.
[[GH-2313]](https://github.com/fatih/vim-go/pull/2313)
* Allow `:GoLint`, `:GoErrCheck`, and `:GoDebug` to work in null modules.
[[GH-2335]](https://github.com/fatih/vim-go/pull/2335)
* Change default value for `g:go_info_mode` and `g:go_def_mode` to `'gopls'`.
[[GH-2329]](https://github.com/fatih/vim-go/pull/2329)
* Add a new option, `g:go_doc_popup_window` to optionally use a popup window
for godoc in Vim 8.1.1513 and later.
[[GH-2347]](https://github.com/fatih/vim-go/pull/2347)
* Check for null modules in the background when initializing gopls.
[[GH-2351]](https://github.com/fatih/vim-go/pull/2351)
* Add `:GoAddWorkspace` function to support multiple workspaces with gopls.
[[GH-2356]](https://github.com/fatih/vim-go/pull/2356)
* Rename `errn` Ultisnip snippet to `err`.
[[GH-2358]](https://github.com/fatih/vim-go/pull/2358)
* Install gopls from its stable package.
[[GH-2360]](https://github.com/fatih/vim-go/pull/2360)
* Disambiguate progress message when initializing gopls.
[[GH-2369]](https://github.com/fatih/vim-go/pull/2369)
* Remove warnings and lsp short-circuiting when using a null module.
[[GH-2371]](https://github.com/fatih/vim-go/pull/2371)
BUG FIXES:
* display info about function and function types whose parameters are
@ -53,6 +78,16 @@ BUG FIXES:
* Do not jump back to the originating window when jumping to definitions with
`g:go_def_mode='gopls'`.
[[GH-2327]](https://github.com/fatih/vim-go/pull/2327)
* Fix getting information about a valid identifier for which gopls returns no
information (e.g. calling `:GoInfo` on a package identifier).
[[GH-2339]](https://github.com/fatih/vim-go/pull/2339)
* Fix tab completion of package names on the cmdline in null modules.
[[GH-2342]](https://github.com/fatih/vim-go/pull/2342)
* Display identifier info correctly when the identifier has no godoc.
[[GH-2373]](https://github.com/fatih/vim-go/pull/2373)
* Fix false positives when saving a buffer and `g:go_metalinter_command` is
`golangci-lint`.
[[GH-2367]](https://github.com/fatih/vim-go/pull/2367)
## 1.20 - (April 22, 2019)

View File

@ -79,7 +79,12 @@ endfunction
" go#complete#GoInfo returns the description of the identifier under the
" cursor.
function! go#complete#GetInfo() abort
return s:sync_info(0)
let l:mode = go#config#InfoMode()
if l:mode == 'gopls' && go#util#has_job()
return go#lsp#GetInfo()
else
return s:sync_info(0)
endif
endfunction
function! go#complete#Info(showstatus) abort

View File

@ -2,23 +2,33 @@
let s:cpo_save = &cpo
set cpo&vim
func! Test_GetInfo()
func! Test_GetInfo_gocode()
let g:go_info_mode = 'gocode'
call s:getinfo()
unlet g:go_info_mode
endfunction
func! Test_GetInfo_guru()
let g:go_info_mode = 'guru'
call s:getinfo()
unlet g:go_info_mode
endfunction
func! Test_GetInfo_gopls()
let g:go_info_mode = 'gopls'
call s:getinfo()
unlet g:go_info_mode
endfunction
func! s:getinfo()
let l:filename = 'complete/complete.go'
let l:tmp = gotest#load_fixture(l:filename)
call cursor(8, 3)
let g:go_info_mode = 'gocode'
let expected = 'func Example(s string)'
let actual = go#complete#GetInfo()
call assert_equal(expected, actual)
let g:go_info_mode = 'guru'
call go#config#InfoMode()
let actual = go#complete#GetInfo()
call assert_equal(expected, actual)
unlet g:go_info_mode
endfunction
" restore Vi compatibility settings

View File

@ -14,10 +14,6 @@ function! go#config#VersionWarning() abort
return get(g:, 'go_version_warning', 1)
endfunction
function! go#config#NullModuleWarning() abort
return get(g:, 'go_null_module_warning', 1)
endfunction
function! go#config#BuildTags() abort
return get(g:, 'go_build_tags', '')
endfunction
@ -118,7 +114,7 @@ function! go#config#ListAutoclose() abort
endfunction
function! go#config#InfoMode() abort
return get(g:, 'go_info_mode', 'gocode')
return get(g:, 'go_info_mode', 'gopls')
endfunction
function! go#config#GuruScope() abort
@ -178,12 +174,15 @@ function! go#config#DocUrl() abort
return godoc_url
endfunction
function! go#config#DocPopupWindow() abort
return get(g:, 'go_doc_popup_window', 0)
endfunction
function! go#config#DefReuseBuffer() abort
return get(g:, 'go_def_reuse_buffer', 0)
endfunction
function! go#config#DefMode() abort
return get(g:, 'go_def_mode', 'guru')
return get(g:, 'go_def_mode', 'gopls')
endfunction
function! go#config#DeclsIncludes() abort
@ -272,10 +271,6 @@ function! go#config#MetalinterEnabled() abort
return get(g:, "go_metalinter_enabled", default_enabled)
endfunction
function! go#config#MetalinterDisabled() abort
return get(g:, "go_metalinter_disabled", [])
endfunction
function! go#config#GolintBin() abort
return get(g:, "go_golint_bin", "golint")
endfunction

View File

@ -595,10 +595,23 @@ function! go#debug#Start(is_test, ...) abort
" append the package when it's given.
if len(a:000) > 0
let l:pkgname = go#package#FromPath(a:1)
if l:pkgname is -1
call go#util#EchoError('could not determine package name')
return
let l:pkgname = a:1
if l:pkgname[0] == '.'
let l:pkgabspath = fnamemodify(l:pkgname, ':p')
let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let l:dir = getcwd()
execute l:cd fnameescape(expand('%:p:h'))
try
let l:pkgname = go#package#FromPath(l:pkgabspath)
if type(l:pkgname) == type(0)
call go#util#EchoError('could not determine package name')
return
endif
finally
execute l:cd fnameescape(l:dir)
endtry
endif
let l:cmd += [l:pkgname]

View File

@ -10,6 +10,10 @@ function! Test_GoDebugStart_RelativePackage() abort
call s:debug('./debug/debugmain')
endfunction
function! Test_GoDebugStart_RelativePackage_NullModule() abort
call s:debug('./debug/debugmain', 1)
endfunction
function! Test_GoDebugStart_Package() abort
call s:debug('debug/debugmain')
endfunction
@ -52,14 +56,22 @@ function! Test_GoDebugStart_Errors() abort
endtry
endfunction
" s:debug takes 2 optional arguments. The first is a package to debug. The
" second is a flag to indicate whether to reset GOPATH after
" gotest#load_fixture is called in order to test behavior outside of GOPATH.
function! s:debug(...) abort
if !go#util#has_job()
return
endif
try
let $oldgopath = $GOPATH
let l:tmp = gotest#load_fixture('debug/debugmain/debugmain.go')
if a:0 > 1 && a:2 == 1
let $GOPATH = $oldgopath
endif
call go#debug#Breakpoint(6)
call assert_false(exists(':GoDebugStop'))

View File

@ -50,8 +50,16 @@ func! Test_Jump_leaves_lists() abort
let l:bufnr = bufnr('%')
call cursor(6, 7)
if !go#util#has_job()
let g:go_def_mode='godef'
endif
call go#def#Jump('', 0)
if !go#util#has_job()
unlet g:go_def_mode
endif
let start = reltime()
while bufnr('%') == l:bufnr && reltimefloat(reltime(start)) < 10
sleep 100m

View File

@ -76,6 +76,18 @@ function! go#doc#Open(newmode, mode, ...) abort
endfunction
function! s:GodocView(newposition, position, content) abort
" popup window
if go#config#DocPopupWindow() && has("patch-8.1.1513")
call popup_clear()
call popup_atcursor(split(a:content, '\n'), {
\ 'padding': [1, 1, 1, 1],
\ 'borderchars': ['-','|','-','|','+','+','+','+'],
\ "border": [1, 1, 1, 1],
\ })
return
endif
" reuse existing buffer window if it exists otherwise create a new one
let is_visible = bufexists(s:buf_nr) && bufwinnr(s:buf_nr) != -1
if !bufexists(s:buf_nr)

View File

@ -22,10 +22,6 @@ function! go#lint#Gometa(bang, autosave, ...) abort
for linter in linters
let cmd += ["--enable=".linter]
endfor
for linter in go#config#MetalinterDisabled()
let cmd += ["--disable=".linter]
endfor
else
" the user wants something else, let us use it.
let cmd = split(go#config#MetalinterCommand(), " ")
@ -44,7 +40,7 @@ function! go#lint#Gometa(bang, autosave, ...) abort
endif
let cmd += include
elseif l:metalinter == "golangci-lint"
let goargs[0] = expand('%:p')
let goargs[0] = expand('%:p:h')
endif
endif
@ -88,7 +84,13 @@ function! go#lint#Gometa(bang, autosave, ...) abort
else
let l:winid = win_getid(winnr())
" Parse and populate our location list
call go#list#ParseFormat(l:listtype, errformat, split(out, "\n"), 'GoMetaLinter')
let l:messages = split(out, "\n")
if a:autosave
call s:metalinterautosavecomplete(fnamemodify(expand('%:p'), ":."), 0, 1, l:messages)
endif
call go#list#ParseFormat(l:listtype, errformat, l:messages, 'GoMetaLinter')
let errors = go#list#Get(l:listtype)
call go#list#Window(l:listtype, len(errors))
@ -101,10 +103,11 @@ function! go#lint#Gometa(bang, autosave, ...) abort
endif
endfunction
" Golint calls 'golint'.
" Golint calls 'golint' on the current directory. Any warnings are populated in
" the location list
function! go#lint#Golint(bang, ...) abort
if a:0 == 0
let [l:out, l:err] = go#util#ExecInDir([go#config#GolintBin(), '.'])
let [l:out, l:err] = go#util#Exec([go#config#GolintBin(), expand('%:p:h')])
else
let [l:out, l:err] = go#util#Exec([go#config#GolintBin()] + a:000)
endif
@ -140,7 +143,7 @@ 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#Exec(['go', 'tool', 'vet'] + a:000)
let [l:out, l:err] = go#util#ExecInDir(['go', 'tool', 'vet'] + a:000)
endif
let l:listtype = go#list#Type("GoVet")
@ -229,6 +232,7 @@ function! s:lint_job(args, bang, autosave)
if a:autosave
let l:opts.for = "GoMetaLinterAutoSave"
let l:opts.complete = funcref('s:metalinterautosavecomplete', [expand('%:p:t')])
endif
" autowrite is not enabled for jobs
@ -278,6 +282,21 @@ function! s:golangcilintcmd(bin_path)
return cmd
endfunction
function! s:metalinterautosavecomplete(filepath, job, exit_code, messages)
if len(a:messages) == 0
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 . ':'
call remove(a:messages, l:idx)
endif
let l:idx -= 1
endwhile
endfunction
" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save

View File

@ -3,7 +3,7 @@ let s:cpo_save = &cpo
set cpo&vim
func! Test_Gometa() abort
call s:gometa('gometaliner')
call s:gometa('gometalinter')
endfunc
func! Test_GometaGolangciLint() abort
@ -11,14 +11,19 @@ func! Test_GometaGolangciLint() abort
endfunc
func! s:gometa(metalinter) abort
let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint'
let RestoreGOPATH = go#util#SetEnv('GOPATH', fnamemodify(getcwd(), ':p') . 'test-fixtures/lint')
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
try
let g:go_metalinter_comand = a:metalinter
let g:go_metalinter_command = a:metalinter
let expected = [
\ {'lnum': 5, 'bufnr': bufnr('%')+1, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
\ ]
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)'}
\ ]
endif
" clear the quickfix lists
call setqflist([], 'r')
@ -36,48 +41,11 @@ func! s:gometa(metalinter) abort
call gotest#assert_quickfix(actual, expected)
finally
call call(RestoreGOPATH, [])
unlet g:go_metalinter_enabled
endtry
endfunc
func! Test_GometaWithDisabled() abort
call s:gometawithdisabled('gometalinter')
endfunc
func! Test_GometaWithDisabledGolangciLint() abort
call s:gometawithdisabled('golangci-lint')
endfunc
func! s:gometawithdisabled(metalinter) abort
let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint'
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
try
let g:go_metalinter_comand = a:metalinter
let expected = [
\ {'lnum': 5, 'bufnr': bufnr('%')+1, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingFooDoc should have comment or be unexported (golint)'}
\ ]
" clear the quickfix lists
call setqflist([], 'r')
let g:go_metalinter_disabled = ['vet']
call go#lint#Gometa(0, 0, $GOPATH . '/src/foo')
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
unlet g:go_metalinter_disabled
endtry
endfunc
func! Test_GometaAutoSave() abort
call s:gometaautosave('gometalinter')
endfunc
@ -87,14 +55,19 @@ func! Test_GometaAutoSaveGolangciLint() abort
endfunc
func! s:gometaautosave(metalinter) abort
let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint'
let RestoreGOPATH = go#util#SetEnv('GOPATH', fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint')
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
try
let g:go_metalinter_comand = a:metalinter
let g:go_metalinter_command = a:metalinter
let expected = [
\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'w', 'pattern': '', 'text': 'exported function MissingDoc should have comment or be unexported (golint)'}
\ ]
if a:metalinter == 'golangci-lint'
let expected = [
\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exported function `MissingDoc` should have comment or be unexported (golint)'}
\ ]
endif
let winnr = winnr()
@ -114,12 +87,13 @@ func! s:gometaautosave(metalinter) abort
call gotest#assert_quickfix(actual, expected)
finally
call call(RestoreGOPATH, [])
unlet g:go_metalinter_autosave_enabled
endtry
endfunc
func! Test_Vet() abort
let $GOPATH = fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint'
let RestoreGOPATH = go#util#SetEnv('GOPATH', fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint')
silent exe 'e ' . $GOPATH . '/src/vet/vet.go'
compiler go
@ -142,6 +116,63 @@ func! Test_Vet() abort
let actual = getqflist()
endwhile
call gotest#assert_quickfix(actual, expected)
call call(RestoreGOPATH, [])
endfunc
func! Test_Lint_GOPATH() abort
let RestoreGOPATH = go#util#SetEnv('GOPATH', fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint')
silent exe 'e ' . $GOPATH . '/src/lint/lint.go'
compiler go
let expected = [
\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exported function MissingDoc should have comment or be unexported'},
\ {'lnum': 5, 'bufnr': 6, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exported function AlsoMissingDoc should have comment or be unexported'}
\ ]
let winnr = winnr()
" clear the location lists
call setqflist([], 'r')
call go#lint#Golint(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)
call call(RestoreGOPATH, [])
endfunc
func! Test_Lint_NullModule() abort
silent exe 'e ' . fnameescape(fnamemodify(getcwd(), ':p')) . 'test-fixtures/lint/src/lint/lint.go'
compiler go
let expected = [
\ {'lnum': 5, 'bufnr': bufnr('%'), 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exported function MissingDoc should have comment or be unexported'},
\ {'lnum': 5, 'bufnr': 6, 'col': 1, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'pattern': '', 'text': 'exported function AlsoMissingDoc should have comment or be unexported'}
\ ]
let winnr = winnr()
" clear the location lists
call setqflist([], 'r')
call go#lint#Golint(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)
endfunc

View File

@ -26,7 +26,6 @@ function! s:newlsp() abort
if has('nvim')
set shortmess-=F
endif
" TODO(bc): start the server in the background using a shell that waits for the right output before returning.
call go#util#EchoWarning('Features that rely on gopls will not work without either Vim 8.0.0087 or newer with +job or Neovim')
" Sleep one second to make sure people see the message. Otherwise it is
" often immediately overwritten by an async message.
@ -55,6 +54,7 @@ function! s:newlsp() abort
\ 'last_request_id': 0,
\ 'buf': '',
\ 'handlers': {},
\ 'workspaceDirectories': [],
\ }
function! l:lsp.readMessage(data) dict abort
@ -83,19 +83,17 @@ function! s:newlsp() abort
endif
" get the start of the rest
let l:rest_start_idx = l:body_start_idx + str2nr(l:length_match[1])
let l:next_start_idx = l:body_start_idx + str2nr(l:length_match[1])
if len(l:rest) < l:rest_start_idx
if len(l:rest) < l:next_start_idx
" incomplete response body
break
endif
if go#util#HasDebug('lsp')
let g:go_lsp_log = add(go#config#LspLog(), "<-\n" . l:rest[:l:rest_start_idx - 1])
endif
call s:debug('received', l:rest[:l:next_start_idx - 1])
let l:body = l:rest[l:body_start_idx : l:rest_start_idx - 1]
let l:rest = l:rest[l:rest_start_idx :]
let l:body = l:rest[l:body_start_idx : l:next_start_idx - 1]
let l:rest = l:rest[l:next_start_idx :]
try
" add the json body to the list.
@ -113,53 +111,77 @@ function! s:newlsp() abort
function! l:lsp.handleMessage(ch, data) dict abort
let self.buf .= a:data
let [self.buf, l:responses] = self.readMessage(self.buf)
let [self.buf, l:messages] = self.readMessage(self.buf)
" TODO(bc): handle notifications (e.g. window/showMessage).
for l:response in l:responses
if has_key(l:response, 'id') && has_key(self.handlers, l:response.id)
try
let l:handler = self.handlers[l:response.id]
let l:winid = win_getid(winnr())
" Always set the active window to the window that was active when
" the request was sent. Among other things, this makes sure that
" the correct window's location list will be populated when the
" list type is 'location' and the user has moved windows since
" sending the reques.
call win_gotoid(l:handler.winid)
if has_key(l:response, 'error')
call l:handler.requestComplete(0)
if has_key(l:handler, 'error')
call call(l:handler.error, [l:response.error.message])
else
call go#util#EchoError(l:response.error.message)
endif
call win_gotoid(l:winid)
return
endif
call l:handler.requestComplete(1)
let l:winidBeforeHandler = l:handler.winid
call call(l:handler.handleResult, [l:response.result])
" change the window back to the window that was active when
" starting to handle the response _only_ if the handler didn't
" update the winid, so that handlers can set the winid if needed
" (e.g. :GoDef).
if l:handler.winid == l:winidBeforeHandler
call win_gotoid(l:winid)
endif
finally
call remove(self.handlers, l:response.id)
endtry
for l:message in l:messages
if has_key(l:message, 'method')
if has_key(l:message, 'id')
call self.handleRequest(l:message)
else
call self.handleNotification(l:message)
endif
elseif has_key(l:message, 'result') || has_key(l:message, 'error')
call self.handleResponse(l:message)
endif
endfor
endfunction
function! l:lsp.handleRequest(req) dict abort
if a:req.method == 'workspace/workspaceFolders'
let l:resp = go#lsp#message#workspaceFolders(self.workspaceDirectories)
endif
let l:msg = self.newResponse(l:resp)
call self.write(l:msg)
endfunction
function! l:lsp.handleNotification(req) dict abort
" TODO(bc): handle notifications (e.g. window/showMessage).
endfunction
function! l:lsp.handleResponse(resp) dict abort
if has_key(a:resp, 'id') && has_key(self.handlers, a:resp.id)
try
let l:handler = self.handlers[a:resp.id]
let l:winid = win_getid(winnr())
" Always set the active window to the window that was active when
" the request was sent. Among other things, this makes sure that
" the correct window's location list will be populated when the
" list type is 'location' and the user has moved windows since
" sending the request.
call win_gotoid(l:handler.winid)
if has_key(a:resp, 'error')
call l:handler.requestComplete(0)
if has_key(l:handler, 'error')
call call(l:handler.error, [a:resp.error.message])
else
call go#util#EchoError(a:resp.error.message)
endif
call win_gotoid(l:winid)
return
endif
call l:handler.requestComplete(1)
let l:winidBeforeHandler = l:handler.winid
call call(l:handler.handleResult, [a:resp.result])
" change the window back to the window that was active when
" starting to handle the message _only_ if the handler didn't
" update the winid, so that handlers can set the winid if needed
" (e.g. :GoDef).
if l:handler.winid == l:winidBeforeHandler
call win_gotoid(l:winid)
endif
finally
call remove(self.handlers, a:resp.id)
endtry
endif
endfunction
function! l:lsp.handleInitializeResult(result) dict abort
call go#util#EchoProgress("initialized gopls")
let self.ready = 1
" TODO(bc): send initialized message to the server?
@ -173,7 +195,15 @@ function! s:newlsp() abort
endfunction
function! l:lsp.sendMessage(data, handler) dict abort
" block while waiting on any in flight initializations to avoid race
" conditions initializing gopls.
while get(self, 'checkingmodule', 0)
sleep 50 m
redraw
endwhile
if !self.last_request_id
call go#util#EchoProgress("initializing gopls")
" TODO(bc): run a server per module and one per GOPATH? (may need to
" keep track of servers by rootUri).
let l:wd = go#util#ModuleRoot()
@ -186,25 +216,7 @@ function! s:newlsp() abort
let l:wd = getcwd()
endif
" do not attempt to send a message to gopls when using neither GOPATH
" mode nor module mode.
if go#package#FromPath(l:wd) == -2
if go#config#NullModuleWarning() && (!has_key(self, 'warned') || !self.warned)
let l:oldshortmess=&shortmess
if has('nvim')
set shortmess-=F
endif
call go#util#EchoWarning('Features that rely on gopls will not work correctly outside of GOPATH or a module.')
let self.warned = 1
" Sleep one second to make sure people see the message. Otherwise it is
" often immediately overwritten by an async message.
sleep 1
let &shortmess=l:oldshortmess
endif
return -1
endif
let self.workspaceDirectories = add(self.workspaceDirectories, l:wd)
let l:msg = self.newMessage(go#lsp#message#Initialize(l:wd))
let l:state = s:newHandlerState('')
@ -235,7 +247,7 @@ function! s:newlsp() abort
let l:msg = {
\ 'method': a:data.method,
\ 'jsonrpc': '2.0',
\ }
\ }
if !a:data.notification
let self.last_request_id += 1
@ -249,13 +261,19 @@ function! s:newlsp() abort
return l:msg
endfunction
function l:lsp.newResponse(id, result) dict abort
let l:msg = {
\ 'jsonrpc': '2.0',
\ 'id': a:id,
\ 'result': a:result,
\ }
endfunction
function! l:lsp.write(msg) dict abort
let l:body = json_encode(a:msg)
let l:data = 'Content-Length: ' . strlen(l:body) . "\r\n\r\n" . l:body
if go#util#HasDebug('lsp')
let g:go_lsp_log = add(go#config#LspLog(), "->\n" . l:data)
endif
call s:debug('sent', l:data)
if has('nvim')
call chansend(self.job, l:data)
@ -275,9 +293,7 @@ function! s:newlsp() abort
endfunction
function! l:lsp.err_cb(ch, msg) dict abort
if go#util#HasDebug('lsp')
let g:go_lsp_log = add(go#config#LspLog(), "<-stderr\n" . a:msg)
endif
call s:debug('stderr', a:msg)
endfunction
" explicitly bind callbacks to l:lsp so that within it, self will always refer
@ -303,7 +319,6 @@ function! s:newlsp() abort
" start in.
let l:lsp.job = go#job#Start([l:bin_path], l:opts)
" TODO(bc): send the initialize message now?
return l:lsp
endfunction
@ -363,16 +378,17 @@ function! s:requestComplete(ok) abort dict
endfunction
function! s:start() abort dict
if self.statustype != ''
let status = {
\ 'desc': 'current status',
\ 'type': self.statustype,
\ 'state': "started",
\ }
call go#statusline#Update(self.jobdir, status)
endif
let self.started_at = reltime()
if self.statustype == ''
return
endif
let status = {
\ 'desc': 'current status',
\ 'type': self.statustype,
\ 'state': "started",
\ }
call go#statusline#Update(self.jobdir, status)
endfunction
" go#lsp#Definition calls gopls to get the definition of the identifier at
@ -506,7 +522,17 @@ function! s:completionHandler(next, msg) abort dict
if has_key(l:item, 'detail')
let l:match.info = l:item.detail
if go#lsp#completionitemkind#IsFunction(l:item.kind) || go#lsp#completionitemkind#IsMethod(l:item.kind)
let l:match.info = printf('func %s %s', l:item.label, l:item.detail)
let l:match.info = printf('%s %s', l:item.label, l:item.detail)
" The detail provided by gopls hasn't always provided the the full
" signature including the return value. The label used to be the
" function signature and the detail was the return value. Handle
" that case for backward compatibility. This can be removed in the
" future once it's likely that the majority of users are on a recent
" version of gopls.
if l:item.detail !~ '^func'
let l:match.info = printf('func %s %s', l:item.label, l:item.detail)
endif
endif
endif
@ -561,13 +587,32 @@ function! go#lsp#Info(showstatus)
let l:state = s:newHandlerState('')
endif
let l:state.handleResult = funcref('s:infoDefinitionHandler', [a:showstatus], l:state)
let l:state.handleResult = funcref('s:infoDefinitionHandler', [function('s:info', [1], l:state), a:showstatus], l:state)
let l:state.error = funcref('s:noop')
let l:msg = go#lsp#message#Definition(l:fname, l:line, l:col)
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:infoDefinitionHandler(showstatus, msg) abort dict
function! go#lsp#GetInfo()
let l:fname = expand('%:p')
let [l:line, l:col] = getpos('.')[1:2]
call go#lsp#DidChange(l:fname)
let l:lsp = s:lspfactory.get()
let l:state = s:newHandlerState('')
let l:info = go#promise#New(function('s:info', [0], l:state), 10000, '')
let l:state.handleResult = funcref('s:infoDefinitionHandler', [l:info.wrapper, 0], l:state)
let l:state.error = funcref('s:noop')
let l:msg = go#lsp#message#Definition(l:fname, l:line, l:col)
call l:lsp.sendMessage(l:msg, l:state)
return l:info.await()
endfunction
function! s:infoDefinitionHandler(next, showstatus, msg) abort dict
" gopls returns a []Location; just take the first one.
let l:msg = a:msg[0]
@ -584,22 +629,101 @@ function! s:infoDefinitionHandler(showstatus, msg) abort dict
let l:state = s:newHandlerState('')
endif
let l:state.handleResult = funcref('s:hoverHandler', [function('s:info', [], l:state)], l:state)
let l:state.handleResult = funcref('s:hoverHandler', [a:next], l:state)
let l:state.error = funcref('s:noop')
return l:lsp.sendMessage(l:msg, l:state)
endfunction
function! s:info(content) abort dict
function! s:info(show, content) abort dict
let l:content = s:infoFromHoverContent(a:content)
if a:show
call go#util#ShowInfo(l:content)
endif
return l:content
endfunction
function! s:infoFromHoverContent(content) abort
if len(a:content) < 1
return ''
endif
let l:content = a:content[0]
" strip godoc summary
let l:content = substitute(l:content, '^[^\n]\+\n', '', '')
" Hover content with godoc summary will have the godoc summary in the first
" line, and the second line will not have leading whitespace. When there is
" leading whitespace on the second line, then the hover content is for a
" struct or interface without godoc.
let l:lines = split(l:content, '\n')
if len(l:lines) > 1 && (l:lines[1] !~# '^\s')
let l:content = substitute(l:content, '^[^\n]\+\n', '', '')
endif
" strip off the method set and fields of structs and interfaces.
if l:content =~# '^type [^ ]\+ \(struct\|interface\)'
if l:content =~# '^\(type \)\?[^ ]\+ \(struct\|interface\)'
let l:content = substitute(l:content, '{.*', '', '')
endif
call go#util#ShowInfo(l:content)
return l:content
endfunction
function! go#lsp#AddWorkspace(...) abort
if a:0 == 0
return
endif
let l:workspaces = []
for l:dir in a:000
let l:dir = fnamemodify(l:dir, ':p')
if !isdirectory(l:dir)
continue
endif
let l:workspaces = add(l:workspaces, l:dir)
endfor
let l:lsp = s:lspfactory.get()
let l:state = s:newHandlerState('')
let l:state.handleResult = funcref('s:noop')
let l:lsp.workspaceDirectories = extend(l:lsp.workspaceDirectories, l:workspaces)
let l:msg = go#lsp#message#AddWorkspaces(l:workspaces)
call l:lsp.sendMessage(l:msg, l:state)
return 0
endfunction
function! s:debug(event, data) abort
if !go#util#HasDebug('lsp')
return
endif
let l:winid = win_getid()
let l:name = '__GOLSP_LOG__'
let l:log_winid = bufwinid(l:name)
if l:log_winid == -1
silent keepalt botright 10new
silent file `='__GOLSP_LOG__'`
setlocal buftype=nofile bufhidden=wipe nomodified nobuflisted noswapfile nowrap nonumber nocursorline
setlocal filetype=golsplog
else
call win_gotoid(l:log_winid)
endif
try
setlocal modifiable
if getline(1) == ''
call setline('$', printf('%s: %s', a:event, a:data))
else
call append('$', printf('%s: %s', a:event, a:data))
endif
normal! G
setlocal nomodifiable
finally
call win_gotoid(l:winid)
endtry
endfunction
" restore Vi compatibility settings

View File

@ -10,7 +10,9 @@ function! go#lsp#message#Initialize(wd) abort
\ 'processId': getpid(),
\ 'rootUri': go#path#ToURI(a:wd),
\ 'capabilities': {
\ 'workspace': {},
\ 'workspace': {
\ 'workspaceFolders': v:true,
\ },
\ 'textDocument': {
\ 'hover': {
\ 'contentFormat': ['plaintext'],
@ -21,6 +23,14 @@ function! go#lsp#message#Initialize(wd) abort
\ }
endfunction
function! go#lsp#message#workspaceFolders(dirs) abort
return map(copy(a:dirs), function('s:workspaceFolderToURI', []))
endfunction
function s:workspaceFolderToURI(key, val) abort
return go#path#ToURI(a:val)
endfunction
function! go#lsp#message#Definition(file, line, col) abort
return {
\ 'notification': 0,
@ -116,6 +126,25 @@ function! go#lsp#message#Hover(file, line, col) abort
\ }
endfunction
function! go#lsp#message#AddWorkspaces(dirs) abort
let l:dirs = map(copy(a:dirs), function('s:workspaceFodlerToAddURI', []))
return {
\ 'notification': 1,
\ 'method': 'workspace/didChangeWorkspaceFolders',
\ 'params': {
\ 'event': {
\ 'added': l:dirs,
\ },
\ }
\ }
endfunction
function s:workspaceFolderToAddURI(key, val) abort
return {'uri': go#path#ToURI(a:val), 'name': a:val}
endfunction
function! s:position(line, col) abort
return {'line': a:line - 1, 'character': a:col-1}
endfunction

View File

@ -8,10 +8,14 @@ function! go#mod#Format() abort
" go mod only exists in `v1.11`
if empty(s:go_major_version)
let tokens = matchlist(go#util#Exec(['go', 'version']), '\d\+.\(\d\+\)\(\.\d\+\)\? ')
let s:go_major_version = str2nr(tokens[1])
if len(tokens) > 0
let s:go_major_version = str2nr(tokens[1])
else
let s:go_major_version = ""
endif
endif
if s:go_major_version < "11"
if !empty(s:go_major_version) && s:go_major_version < "11"
call go#util#EchoError("Go v1.11 is required to format go.mod file")
return
endif

View File

@ -82,6 +82,10 @@ function! s:vendordirs() abort
if l:err != 0
return []
endif
if empty(l:root)
return []
endif
let l:root = split(l:root, '\n')[0] . go#util#PathSep() . 'src'
let [l:dir, l:err] = go#util#ExecInDir(['go', 'list', '-f', '{{.Dir}}'])
@ -111,35 +115,29 @@ function! s:vendordirs() abort
endfunction
let s:import_paths = {}
" ImportPath returns the import path of the package for current buffer.
" ImportPath returns the import path of the package for current buffer. It
" returns -1 if the import path cannot be determined.
function! go#package#ImportPath() abort
let dir = expand("%:p:h")
let l:dir = expand("%:p:h")
if has_key(s:import_paths, dir)
return s:import_paths[dir]
return s:import_paths[l:dir]
endif
let [l:out, l:err] = go#util#ExecInDir(['go', 'list'])
if l:err != 0
let l:importpath = go#package#FromPath(l:dir)
if type(l:importpath) == type(0)
return -1
endif
let l:importpath = split(out, '\n')[0]
" go list returns '_CURRENTDIRECTORY' if the directory is not inside GOPATH.
" Check it and retun an error if that is the case
if l:importpath[0] ==# '_'
return -1
endif
let s:import_paths[dir] = l:importpath
let s:import_paths[l:dir] = l:importpath
return l:importpath
endfunction
" go#package#FromPath returns the import path of arg. -1 is returned when arg
" does not specify a package. -2 is returned when arg is a relative path
" outside of GOPATH and not in a module.
" outside of GOPATH, not in a module, and not below the current working
" directory. A relative path is returned when in a null module at or below the
" current working directory..
function! go#package#FromPath(arg) abort
let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
let l:dir = getcwd()
@ -150,25 +148,44 @@ function! go#package#FromPath(arg) abort
endif
execute l:cd fnameescape(l:path)
if glob("*.go") == ""
" There's no Go code in this directory. We might be in a module directory
" which doesn't have any code at this level.
if !empty(s:module())
try
if glob("*.go") == ""
" There's no Go code in this directory. We might be in a module directory
" which doesn't have any code at this level. To avoid `go list` making a
" bunch of HTTP requests to fetch dependencies, short-circuit `go list`
" and return -1 immediately.
if !empty(s:module())
return -1
endif
endif
let [l:out, l:err] = go#util#Exec(['go', 'list'])
if l:err != 0
return -1
endif
endif
let [l:out, l:err] = go#util#Exec(['go', 'list'])
execute l:cd fnameescape(l:dir)
if l:err != 0
return -1
endif
let l:importpath = split(l:out, '\n')[0]
let l:importpath = split(l:out, '\n')[0]
finally
execute l:cd fnameescape(l:dir)
endtry
" go list returns '_CURRENTDIRECTORY' if the directory is neither in GOPATH
" nor in a module. Check it and retun an error if that is the case
" go list returns '_CURRENTDIRECTORY' if the directory is in a null module
" (i.e. neither in GOPATH nor in a module). Return a relative import path
" if possible or an error if that is the case.
if l:importpath[0] ==# '_'
return -2
let l:relativeimportpath = fnamemodify(l:importpath[1:], ':.')
if go#util#IsWin()
let l:relativeimportpath = substitute(l:relativeimportpath, '\\', '/', 'g')
endif
if l:relativeimportpath == l:importpath[1:]
return '.'
endif
if l:relativeimportpath[0] == '/'
return -2
endif
let l:importpath= printf('./%s', l:relativeimportpath)
endif
return l:importpath

View File

@ -0,0 +1,50 @@
" don't spam the user when Vim is started in Vi compatibility mode
let s:cpo_save = &cpo
set cpo&vim
scriptencoding utf-8
" New returns a promise. A promise's primary purpose is to make async jobs
" synchronous by awaiting fn.
"
" A promise is a dictionary with two keys:
" 'wrapper':
" A function that wraps fn. It can be used in place of fn.
" 'await':
" A function that waits for wrapper to be called and returns the value
" returned by fn. Returns default if timeout expires.
function! go#promise#New(fn, timeout, default) abort
let l:state = {}
" explicitly bind to state so that within l:promise's methods, self will
" always refer to state. See :help Partial for more information.
return {
\ 'wrapper': function('s:wrapper', [a:fn], l:state),
\ 'await': function('s:await', [a:timeout, a:default], l:state),
\ }
endfunction
function! s:wrapper(fn, ...) dict
let self.retval = call(a:fn, a:000)
return self.retval
endfunction
function! s:await(timeout, default) dict
let l:timer = timer_start(a:timeout, function('s:setretval', [a:default], self))
while !has_key(self, 'retval')
sleep 50m
endwhile
call timer_stop(l:timer)
return self.retval
endfunction
function! s:setretval(val, timer) dict
let self.retval = a:val
endfunction
" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: sw=2 ts=2 et

View File

@ -0,0 +1,41 @@
" don't spam the user when Vim is started in Vi compatibility mode
let s:cpo_save = &cpo
set cpo&vim
func! Test_PromiseNew() abort
let l:sut = go#promise#New(function('s:work', []), 100, -1)
call assert_true(has_key(l:sut, 'wrapper'))
call assert_true(has_key(l:sut, 'await'))
endfunc
func! Test_PromiseAwait() abort
let l:expected = 1
let l:default = -1
let l:sut = go#promise#New(function('s:work', [l:expected]), 100, l:default)
call timer_start(10, l:sut.wrapper)
let l:actual = call(l:sut.await, [])
call assert_equal(l:expected, l:actual)
endfunc
func! Test_PromiseAwait_Timeout() abort
let l:desired = 1
let l:expected = -1
let l:sut = go#promise#New(function('s:work', [l:desired]), 10, l:expected)
call timer_start(100, l:sut.wrapper)
let l:actual = call(l:sut.await, [])
call assert_equal(l:expected, l:actual)
endfunc
func! s:work(val, timer)
return a:val
endfunc
" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: sw=2 ts=2 et

View File

@ -94,26 +94,26 @@ For Pathogen or Vim |packages|, just clone the repo. For other plugin managers
you may also need to add the lines to your vimrc to execute the plugin
manager's install command.
* Vim 8 |packages|
>
* Vim 8 |packages| >
git clone https://github.com/fatih/vim-go.git \
~/.vim/pack/plugins/start/vim-go
<
* https://github.com/tpope/vim-pathogen >
git clone https://github.com/fatih/vim-go.git ~/.vim/bundle/vim-go
<
* https://github.com/junegunn/vim-plug >
Plug 'fatih/vim-go'
Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }
<
* https://github.com/Shougo/neobundle.vim >
NeoBundle 'fatih/vim-go'
<
* https://github.com/gmarik/vundle >
Plugin 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }
Plugin 'fatih/vim-go'
<
* Manual (not recommended) >
@ -536,7 +536,7 @@ CTRL-t
*:GoGuruScope*
:GoGuruScope [pattern] [pattern2] ... [patternN]
:GoGuruScope [pattern] ...
Changes the custom |'g:go_guru_scope'| setting and overrides it with the
given package patterns. The custom scope is cleared (unset) if `""` is
@ -906,6 +906,11 @@ CTRL-t
tries to preserve cursor position and avoids replacing the buffer with
stderr output.
*:GoAddWorkspace*
:GoAddWorkspace [dir] ...
Add directories to the `gopls` workspace.
==============================================================================
MAPPINGS *go-mappings*
@ -1212,14 +1217,6 @@ enabled.
let g:go_version_warning = 1
<
*'g:go_null_module_warning'*
Enable warning when trying to use lsp features in a null module. By default it
is enabled.
>
let g:go_null_module_warning = 1
<
*'g:go_code_completion_enabled'*
Enable code completion with |'omnifunc'|. By default it is enabled.
@ -1275,11 +1272,11 @@ updated. By default it's disabled. The delay can be configured with the
*'g:go_info_mode'*
Use this option to define the command to be used for |:GoInfo|. By default
`gocode` is being used as it's the fastest option. But one might also use
`gopls` or `guru` as they cover more cases and are more accurate. Current
valid options are: `[gocode, guru, gopls]` >
let g:go_info_mode = 'gocode'
`gopls` is used, because it is the fastest and is known to be highly accurate.
One might also use `guru` for its accuracy or `gocode` for its performance.
Valid options are `gocode`, `gopls`, and `guru`.
>
let g:go_info_mode = 'gopls'
<
*'g:go_auto_sameids'*
@ -1391,10 +1388,11 @@ a private internal service. Default is 'https://godoc.org'.
*'g:go_def_mode'*
Use this option to define the command to be used for |:GoDef|. By default
`guru` is being used as it covers all edge cases. But one might also use
`godef` as it's faster. Current valid options are: `[guru, godef, gopls]` >
let g:go_def_mode = 'guru'
`gopls` is used, because it is the fastest. One might also use `guru` for its
accuracy or `godef` for its performance. Valid options are `godef`, `gopls`,
and `guru`.
>
let g:go_def_mode = 'gopls'
<
*'g:go_def_mapping_enabled'*
@ -1804,7 +1802,8 @@ Currently accepted values:
debugger-state Expose debugger state in 'g:go_debug_diag'.
debugger-commands Echo communication between vim-go and `dlv`; requests and
responses are recorded in `g:go_debug_commands`.
lsp Record lsp requests and responses in g:go_lsp_log.
lsp Echo communication between vim-go and `gopls`. All
communication is shown in a dedicated window.
>
let g:go_debug = []
<
@ -2043,8 +2042,7 @@ rest of the commands and mappings become available after starting debug mode.
* Make the `:GoDebug*` commands and `(go-debug-*)` mappings available.
The directory of the current buffer is used if [pkg] is empty. Any other
arguments will be passed to the program. When [pkg] is relative, it will
be interpreted relative to the directory of the current buffer.
arguments will be passed to the program.
Use |:GoDebugStop| to stop `dlv` and exit debugging mode.

View File

@ -116,4 +116,7 @@ command! -nargs=0 GoReportGitHubIssue call go#issue#New()
" -- iferr
command! -nargs=0 GoIfErr call go#iferr#Generate()
" -- lsp
command! -nargs=+ -complete=dir GoAddWorkspace call go#lsp#AddWorkspace(<f-args>)
" vim: sw=2 ts=2 et

View File

@ -151,7 +151,7 @@ if err := ${1:condition}; err != nil {
endsnippet
# error snippet
snippet errn "Error return " !b
snippet err "Error return" !b
if err != nil {
return err
}
@ -326,7 +326,7 @@ endsnippet
# struct
snippet st "type T struct { ... }"
type ${1:Type} struct {
${0}
${0}
}
endsnippet

View File

@ -20,19 +20,19 @@ function! s:checkVersion() abort
let l:unsupported = 0
if go#config#VersionWarning() != 0
if has('nvim')
let l:unsupported = !has('nvim-0.3.1')
let l:unsupported = !has('nvim-0.3.2')
else
let l:unsupported = (v:version < 704 || (v:version == 704 && !has('patch2009')))
endif
if l:unsupported == 1
echohl Error
echom "vim-go requires Vim 7.4.2009 or Neovim 0.3.1, but you're using an older version."
echom "vim-go requires Vim 7.4.2009 or Neovim 0.3.2, but you're using an older version."
echom "Please update your Vim for the best vim-go experience."
echom "If you really want to continue you can set this to make the error go away:"
echom " let g:go_version_warning = 0"
echom "Note that some features may error out or behave incorrectly."
echom "Please do not report bugs unless you're using Vim 7.4.2009 or newer or Neovim 0.3.1."
echom "Please do not report bugs unless you're using Vim 7.4.2009 or newer or Neovim 0.3.2."
echohl None
" Make sure people see this.
@ -56,7 +56,7 @@ let s:packages = {
\ 'gogetdoc': ['github.com/zmb3/gogetdoc'],
\ 'goimports': ['golang.org/x/tools/cmd/goimports'],
\ 'golint': ['golang.org/x/lint/golint'],
\ 'gopls': ['golang.org/x/tools/cmd/gopls'],
\ 'gopls': ['golang.org/x/tools/gopls@latest'],
\ 'gometalinter': ['github.com/alecthomas/gometalinter'],
\ 'golangci-lint': ['github.com/golangci/golangci-lint/cmd/golangci-lint'],
\ 'gomodifytags': ['github.com/fatih/gomodifytags'],
@ -104,9 +104,6 @@ function! s:GoInstallBinaries(updateBinaries, ...)
" vim's executable path is looking in PATH so add our go_bin path to it
let Restore_path = go#util#SetEnv('PATH', go_bin_path . go#util#PathListSep() . $PATH)
" GO111MODULE must be off to install golanci-lint and gometalinter
let Restore_modules = go#util#SetEnv('GO111MODULE', 'off')
" when shellslash is set on MS-* systems, shellescape puts single quotes
" around the output string. cmd on Windows does not handle single quotes
" correctly. Unsetting shellslash forces shellescape to use double quotes
@ -117,10 +114,7 @@ function! s:GoInstallBinaries(updateBinaries, ...)
set noshellslash
endif
let l:dl_cmd = ['go', 'get', '-v', '-d']
if get(g:, "go_get_update", 1) != 0
let l:dl_cmd += ['-u']
endif
let l:get_base_cmd = ['go', 'get', '-v']
" Filter packages from arguments (if any).
let l:packages = {}
@ -145,11 +139,9 @@ function! s:GoInstallBinaries(updateBinaries, ...)
for [binary, pkg] in items(l:packages)
let l:importPath = pkg[0]
let l:run_cmd = copy(l:dl_cmd)
if len(l:pkg) > 1 && get(l:pkg[1], l:platform, '') isnot ''
let l:run_cmd += get(l:pkg[1], l:platform, '')
endif
" TODO(bc): how to support this with modules? Do we have to clone and then
" install manually? Probably not. I suspect that we can just use GOPATH
" mode and then do the legacy method.
let bin_setting_name = "go_" . binary . "_bin"
if exists("g:{bin_setting_name}")
@ -169,24 +161,61 @@ function! s:GoInstallBinaries(updateBinaries, ...)
echo "vim-go: ". binary ." not found. Installing ". importPath . " to folder " . go_bin_path
endif
" first download the binary
let [l:out, l:err] = go#util#Exec(l:run_cmd + [l:importPath])
if l:err
echom "Error downloading " . l:importPath . ": " . l:out
if l:importPath =~ "@"
let Restore_modules = go#util#SetEnv('GO111MODULE', 'on')
let l:tmpdir = go#util#tempdir('vim-go')
let l:cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
let l:dir = getcwd()
try
execute l:cd . fnameescape(l:tmpdir)
let l:get_cmd = copy(l:get_base_cmd)
" first download the binary
let [l:out, l:err] = go#util#Exec(l:get_cmd + [l:importPath])
if l:err
echom "Error installing " . l:importPath . ": " . l:out
endif
call call(Restore_modules, [])
finally
execute l:cd . fnameescape(l:dir)
endtry
call call(Restore_modules, [])
else
let l:get_cmd = copy(l:get_base_cmd)
let l:get_cmd += ['-d']
if get(g:, "go_get_update", 1) != 0
let l:get_cmd += ['-u']
endif
" GO111MODULE must be off to install gometalinter.
let Restore_modules = go#util#SetEnv('GO111MODULE', 'off')
" first download the binary
let [l:out, l:err] = go#util#Exec(l:get_cmd + [l:importPath])
if l:err
echom "Error downloading " . l:importPath . ": " . l:out
endif
" and then build and install it
let l:build_cmd = ['go', 'build', '-o', go_bin_path . go#util#PathSep() . bin, l:importPath]
if len(l:pkg) > 1 && get(l:pkg[1], l:platform, '') isnot ''
let l:build_cmd += get(l:pkg[1], l:platform, '')
endif
let [l:out, l:err] = go#util#Exec(l:build_cmd)
if l:err
echom "Error installing " . l:importPath . ": " . l:out
endif
call call(Restore_modules, [])
endif
" and then build and install it
let l:build_cmd = ['go', 'build', '-o', go_bin_path . go#util#PathSep() . bin, l:importPath]
let [l:out, l:err] = go#util#Exec(l:build_cmd)
if l:err
echom "Error installing " . l:importPath . ": " . l:out
endif
endif
endfor
" restore back!
call call(Restore_path, [])
call call(Restore_modules, [])
if resetshellslash
set shellslash

View File

@ -30,7 +30,7 @@ case "$vim" in
"nvim")
# Use latest stable version.
tag="v0.3.1"
tag="v0.3.2"
giturl="https://github.com/neovim/neovim"
;;
@ -62,7 +62,7 @@ cd "$srcdir"
if [ "$1" = "nvim" ]; then
# TODO: Use macOS binaries on macOS
curl -Ls https://github.com/neovim/neovim/releases/download/nightly/nvim-linux64.tar.gz |
curl -Ls https://github.com/neovim/neovim/releases/download/$tag/nvim-linux64.tar.gz |
tar xzf - -C /tmp/vim-go-test/
mv /tmp/vim-go-test/nvim-linux64 /tmp/vim-go-test/nvim-install
mkdir -p "$installdir/share/nvim/runtime/pack/vim-go/start"