From 70ccf57e4b75514eaa0d0b35525b2b5fd63e489a Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 3 Dec 2021 10:51:49 +0100 Subject: [PATCH] go/packages: fix loading single file when outside of GOPATH, module Allows a 'file=' query to load a single file even when it is outside of GOPATH or a module. Fixes golang/go#49949 Change-Id: I519f1412923dfc1d2504ec49620d10c823e5c0dc Reviewed-on: https://go-review.googlesource.com/c/tools/+/369014 TryBot-Result: Gopher Robot gopls-CI: kokoro Reviewed-by: Robert Findley Reviewed-by: Hyang-Ah Hana Kim --- go/packages/golist.go | 7 ++++--- go/packages/packages_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/go/packages/golist.go b/go/packages/golist.go index 50533995a6..de881562de 100644 --- a/go/packages/golist.go +++ b/go/packages/golist.go @@ -302,11 +302,12 @@ func (state *golistState) runContainsQueries(response *responseDeduper, queries } dirResponse, err := state.createDriverResponse(pattern) - // If there was an error loading the package, or the package is returned - // with errors, try to load the file as an ad-hoc package. + // If there was an error loading the package, or no packages are returned, + // or the package is returned with errors, try to load the file as an + // ad-hoc package. // Usually the error will appear in a returned package, but may not if we're // in module mode and the ad-hoc is located outside a module. - if err != nil || len(dirResponse.Packages) == 1 && len(dirResponse.Packages[0].GoFiles) == 0 && + if err != nil || len(dirResponse.Packages) == 0 || len(dirResponse.Packages) == 1 && len(dirResponse.Packages[0].GoFiles) == 0 && len(dirResponse.Packages[0].Errors) == 1 { var queryErr error if dirResponse, queryErr = state.adhocPackage(pattern, query); queryErr != nil { diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go index 796edb6b7b..647f3a366d 100644 --- a/go/packages/packages_test.go +++ b/go/packages/packages_test.go @@ -2709,6 +2709,31 @@ func TestEmptyEnvironment(t *testing.T) { } } +func TestPackageLoadSingleFile(t *testing.T) { + tmp, err := ioutil.TempDir("", "a") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmp) + + filename := filepath.Join(tmp, "a.go") + + if err := ioutil.WriteFile(filename, []byte(`package main; func main() { println("hello world") }`), 0775); err != nil { + t.Fatal(err) + } + + pkgs, err := packages.Load(&packages.Config{Mode: packages.LoadSyntax, Dir: tmp}, "file="+filename) + if err != nil { + t.Fatalf("could not load package: %v", err) + } + if len(pkgs) != 1 { + t.Fatalf("expected one package to be loaded, got %d", len(pkgs)) + } + if len(pkgs[0].CompiledGoFiles) != 1 || pkgs[0].CompiledGoFiles[0] != filename { + t.Fatalf("expected one compiled go file (%q), got %v", filename, pkgs[0].CompiledGoFiles) + } +} + func errorMessages(errors []packages.Error) []string { var msgs []string for _, err := range errors {