Skip to content

Commit a0370a2

Browse files
committed
go/packages: Ignore more errors in go list
Adds some hacks to work around go list bugs causing golang/go#31462 and golang/go#32755. In addition, appends error messages generated in this manner to stdout instead of discarding stdout entirely, and ensures that this does not cause a conflicting package error by adding an internal field to packageJson.
1 parent 2214986 commit a0370a2

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

go/packages/golist.go

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,8 @@ type jsonPackage struct {
553553
ForTest string // q in a "p [q.test]" package, else ""
554554
DepOnly bool
555555

556+
Gen bool // generated by this code
557+
556558
Error *jsonPackageError
557559
}
558560

@@ -611,11 +613,15 @@ func golistDriver(cfg *Config, words ...string) (*driverResponse, error) {
611613
}
612614

613615
if old, found := seen[p.ImportPath]; found {
614-
if !reflect.DeepEqual(p, old) {
616+
if p.Gen {
617+
// new package is generated, skip it
618+
continue
619+
} else if !reflect.DeepEqual(p, old) {
615620
return nil, fmt.Errorf("internal error: go list gives conflicting information for package %v", p.ImportPath)
621+
} else if !old.Gen {
622+
// skip the duplicate if the old package wasn't generated
623+
continue
616624
}
617-
// skip the duplicate
618-
continue
619625
}
620626
seen[p.ImportPath] = p
621627

@@ -804,15 +810,29 @@ func invokeGo(cfg *Config, args ...string) (*bytes.Buffer, error) {
804810
// a zero exit status and set an error on that package.
805811
if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "no Go files in") {
806812
// try to extract package name from string
807-
stderrStr := stderr.String()
808-
var importPath string
809-
colon := strings.Index(stderrStr, ":")
810-
if colon > 0 && strings.HasPrefix(stderrStr, "go build ") {
811-
importPath = stderrStr[len("go build "):colon]
813+
noFileRe := regexp.MustCompile(`(?m)^go build ([\p{L}\p{Nd}\/.]+): (no Go files in.*)$`)
814+
815+
for _, matches := range noFileRe.FindAllStringSubmatch(stderr.String(), -1) {
816+
stdout.WriteString(fmt.Sprintf("\n"+`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q},"Gen": true}`,
817+
matches[1], matches[2]))
812818
}
813-
output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
814-
importPath, strings.Trim(stderrStr, "\n"))
815-
return bytes.NewBufferString(output), nil
819+
return stdout, nil
820+
}
821+
822+
// Workaround for an instance of golang.org/issue/26755: go list -e will
823+
// return a non-zero exit status if cgo preprocessing fails. But it should
824+
// return a zero exit status and set an error on that package.
825+
if len(stderr.String()) > 0 &&
826+
(strings.Contains(stderr.String(), "collect2: error: ld returned") ||
827+
strings.Contains(stderr.String(), "could not determine kind of name for C.")) {
828+
pkgRe := regexp.MustCompile(`(?m)^# ([\p{L}\p{Nd}\/.]+)\n((?:[^#].*\n)+)`)
829+
830+
for _, matches := range pkgRe.FindAllStringSubmatch(stderr.String(), -1) {
831+
stdout.WriteString(fmt.Sprintf("\n"+`{"ImportPath": %q,"Incomplete":true,"Error": {"Pos": "","Err": %q},"Gen": true}`,
832+
matches[1], strings.Trim(matches[2], "\n")))
833+
}
834+
835+
return stdout, nil
816836
}
817837

818838
// Export mode entails a build.

0 commit comments

Comments
 (0)