gopls/internal/lsp/cache: don't report a bug for standalone test files

go/packages will return test command-line-arguments test variants for
standalone test files. Handle this case, and refine our bug report.

Fixes golang/go#64233

Change-Id: I15fd8a50476ece58eedbf09233827f55bfb79a2e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/557635
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
Rob Findley 2024-01-22 16:42:07 -05:00 коммит произвёл Robert Findley
Родитель a49867fe1f
Коммит 4c532679b1
2 изменённых файлов: 81 добавлений и 4 удалений

43
gopls/internal/lsp/cache/load.go поставляемый
Просмотреть файл

@ -151,6 +151,45 @@ func (s *Snapshot) load(ctx context.Context, allowNetwork bool, scopes ...loadSc
event.Log(ctx, eventName, labels...)
}
if standalone {
// Handle standalone package result.
//
// In general, this should just be a single "command-line-arguments"
// package containing the requested file. However, if the file is a test
// file, go/packages may return test variants of the command-line-arguments
// package. We don't support this; theoretically we could, but it seems
// unnecessarily complicated.
//
// Prior to golang/go#64233 we just assumed that we'd get exactly one
// package here. The categorization of bug reports below may be a bit
// verbose, but anticipates that perhaps we don't fully understand
// possible failure modes.
errorf := bug.Errorf
if s.view.typ == GoPackagesDriverView {
errorf = fmt.Errorf // all bets are off
}
var standalonePkg *packages.Package
for _, pkg := range pkgs {
if pkg.ID == "command-line-arguments" {
if standalonePkg != nil {
return errorf("internal error: go/packages returned multiple standalone packages")
}
standalonePkg = pkg
} else if packagesinternal.GetForTest(pkg) == "" && !strings.HasSuffix(pkg.ID, ".test") {
return errorf("internal error: go/packages returned unexpected package %q for standalone file", pkg.ID)
}
}
if standalonePkg == nil {
return errorf("internal error: go/packages failed to return non-test standalone package")
}
if len(standalonePkg.CompiledGoFiles) > 0 {
pkgs = []*packages.Package{standalonePkg}
} else {
pkgs = nil
}
}
if len(pkgs) == 0 {
if err == nil {
err = errNoPackages
@ -158,10 +197,6 @@ func (s *Snapshot) load(ctx context.Context, allowNetwork bool, scopes ...loadSc
return fmt.Errorf("packages.Load error: %w", err)
}
if standalone && len(pkgs) > 1 {
return bug.Errorf("internal error: go/packages returned multiple packages for standalone file")
}
moduleErrs := make(map[string][]packages.Error) // module path -> errors
filterFunc := s.view.filterFunc()
newMetadata := make(map[PackageID]*metadata.Package)

42
gopls/internal/test/marker/testdata/definition/standalone.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,42 @@
This test checks the behavior of standalone packages, in particular documenting
our failure to support test files as standalone packages (golang/go#64233).
-- go.mod --
module golang.org/lsptests/a
go 1.20
-- a.go --
package a
func F() {} //@loc(F, "F")
-- standalone.go --
//go:build ignore
package main
import "golang.org/lsptests/a"
func main() {
a.F() //@def("F", F)
}
-- standalone_test.go --
//go:build ignore
package main //@diag("main", re"No packages found")
import "golang.org/lsptests/a"
func main() {
a.F() //@hovererr("F", "no package")
}
-- standalone_x_test.go --
//go:build ignore
package main_test //@diag("main", re"No packages found")
import "golang.org/lsptests/a"
func main() {
a.F() //@hovererr("F", "no package")
}