Commit 993ec7f6 authored by Jay Conrod's avatar Jay Conrod

cmd/go: include imports in 'go list -e' output even after parse errors

If we aren't able to load imports from one file in a package due to a
parse error (scanner.ErrorList), 'go list -e' should still list
imports in other files.

Fixes #35973

Change-Id: I59f171877949bb7afaf252b6c8a970de22e60c7a
Reviewed-on: https://go-review.googlesource.com/c/go/+/210097
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBryan C. Mills <bcmills@google.com>
parent e3c7ffcd
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"go/build" "go/build"
"go/scanner"
"go/token" "go/token"
"io/ioutil" "io/ioutil"
"os" "os"
...@@ -1519,17 +1520,30 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { ...@@ -1519,17 +1520,30 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
p.Internal.LocalPrefix = dirToImportPath(p.Dir) p.Internal.LocalPrefix = dirToImportPath(p.Dir)
} }
// setError sets p.Error if it hasn't already been set. We may proceed
// after encountering some errors so that 'go list -e' has more complete
// output. If there's more than one error, we should report the first.
setError := func(err error) {
if p.Error == nil {
p.Error = &PackageError{
ImportStack: stk.Copy(),
Err: err,
}
}
}
if err != nil { if err != nil {
if _, ok := err.(*build.NoGoError); ok { if _, ok := err.(*build.NoGoError); ok {
err = &NoGoError{Package: p} err = &NoGoError{Package: p}
} }
p.Incomplete = true p.Incomplete = true
err = base.ExpandScanner(err)
p.Error = &PackageError{ setError(base.ExpandScanner(err))
ImportStack: stk.Copy(), if _, isScanErr := err.(scanner.ErrorList); !isScanErr {
Err: err, return
} }
return // Fall through if there was an error parsing a file. 'go list -e' should
// still report imports and other metadata.
} }
useBindir := p.Name == "main" useBindir := p.Name == "main"
...@@ -1545,7 +1559,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { ...@@ -1545,7 +1559,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
if InstallTargetDir(p) == StalePath { if InstallTargetDir(p) == StalePath {
newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1) newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)
e := ImportErrorf(p.ImportPath, "the %v command has moved; use %v instead.", p.ImportPath, newPath) e := ImportErrorf(p.ImportPath, "the %v command has moved; use %v instead.", p.ImportPath, newPath)
p.Error = &PackageError{Err: e} setError(e)
return return
} }
elem := p.DefaultExecName() elem := p.DefaultExecName()
...@@ -1658,10 +1672,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { ...@@ -1658,10 +1672,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
inputs := p.AllFiles() inputs := p.AllFiles()
f1, f2 := str.FoldDup(inputs) f1, f2 := str.FoldDup(inputs)
if f1 != "" { if f1 != "" {
p.Error = &PackageError{ setError(fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2))
ImportStack: stk.Copy(),
Err: fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2),
}
return return
} }
...@@ -1674,25 +1685,16 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { ...@@ -1674,25 +1685,16 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
// so we shouldn't see any _cgo_ files anyway, but just be safe. // so we shouldn't see any _cgo_ files anyway, but just be safe.
for _, file := range inputs { for _, file := range inputs {
if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") { if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
p.Error = &PackageError{ setError(fmt.Errorf("invalid input file name %q", file))
ImportStack: stk.Copy(),
Err: fmt.Errorf("invalid input file name %q", file),
}
return return
} }
} }
if name := pathpkg.Base(p.ImportPath); !SafeArg(name) { if name := pathpkg.Base(p.ImportPath); !SafeArg(name) {
p.Error = &PackageError{ setError(fmt.Errorf("invalid input directory name %q", name))
ImportStack: stk.Copy(),
Err: fmt.Errorf("invalid input directory name %q", name),
}
return return
} }
if !SafeArg(p.ImportPath) { if !SafeArg(p.ImportPath) {
p.Error = &PackageError{ setError(ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath))
ImportStack: stk.Copy(),
Err: ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath),
}
return return
} }
...@@ -1737,13 +1739,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { ...@@ -1737,13 +1739,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
// code; see issue #16050). // code; see issue #16050).
} }
setError := func(err error) {
p.Error = &PackageError{
ImportStack: stk.Copy(),
Err: err,
}
}
// The gc toolchain only permits C source files with cgo or SWIG. // The gc toolchain only permits C source files with cgo or SWIG.
if len(p.CFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() && cfg.BuildContext.Compiler == "gc" { if len(p.CFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() && cfg.BuildContext.Compiler == "gc" {
setError(fmt.Errorf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " "))) setError(fmt.Errorf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " ")))
......
# 'go list' should report imports, even if some files have parse errors
# before the import block.
go list -e -f '{{range .Imports}}{{.}} {{end}}'
stdout '^fmt '
-- go.mod --
module m
go 1.13
-- a.go --
package a
import "fmt"
-- b.go --
// no package statement
...@@ -976,13 +976,6 @@ Found: ...@@ -976,13 +976,6 @@ Found:
} }
} }
if badGoError != nil {
return p, badGoError
}
if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
return p, &NoGoError{p.Dir}
}
for tag := range allTags { for tag := range allTags {
p.AllTags = append(p.AllTags, tag) p.AllTags = append(p.AllTags, tag)
} }
...@@ -1000,6 +993,12 @@ Found: ...@@ -1000,6 +993,12 @@ Found:
sort.Strings(p.SFiles) sort.Strings(p.SFiles)
} }
if badGoError != nil {
return p, badGoError
}
if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
return p, &NoGoError{p.Dir}
}
return p, pkgerr return p, pkgerr
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment