Skip to content

Commit 0a80f6c

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 0a80f6c

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

go/packages/golist.go

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,17 @@ func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, q
269269
// modCacheRegexp splits a path in a module cache into module, module version, and package.
270270
var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`)
271271

272+
// noFileRe looks for a package name in a "no Go files in" errors line that is output by go list.
273+
var noFileRe = regexp.MustCompile(`(?m)^go build ([\p{L}\p{Nd}\/.]+): (no Go files in.*)$`)
274+
275+
// cgoErrRe attempts to detect cgo errors from go list stderr output
276+
var cgoErrRe = regexp.MustCompile(
277+
`(collect2: error: ld returned)|(could not determine kind of name for C\.)|` +
278+
`(fatal error: \S+.(c|h): No such file or directory)`)
279+
280+
// goListErrRe attempts to extract errors from go list stderr output
281+
var goListErrRe = regexp.MustCompile(`(?m)^# ([\p{L}\p{Nd}\/.]+)\n((?:[^#].*\n)+)`)
282+
272283
func runNamedQueries(cfg *Config, driver driver, response *responseDeduper, queries []string) error {
273284
// calling `go env` isn't free; bail out if there's nothing to do.
274285
if len(queries) == 0 {
@@ -553,6 +564,8 @@ type jsonPackage struct {
553564
ForTest string // q in a "p [q.test]" package, else ""
554565
DepOnly bool
555566

567+
Gen bool // generated by this code
568+
556569
Error *jsonPackageError
557570
}
558571

@@ -611,11 +624,15 @@ func golistDriver(cfg *Config, words ...string) (*driverResponse, error) {
611624
}
612625

613626
if old, found := seen[p.ImportPath]; found {
614-
if !reflect.DeepEqual(p, old) {
627+
if p.Gen {
628+
// new package is generated, skip it
629+
continue
630+
} else if !reflect.DeepEqual(p, old) {
615631
return nil, fmt.Errorf("internal error: go list gives conflicting information for package %v", p.ImportPath)
632+
} else if !old.Gen {
633+
// skip the duplicate if the old package wasn't generated
634+
continue
616635
}
617-
// skip the duplicate
618-
continue
619636
}
620637
seen[p.ImportPath] = p
621638

@@ -804,15 +821,23 @@ func invokeGo(cfg *Config, args ...string) (*bytes.Buffer, error) {
804821
// a zero exit status and set an error on that package.
805822
if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "no Go files in") {
806823
// 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]
824+
for _, matches := range noFileRe.FindAllStringSubmatch(stderr.String(), -1) {
825+
stdout.WriteString(fmt.Sprintf("\n"+`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q},"Gen": true}`,
826+
matches[1], matches[2]))
812827
}
813-
output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
814-
importPath, strings.Trim(stderrStr, "\n"))
815-
return bytes.NewBufferString(output), nil
828+
return stdout, nil
829+
}
830+
831+
// Workaround for an instance of golang.org/issue/26755: go list -e will
832+
// return a non-zero exit status if cgo preprocessing fails. But it should
833+
// return a zero exit status and set an error on that package.
834+
if len(stderr.String()) > 0 && cgoErrRe.MatchString(stderr.String()) {
835+
for _, matches := range goListErrRe.FindAllStringSubmatch(stderr.String(), -1) {
836+
stdout.WriteString(fmt.Sprintf("\n"+`{"ImportPath": %q,"Incomplete":true,"Error": {"Pos": "","Err": %q},"Gen": true}`,
837+
matches[1], strings.Trim(matches[2], "\n")))
838+
}
839+
840+
return stdout, nil
816841
}
817842

818843
// Export mode entails a build.

0 commit comments

Comments
 (0)