saibing / bingo

Bingo is a Go language server that speaks Language Server Protocol.
MIT License
495 stars 25 forks source link

Fix errors in non-moduled dependencies #87

Closed yudai closed 5 years ago

yudai commented 5 years ago

What's Observed

Bingo returns errors when I open files in the $GOPATH/pkg/mod directory (on Emacs with lsp-mode).

For example, textDocument/hover requests fail with the following error message:

--> request #165: textDocument/hover:
{"textDocument":{"uri":"file:///home/yudai/gopath/pkg/mod/k8s.io/kubernetes@v1.13.3/pkg/kubelet/pod/pod_manager.go"},"position":{"line":131,"character":0}}
<-- error #165: textDocument/hover: {"code":0,"message":"go [list -f
{{context.GOARCH}} {{context.Compiler}} -- unsafe]: exit status 1: go:
creating new go.mod: module k8s.io/kubernetes\ngo: copying requirements
from ../../../Godeps/Godeps.json\ngo: open
/home/yudai/gopath/pkg/mod/k8s.io/kubernetes@v1.13.3/go.mod: permission
denied\n","data":null}

Root Cause

The command go [list -f {{context.GOARCH}} {{context.Compiler}} -- unsafe is executed by GetSizesGolist() in golang.org/x/tools: https://github.com/golang/tools/blob/79186431cf2917562ba2e632326924b5594ce114/go/internal/packagesdriver/sizes.go#L81

The go list command actually fails alone if you run it on the directory of a non-moduled (no go.mod) dependency package.

$ echo $GO111MODULE
on
$ pwd
/home/yudai/gopath/pkg/mod/k8s.io/kubernetes@v1.13.3
$ go list -f '{{context.GOARCH}} {{context.Compiler}}' --
unsafe
go: creating new go.mod: module k8s.io/kubernetes
go: copying requirements from Godeps/Godeps.json
go: open /home/yudai/gopath/pkg/mod/k8s.io/kubernetes@v1.13.3/go.mod:
permission denied

It seems go list tries to create go.md when GO111MODULE is on even if you are in pkg/mod. However since directories in pkg/mod are read only, the command always fails. I’m not sure if this behavior itself is correct (go list should not try to convert packages to modules in pkg/mod even when MODULE is on?), but anyway it won’t work in pkg/mod now. 
This GetSizesGoList() is called from packages.Load() and it’s originated from *View.parse() in cache/view.go. We currently set path to v.Config.Dir, that makes the go list command run in path and causes the error above.

Fix

We don’t need to set v.Config.Dir. The go command will be run in the current working directory and that just works.

yudai commented 5 years ago

I'm not sure if there is any side effect by this change. It looks working on my env though.

yudai commented 5 years ago

see also: https://github.com/golang/go/issues/29452

s-kostyaev commented 5 years ago

@yudai @saibing I have found case where it breaks bingo on my project (files in nested module like in #2). I'll fix it in another PR.