Skip to content

Commit

Permalink
Merge pull request #2335 from bhcleek/better-relative-import-path-sup…
Browse files Browse the repository at this point in the history
…port

try to use relative import paths if necessary
  • Loading branch information
bhcleek authored Jun 4, 2019
2 parents 5b5a90b + ea28320 commit b82f469
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 41 deletions.
21 changes: 17 additions & 4 deletions autoload/go/debug.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
12 changes: 12 additions & 0 deletions autoload/go/debug_test.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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'))
Expand Down
2 changes: 1 addition & 1 deletion autoload/go/lint.vim
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,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")
Expand Down
9 changes: 5 additions & 4 deletions autoload/go/lsp.vim
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,16 @@ 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
" do not attempt to send a message to gopls when using a null module in
" module mode.
let l:importpath = go#package#FromPath(l:wd)
if l:importpath == -2 || (type(l:importpath) == type('') && l:importpath[0] == '.')
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.')
call go#util#EchoWarning('Features that rely on gopls will not work correctly in a null 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.
Expand Down
73 changes: 43 additions & 30 deletions autoload/go/package.vim
Original file line number Diff line number Diff line change
Expand Up @@ -115,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
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] ==# '_'
let l:importpath = go#package#FromPath(l:dir)
if type(l:importpath) == type(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()
Expand All @@ -154,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
Expand Down
3 changes: 1 addition & 2 deletions doc/vim-go.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2043,8 +2043,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.

Expand Down

0 comments on commit b82f469

Please sign in to comment.