Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

Commit

Permalink
cue/load: expose error types
Browse files Browse the repository at this point in the history
Change-Id: I6910aa23d385182c5bc7b83d617289c783b73873
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/4662
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Jan 16, 2020
1 parent 00757a9 commit 1288f89
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 52 deletions.
75 changes: 31 additions & 44 deletions cue/load/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,64 +24,52 @@ import (
"cuelang.org/go/cue/token"
)

func lastError(p *build.Instance) *packageError {
func lastError(p *build.Instance) *PackageError {
if p == nil {
return nil
}
switch v := p.Err.(type) {
case *packageError:
case *PackageError:
return v
}
return nil
}

func report(p *build.Instance, err *packageError) {
func report(p *build.Instance, err *PackageError) {
if err != nil {
p.ReportError(err)
}
}

// shortPath returns an absolute or relative name for path, whatever is shorter.
func shortPath(cwd, path string) string {
if cwd == "" {
return path
}
if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {
return rel
}
return path
}

// A packageError describes an error loading information about a package.
type packageError struct {
// A PackageError describes an error loading information about a package.
type PackageError struct {
ImportStack []string // shortest path from package named on command line to this one
Pos token.Pos // position of error
errors.Message // the error itself
IsImportCycle bool `json:"-"` // the error is an import cycle
Hard bool `json:"-"` // whether the error is soft or hard; soft errors are ignored in some places
IsImportCycle bool // the error is an import cycle
}

func (p *packageError) Position() token.Pos { return p.Pos }
func (p *packageError) InputPositions() []token.Pos { return nil }
func (p *packageError) Path() []string { return nil }
func (p *PackageError) Position() token.Pos { return p.Pos }
func (p *PackageError) InputPositions() []token.Pos { return nil }
func (p *PackageError) Path() []string { return nil }

func (l *loader) errPkgf(importPos []token.Pos, format string, args ...interface{}) *packageError {
err := &packageError{
func (l *loader) errPkgf(importPos []token.Pos, format string, args ...interface{}) *PackageError {
err := &PackageError{
ImportStack: l.stk.Copy(),
Message: errors.NewMessage(format, args),
}
err.fillPos(l.cfg.Dir, importPos)
return err
}

func (p *packageError) fillPos(cwd string, positions []token.Pos) {
func (p *PackageError) fillPos(cwd string, positions []token.Pos) {
if len(positions) > 0 && !p.Pos.IsValid() {
p.Pos = positions[0]
}
}

// TODO(localize)
func (p *packageError) Error() string {
func (p *PackageError) Error() string {
// Import cycles deserve special treatment.
if p.IsImportCycle {
return fmt.Sprintf("%s\npackage %s\n", p.Message, strings.Join(p.ImportStack, "\n\timports "))
Expand All @@ -97,25 +85,24 @@ func (p *packageError) Error() string {
return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Message.Error()
}

// noCUEError is the error used by Import to describe a directory
// containing no buildable Go source files. (It may still contain
// test files, files hidden by build tags, and so on.)
type noCUEError struct {
// NoFilesError is the error used by Import to describe a directory
// containing no usable source files. (It may still contain
// tool files, files hidden by build tags, and so on.)
type NoFilesError struct {
Package *build.Instance

Dir string
Ignored bool // whether any Go files were ignored due to build tags
ignored bool // whether any Go files were ignored due to build tags
}

func (e *noCUEError) Position() token.Pos { return token.NoPos }
func (e *noCUEError) InputPositions() []token.Pos { return nil }
func (e *noCUEError) Path() []string { return nil }
func (e *NoFilesError) Position() token.Pos { return token.NoPos }
func (e *NoFilesError) InputPositions() []token.Pos { return nil }
func (e *NoFilesError) Path() []string { return nil }

// TODO(localize)
func (e *noCUEError) Msg() (string, []interface{}) { return e.Error(), nil }
func (e *NoFilesError) Msg() (string, []interface{}) { return e.Error(), nil }

// TODO(localize)
func (e *noCUEError) Error() string {
func (e *NoFilesError) Error() string {
// Count files beginning with _, which we will pretend don't exist at all.
dummy := 0
for _, name := range e.Package.IgnoredCUEFiles {
Expand Down Expand Up @@ -150,19 +137,19 @@ func (e *noCUEError) Error() string {
return "no CUE files in " + path
}

// multiplePackageError describes a directory containing
// multiple buildable Go source files for multiple packages.
type multiplePackageError struct {
// MultiplePackageError describes an attempt to build a package composed of
// CUE files from different packages.
type MultiplePackageError struct {
Dir string // directory containing files
Packages []string // package names found
Files []string // corresponding files: Files[i] declares package Packages[i]
}

func (e *multiplePackageError) Position() token.Pos { return token.NoPos }
func (e *multiplePackageError) InputPositions() []token.Pos { return nil }
func (e *multiplePackageError) Path() []string { return nil }
func (e *MultiplePackageError) Position() token.Pos { return token.NoPos }
func (e *MultiplePackageError) InputPositions() []token.Pos { return nil }
func (e *MultiplePackageError) Path() []string { return nil }

func (e *multiplePackageError) Msg() (string, []interface{}) {
func (e *MultiplePackageError) Msg() (string, []interface{}) {
return "found packages %s (%s) and %s (%s) in %s", []interface{}{
e.Packages[0],
e.Files[0],
Expand All @@ -172,7 +159,7 @@ func (e *multiplePackageError) Msg() (string, []interface{}) {
}
}

func (e *multiplePackageError) Error() string {
func (e *MultiplePackageError) Error() string {
// Error string limited to two entries for compatibility.
format, args := e.Msg()
return fmt.Sprintf(format, args...)
Expand Down
4 changes: 2 additions & 2 deletions cue/load/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ func (fp *fileProcessor) finalize() errors.Error {
return fp.err
}
if countCUEFiles(fp.c, p) == 0 && !fp.c.DataFiles {
fp.err = errors.Append(fp.err, &noCUEError{Package: p, Dir: p.Dir, Ignored: len(p.IgnoredCUEFiles) > 0})
fp.err = errors.Append(fp.err, &NoFilesError{Package: p, ignored: len(p.IgnoredCUEFiles) > 0})
return fp.err
}

Expand Down Expand Up @@ -364,7 +364,7 @@ func (fp *fileProcessor) add(pos token.Pos, root, path string, mode importMode)
p.IgnoredCUEFiles = append(p.IgnoredCUEFiles, fullPath)
return false
}
return badFile(&multiplePackageError{
return badFile(&MultiplePackageError{
Dir: p.Dir,
Packages: []string{p.PkgName, pkg},
Files: []string{fp.firstFile, name},
Expand Down
10 changes: 5 additions & 5 deletions cue/load/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,31 +50,31 @@ func TestEmptyImport(t *testing.T) {

func TestEmptyFolderImport(t *testing.T) {
_, err := getInst(".", testdata+"empty")
if _, ok := err.(*noCUEError); !ok {
if _, ok := err.(*NoFilesError); !ok {
t.Fatal(`Import("testdata/empty") did not return NoCUEError.`)
}
}

func TestIgnoredCUEFilesImport(t *testing.T) {
_, err := getInst(".", testdata+"ignored")
var e *noCUEError
var e *NoFilesError
ok := xerrors.As(err, &e)
if !ok {
t.Fatal(`Import("testdata/ignored") did not return NoCUEError.`)
}
if !e.Ignored {
if !e.ignored {
t.Fatal(`Import("testdata/ignored") should have ignored CUE files.`)
}
}

func TestMultiplePackageImport(t *testing.T) {
_, err := getInst(".", testdata+"multi")
mpe, ok := err.(*multiplePackageError)
mpe, ok := err.(*MultiplePackageError)
if !ok {
t.Fatal(`Import("testdata/multi") did not return MultiplePackageError.`)
}
mpe.Dir = ""
want := &multiplePackageError{
want := &MultiplePackageError{
Packages: []string{"main", "test_package"},
Files: []string{"file.cue", "file_appengine.cue"},
}
Expand Down
2 changes: 1 addition & 1 deletion cue/load/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func (l *loader) matchPackagesInFS(pattern, pkgName string) *match {
switch err.(type) {
case nil:
break
case *noCUEError:
case *NoFilesError:
if c.DataFiles && len(p.DataFiles) > 0 {
break
}
Expand Down

0 comments on commit 1288f89

Please sign in to comment.