internal/lsp/cache: always consider go.work files for ws expansion

If a go.work file is present, we activate the workspace mode regardless
of the experimentalWorkspaceModule setting.

Fixing this also revealed a long-standing bug in traversing parent
directories. Amazingly I have no recollection of this bug being
reported, but it is far more likely to be hit with go.work files, when
users regularly open nested subdirectories.

Fixes golang/go#51477

Change-Id: I310a11b14f3bbc18fdd604c5c0ec33d7ee8f1174
Reviewed-on: https://go-review.googlesource.com/c/tools/+/389300
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Robert Findley 2022-03-03 18:37:26 -05:00
parent e155b03a0e
commit b59c441bdb
3 changed files with 55 additions and 2 deletions

View File

@ -865,6 +865,55 @@ module example.com/bar/baz
})
}
func TestExpandToGoWork(t *testing.T) {
testenv.NeedsGo1Point(t, 18)
const workspace = `
-- moda/a/go.mod --
module a.com
require b.com v1.2.3
-- moda/a/a.go --
package a
import (
"b.com/b"
)
func main() {
var x int
_ = b.Hello()
}
-- modb/go.mod --
module b.com
require example.com v1.2.3
-- modb/b/b.go --
package b
func Hello() int {
var x int
}
-- go.work --
go 1.17
use (
./moda/a
./modb
)
`
WithOptions(
WorkspaceFolders("moda/a"),
).Run(t, workspace, func(t *testing.T, env *Env) {
env.OpenFile("moda/a/a.go")
env.Await(env.DoneWithOpen())
location, _ := env.GoToDefinition("moda/a/a.go", env.RegexpSearch("moda/a/a.go", "Hello"))
want := "modb/b/b.go"
if !strings.HasSuffix(location, want) {
t.Errorf("expected %s, got %v", want, location)
}
})
}
func TestNonWorkspaceFileCreation(t *testing.T) {
testenv.NeedsGo1Point(t, 13)

View File

@ -832,7 +832,7 @@ func go111moduleForVersion(go111module string, goversion int) go111module {
// TODO (rFindley): move this to workspace.go
// TODO (rFindley): simplify this once workspace modules are enabled by default.
func findWorkspaceRoot(ctx context.Context, folder span.URI, fs source.FileSource, excludePath func(string) bool, experimental bool) (span.URI, error) {
patterns := []string{"go.mod"}
patterns := []string{"go.work", "go.mod"}
if experimental {
patterns = []string{"go.work", "gopls.mod", "go.mod"}
}
@ -882,7 +882,8 @@ func findRootPattern(ctx context.Context, folder span.URI, basename string, fs s
if exists {
return span.URIFromPath(dir), nil
}
next, _ := filepath.Split(dir)
// Trailing separators must be trimmed, otherwise filepath.Split is a noop.
next, _ := filepath.Split(strings.TrimRight(dir, string(filepath.Separator)))
if next == dir {
break
}

View File

@ -55,6 +55,8 @@ func TestFindWorkspaceRoot(t *testing.T) {
module a
-- a/x/x.go
package x
-- a/x/y/y.go
package x
-- b/go.mod --
module b
-- b/c/go.mod --
@ -79,6 +81,7 @@ module fg
{"", "", false}, // no module at root, and more than one nested module
{"a", "a", false},
{"a/x", "a", false},
{"a/x/y", "a", false},
{"b/c", "b/c", false},
{"d", "d/e", false},
{"d", "d", true},