From cb42bbeb799cab99c22c42762584b4ab07e4daf3 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 5 Apr 2019 17:46:00 -0400 Subject: [PATCH] go/packages: add a work around for go list behavior for missing ad-hoc package If a file in an ad-hoc package doesn't exist, go list should exit 0 and return an dummy package with an error set on it. Since it doesn't do that yet, add a work-around. Updates golang/go#29280 Change-Id: I6019f28ce4770582f274919d1aa35d85a634687e Reviewed-on: https://go-review.googlesource.com/c/tools/+/171018 Run-TryBot: Michael Matloob Reviewed-by: Ian Cottrell --- go/packages/golist.go | 11 ++++-- go/packages/packages_test.go | 65 +++++++++++++++++++++++------------- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/go/packages/golist.go b/go/packages/golist.go index a25c3acb1af..132d28347e8 100644 --- a/go/packages/golist.go +++ b/go/packages/golist.go @@ -761,8 +761,15 @@ func invokeGo(cfg *Config, args ...string) (*bytes.Buffer, error) { // the error in the Err section of stdout in case -e option is provided. // This fix is provided for backwards compatibility. if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "named files must be .go files") { - output := fmt.Sprintf(`{"ImportPath": "","Incomplete": true,"Error": {"Pos": "","Err": %s}}`, - strconv.Quote(strings.Trim(stderr.String(), "\n"))) + output := fmt.Sprintf(`{"ImportPath": "command-line-arguments","Incomplete": true,"Error": {"Pos": "","Err": %q}}`, + strings.Trim(stderr.String(), "\n")) + return bytes.NewBufferString(output), nil + } + + // Workaround for #29280: go list -e has incorrect behavior when an ad-hoc package doesn't exist. + if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "no such file or directory") { + output := fmt.Sprintf(`{"ImportPath": "command-line-arguments","Incomplete": true,"Error": {"Pos": "","Err": %q}}`, + strings.Trim(stderr.String(), "\n")) return bytes.NewBufferString(output), nil } diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go index d3e22504b2e..9c33ebeca09 100644 --- a/go/packages/packages_test.go +++ b/go/packages/packages_test.go @@ -313,29 +313,6 @@ func TestLoadAbsolutePath(t *testing.T) { } } -func TestReturnErrorWhenUsingNonGoFiles(t *testing.T) { - exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{ - Name: "golang.org/gopatha", - Files: map[string]interface{}{ - "a/a.go": `package a`, - }}, { - Name: "golang.org/gopathb", - Files: map[string]interface{}{ - "b/b.c": `package b`, - }}}) - defer exported.Cleanup() - config := packages.Config{} - _, err := packages.Load(&config, "a/a.go", "b/b.c") - if err == nil { - t.Fatalf("should have failed with an error") - } - got := err.Error() - want := "named files must be .go files" - if !strings.Contains(got, want) { - t.Fatalf("want error message: %s, got: %s", want, got) - } -} - func TestVendorImports(t *testing.T) { exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{ Name: "golang.org/fake", @@ -1723,7 +1700,47 @@ func testErrorMissingFile(t *testing.T, exporter packagestest.Exporter) { if err != nil { t.Fatal(err) } - t.Log(pkgs) + if len(pkgs) == 0 && runtime.GOOS == "windows" { + t.Skip("Issue #31344: the ad-hoc command-line-arguments package isn't created on windows") + } + if len(pkgs) != 1 || pkgs[0].PkgPath != "command-line-arguments" { + t.Fatalf("packages.Load: want [command-line-arguments], got %v", pkgs) + } + if len(pkgs[0].Errors) == 0 { + t.Errorf("result of Load: want package with errors, got none: %+v", pkgs[0]) + } +} + +func TestReturnErrorWhenUsingNonGoFiles(t *testing.T) { + packagestest.TestAll(t, testReturnErrorWhenUsingNonGoFiles) +} +func testReturnErrorWhenUsingNonGoFiles(t *testing.T, exporter packagestest.Exporter) { + exported := packagestest.Export(t, exporter, []packagestest.Module{{ + Name: "golang.org/gopatha", + Files: map[string]interface{}{ + "a/a.go": `package a`, + }}, { + Name: "golang.org/gopathb", + Files: map[string]interface{}{ + "b/b.c": `package b`, + }}}) + defer exported.Cleanup() + config := packages.Config{} + pkgs, err := packages.Load(&config, "a/a.go", "b/b.c") + 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) + } + if len(pkgs[0].Errors) != 1 { + t.Fatalf("result of Load: want package with one error, got: %+v", pkgs[0]) + } + got := pkgs[0].Errors[0].Error() + want := "named files must be .go files" + if !strings.Contains(got, want) { + t.Fatalf("want error message: %s, got: %s", want, got) + } } func errorMessages(errors []packages.Error) []string {