cuelang.org/go@v0.10.1/cue/load/errors.go (about) 1 // Copyright 2018 The CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package load 16 17 import ( 18 "fmt" 19 "path/filepath" 20 "strings" 21 22 "cuelang.org/go/cue/build" 23 "cuelang.org/go/cue/errors" 24 "cuelang.org/go/cue/token" 25 ) 26 27 // A PackageError describes an error loading information about a package. 28 type PackageError struct { 29 ImportStack []string // shortest path from package named on command line to this one 30 Pos token.Pos // position of error 31 errors.Message // the error itself 32 IsImportCycle bool // the error is an import cycle 33 } 34 35 func (p *PackageError) Position() token.Pos { return p.Pos } 36 func (p *PackageError) InputPositions() []token.Pos { return nil } 37 func (p *PackageError) Path() []string { return p.ImportStack } 38 39 func (p *PackageError) fillPos(cwd string, positions []token.Pos) { 40 if len(positions) > 0 && !p.Pos.IsValid() { 41 p.Pos = positions[0] 42 } 43 } 44 45 // TODO(localize) 46 func (p *PackageError) Error() string { 47 // Import cycles deserve special treatment. 48 if p.IsImportCycle { 49 return fmt.Sprintf("%s\npackage %s\n", p.Message, strings.Join(p.ImportStack, "\n\timports ")) 50 } 51 if p.Pos.IsValid() { 52 // Omit import stack. The full path to the file where the error 53 // is the most important thing. 54 return p.Pos.String() + ": " + p.Message.Error() 55 } 56 if len(p.ImportStack) == 0 { 57 return p.Message.Error() 58 } 59 return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Message.Error() 60 } 61 62 // NoFilesError is the error used by Import to describe a directory 63 // containing no usable source files. (It may still contain 64 // tool files, files hidden by build tags, and so on.) 65 type NoFilesError struct { 66 Package *build.Instance 67 68 ignored bool // whether any CUE files were ignored due to build tags 69 } 70 71 func (e *NoFilesError) Position() token.Pos { return token.NoPos } 72 func (e *NoFilesError) InputPositions() []token.Pos { return nil } 73 func (e *NoFilesError) Path() []string { return nil } 74 75 // TODO(localize) 76 func (e *NoFilesError) Msg() (string, []interface{}) { return e.Error(), nil } 77 78 // TODO(localize) 79 func (e *NoFilesError) Error() string { 80 // Count files beginning with _, which we will pretend don't exist at all. 81 dummy := 0 82 for _, f := range e.Package.IgnoredFiles { 83 if strings.HasPrefix(filepath.Base(f.Filename), "_") { 84 dummy++ 85 } 86 } 87 88 // path := shortPath(e.Package.Root, e.Package.Dir) 89 path := e.Package.DisplayPath 90 91 if len(e.Package.IgnoredFiles) > dummy { 92 b := strings.Builder{} 93 b.WriteString("build constraints exclude all CUE files in ") 94 b.WriteString(path) 95 b.WriteString(":") 96 // CUE files exist, but they were ignored due to build constraints. 97 for _, f := range e.Package.IgnoredFiles { 98 b.WriteString("\n ") 99 b.WriteString(filepath.ToSlash(e.Package.RelPath(f))) 100 if f.ExcludeReason != nil { 101 b.WriteString(": ") 102 b.WriteString(f.ExcludeReason.Error()) 103 } 104 } 105 return b.String() 106 } 107 // if len(e.Package.TestCUEFiles) > 0 { 108 // // Test CUE files exist, but we're not interested in them. 109 // // The double-negative is unfortunate but we want e.Package.Dir 110 // // to appear at the end of error message. 111 // return "no non-test CUE files in " + e.Package.Dir 112 // } 113 return "no CUE files in " + path 114 } 115 116 // MultiplePackageError describes an attempt to build a package composed of 117 // CUE files from different packages. 118 type MultiplePackageError struct { 119 Dir string // directory containing files 120 Packages []string // package names found 121 Files []string // corresponding files: Files[i] declares package Packages[i] 122 } 123 124 func (e *MultiplePackageError) Position() token.Pos { return token.NoPos } 125 func (e *MultiplePackageError) InputPositions() []token.Pos { return nil } 126 func (e *MultiplePackageError) Path() []string { return nil } 127 128 func (e *MultiplePackageError) Msg() (string, []interface{}) { 129 return "found packages %q (%s) and %q (%s) in %q", []interface{}{ 130 e.Packages[0], 131 e.Files[0], 132 e.Packages[1], 133 e.Files[1], 134 e.Dir, 135 } 136 } 137 138 func (e *MultiplePackageError) Error() string { 139 // Error string limited to two entries for compatibility. 140 format, args := e.Msg() 141 return fmt.Sprintf(format, args...) 142 }