From 4bb205a2067d17ffba8609084fd437e5b1775cf1 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 14 Jun 2019 13:17:31 -0400 Subject: [PATCH] go/packages: add support for file= queries on ad-hoc packages This will do a go list using a filename directly if listing using the directory failed. Fixes golang/go#32587 Change-Id: Id9993968f0ebc18a455132e0f1468356416a66dd Reviewed-on: https://go-review.googlesource.com/c/tools/+/182465 Run-TryBot: Michael Matloob Reviewed-by: Rebecca Stambler --- go/packages/golist.go | 7 ++++++ go/packages/packages_test.go | 42 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/go/packages/golist.go b/go/packages/golist.go index 72c0c5d6..a931fcaa 100644 --- a/go/packages/golist.go +++ b/go/packages/golist.go @@ -231,6 +231,13 @@ func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, q if err != nil { return err } + if len(dirResponse.Roots) == 0 { + // Couldn't find a package for the directory. Try to load the file as an ad-hoc package. + dirResponse, err = driver(cfg, query) + if err != nil { + return err + } + } isRoot := make(map[string]bool, len(dirResponse.Roots)) for _, root := range dirResponse.Roots { isRoot[root] = true diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go index b5eb3666..202125a1 100644 --- a/go/packages/packages_test.go +++ b/go/packages/packages_test.go @@ -1854,6 +1854,48 @@ func testMissingDependency(t *testing.T, exporter packagestest.Exporter) { } } +func TestAdHocContains(t *testing.T) { packagestest.TestAll(t, testAdHocContains) } +func testAdHocContains(t *testing.T, exporter packagestest.Exporter) { + exported := packagestest.Export(t, exporter, []packagestest.Module{{ + Name: "golang.org/fake", + Files: map[string]interface{}{ + "a/a.go": `package a;`, + }}}) + defer exported.Cleanup() + + tmpfile, err := ioutil.TempFile("", "adhoc*.go") + filename := tmpfile.Name() + if err != nil { + t.Fatal(err) + } + fmt.Fprint(tmpfile, `package main; import "fmt"; func main() { fmt.Println("time for coffee") }`) + if err := tmpfile.Close(); err != nil { + t.Fatal(err) + } + + defer func() { + if err := os.Remove(filename); err != nil { + t.Fatal(err) + } + }() + + exported.Config.Mode = packages.NeedImports | packages.NeedFiles + pkgs, err := packages.Load(exported.Config, filename) + if err != nil { + t.Fatal(err) + } + if len(pkgs) != 1 && pkgs[0].PkgPath != "command-line-arguments" { + t.Fatalf("packages.Load: want [command-line-arguments], got %v", pkgs) + } + pkg := pkgs[0] + if _, ok := pkg.Imports["fmt"]; !ok || len(pkg.Imports) != 1 { + t.Fatalf("Imports of loaded package: want [fmt], got %v", pkg.Imports) + } + if len(pkg.GoFiles) != 1 || pkg.GoFiles[0] != filename { + t.Fatalf("GoFiles of loaded packge: want [%s], got %v", filename, pkg.GoFiles) + } +} + func errorMessages(errors []packages.Error) []string { var msgs []string for _, err := range errors {