Skip to content

Commit 597f577

Browse files
committed
go/packages: handle more errors that 'go list' prints to stderr
This change adds special handling for two more errors that 'go list' prints to stderr: 1. when trying to construct an ad-hoc package from files in multiple directories 2. the "unexpected directory layout" error (#24854) Change-Id: Icbd14bcc02c2ca9676dc0449e155ff817da038cb Reviewed-on: https://go-review.googlesource.com/c/tools/+/190077 Run-TryBot: Dominik Honnef <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Cottrell <[email protected]> Reviewed-by: Michael Matloob <[email protected]>
1 parent 60bb302 commit 597f577

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

go/packages/golist.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,11 @@ func invokeGo(cfg *Config, args ...string) (*bytes.Buffer, error) {
847847
return nil, goTooOldError{fmt.Errorf("unsupported version of go: %s: %s", exitErr, stderr)}
848848
}
849849

850+
// Related to #24854
851+
if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "unexpected directory layout") {
852+
return nil, fmt.Errorf("%s", stderr.String())
853+
}
854+
850855
// This error only appears in stderr. See golang.org/cl/166398 for a fix in go list to show
851856
// the error in the Err section of stdout in case -e option is provided.
852857
// This fix is provided for backwards compatibility.
@@ -856,6 +861,13 @@ func invokeGo(cfg *Config, args ...string) (*bytes.Buffer, error) {
856861
return bytes.NewBufferString(output), nil
857862
}
858863

864+
// Similar to the previous error, but currently lacks a fix in Go.
865+
if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "named files must all be in one directory") {
866+
output := fmt.Sprintf(`{"ImportPath": "command-line-arguments","Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
867+
strings.Trim(stderr.String(), "\n"))
868+
return bytes.NewBufferString(output), nil
869+
}
870+
859871
// Backwards compatibility for Go 1.11 because 1.12 and 1.13 put the directory in the ImportPath.
860872
// If the package doesn't exist, put the absolute path of the directory into the error message,
861873
// as Go 1.13 list does.

go/packages/packages_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,6 +1979,69 @@ func testReturnErrorWhenUsingNonGoFiles(t *testing.T, exporter packagestest.Expo
19791979
}
19801980
}
19811981

1982+
func TestReturnErrorWhenUsingGoFilesInMultipleDirectories(t *testing.T) {
1983+
packagestest.TestAll(t, testReturnErrorWhenUsingGoFilesInMultipleDirectories)
1984+
}
1985+
func testReturnErrorWhenUsingGoFilesInMultipleDirectories(t *testing.T, exporter packagestest.Exporter) {
1986+
exported := packagestest.Export(t, exporter, []packagestest.Module{{
1987+
Name: "golang.org/gopatha",
1988+
Files: map[string]interface{}{
1989+
"a/a.go": `package a`,
1990+
"b/b.go": `package b`,
1991+
}}})
1992+
defer exported.Cleanup()
1993+
want := "named files must all be in one directory"
1994+
pkgs, err := packages.Load(exported.Config, exported.File("golang.org/gopatha", "a/a.go"), exported.File("golang.org/gopatha", "b/b.go"))
1995+
if err != nil {
1996+
// Check if the error returned is the one we expected.
1997+
if !strings.Contains(err.Error(), want) {
1998+
t.Fatalf("want error message: %s, got: %s", want, err.Error())
1999+
}
2000+
return
2001+
}
2002+
if len(pkgs) != 1 || pkgs[0].PkgPath != "command-line-arguments" {
2003+
t.Fatalf("packages.Load: want [command-line-arguments], got %v", pkgs)
2004+
}
2005+
if len(pkgs[0].Errors) != 1 {
2006+
t.Fatalf("result of Load: want package with one error, got: %+v", pkgs[0])
2007+
}
2008+
got := pkgs[0].Errors[0].Error()
2009+
if !strings.Contains(got, want) {
2010+
t.Fatalf("want error message: %s, got: %s", want, got)
2011+
}
2012+
}
2013+
2014+
func TestReturnErrorForUnexpectedDirectoryLayout(t *testing.T) {
2015+
packagestest.TestAll(t, testReturnErrorForUnexpectedDirectoryLayout)
2016+
}
2017+
func testReturnErrorForUnexpectedDirectoryLayout(t *testing.T, exporter packagestest.Exporter) {
2018+
exported := packagestest.Export(t, exporter, []packagestest.Module{{
2019+
Name: "golang.org/gopatha",
2020+
Files: map[string]interface{}{
2021+
"a/testdata/a.go": `package a; import _ "b"`,
2022+
"a/vendor/b/b.go": `package b; import _ "fmt"`,
2023+
}}})
2024+
defer exported.Cleanup()
2025+
want := "unexpected directory layout"
2026+
// triggering this error requires a relative package path
2027+
exported.Config.Dir = filepath.Dir(exported.File("golang.org/gopatha", "a/testdata/a.go"))
2028+
pkgs, err := packages.Load(exported.Config, ".")
2029+
2030+
// This error doesn't seem to occur in module mode; so only
2031+
// complain if we get zero packages while also getting no error.
2032+
if err == nil {
2033+
if len(pkgs) == 0 {
2034+
// TODO(dh): we'll need to expand on the error check if/when Go stops emitting this error
2035+
t.Fatalf("want error, got nil")
2036+
}
2037+
return
2038+
}
2039+
// Check if the error returned is the one we expected.
2040+
if !strings.Contains(err.Error(), want) {
2041+
t.Fatalf("want error message: %s, got: %s", want, err.Error())
2042+
}
2043+
}
2044+
19822045
func TestMissingDependency(t *testing.T) { packagestest.TestAll(t, testMissingDependency) }
19832046
func testMissingDependency(t *testing.T, exporter packagestest.Exporter) {
19842047
exported := packagestest.Export(t, exporter, []packagestest.Module{{

0 commit comments

Comments
 (0)