]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: include imports in 'go list -e' output even after parse errors
authorJay Conrod <jayconrod@google.com>
Thu, 5 Dec 2019 18:28:57 +0000 (13:28 -0500)
committerJay Conrod <jayconrod@google.com>
Thu, 5 Dec 2019 21:42:53 +0000 (21:42 +0000)
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: Bryan C. Mills <bcmills@google.com>
src/cmd/go/internal/load/pkg.go
src/cmd/go/testdata/script/list_parse_err.txt [new file with mode: 0644]
src/go/build/build.go

index 0d63187e0625fa1dd58ec054042eec7098f6ca68..369a79b7164d3779152b511d2b8c29808cd45ea9 100644 (file)
@@ -11,6 +11,7 @@ import (
        "errors"
        "fmt"
        "go/build"
+       "go/scanner"
        "go/token"
        "io/ioutil"
        "os"
@@ -1519,17 +1520,30 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
                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 _, ok := err.(*build.NoGoError); ok {
                        err = &NoGoError{Package: p}
                }
                p.Incomplete = true
-               err = base.ExpandScanner(err)
-               p.Error = &PackageError{
-                       ImportStack: stk.Copy(),
-                       Err:         err,
+
+               setError(base.ExpandScanner(err))
+               if _, isScanErr := err.(scanner.ErrorList); !isScanErr {
+                       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"
@@ -1545,7 +1559,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
                if InstallTargetDir(p) == StalePath {
                        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)
-                       p.Error = &PackageError{Err: e}
+                       setError(e)
                        return
                }
                elem := p.DefaultExecName()
@@ -1658,10 +1672,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
        inputs := p.AllFiles()
        f1, f2 := str.FoldDup(inputs)
        if f1 != "" {
-               p.Error = &PackageError{
-                       ImportStack: stk.Copy(),
-                       Err:         fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2),
-               }
+               setError(fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2))
                return
        }
 
@@ -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.
        for _, file := range inputs {
                if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
-                       p.Error = &PackageError{
-                               ImportStack: stk.Copy(),
-                               Err:         fmt.Errorf("invalid input file name %q", file),
-                       }
+                       setError(fmt.Errorf("invalid input file name %q", file))
                        return
                }
        }
        if name := pathpkg.Base(p.ImportPath); !SafeArg(name) {
-               p.Error = &PackageError{
-                       ImportStack: stk.Copy(),
-                       Err:         fmt.Errorf("invalid input directory name %q", name),
-               }
+               setError(fmt.Errorf("invalid input directory name %q", name))
                return
        }
        if !SafeArg(p.ImportPath) {
-               p.Error = &PackageError{
-                       ImportStack: stk.Copy(),
-                       Err:         ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath),
-               }
+               setError(ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath))
                return
        }
 
@@ -1737,13 +1739,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
                // 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.
        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, " ")))
diff --git a/src/cmd/go/testdata/script/list_parse_err.txt b/src/cmd/go/testdata/script/list_parse_err.txt
new file mode 100644 (file)
index 0000000..5aacaa8
--- /dev/null
@@ -0,0 +1,17 @@
+# '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
index 62b70c26f12ff7464ef5b6903a1b1e1c53398096..a1ea8af81f8c23304e13da49d5e05106073d3913 100644 (file)
@@ -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 {
                p.AllTags = append(p.AllTags, tag)
        }
@@ -1000,6 +993,12 @@ Found:
                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
 }