cuelang.org/go@v0.13.0/cue/load/loader.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 // Files in this package are to a large extent based on Go files from the following 18 // Go packages: 19 // - cmd/go/internal/load 20 // - go/build 21 22 import ( 23 "path/filepath" 24 25 "cuelang.org/go/cue/build" 26 "cuelang.org/go/cue/errors" 27 "cuelang.org/go/cue/token" 28 "cuelang.org/go/internal/mod/modpkgload" 29 ) 30 31 type loader struct { 32 cfg *Config 33 tagger *tagger 34 stk importStack 35 pkgs *modpkgload.Packages 36 37 // dirCachedBuildFiles caches the work involved when reading a 38 // directory. It is keyed by directory name. When we descend into 39 // subdirectories to load patterns such as ./... we often end up 40 // loading parent directories many times over; this cache 41 // amortizes that work. 42 dirCachedBuildFiles map[string]cachedDirFiles 43 } 44 45 type cachedDirFiles struct { 46 err errors.Error 47 filenames []string 48 } 49 50 func newLoader(c *Config, tg *tagger, pkgs *modpkgload.Packages) *loader { 51 return &loader{ 52 cfg: c, 53 tagger: tg, 54 pkgs: pkgs, 55 dirCachedBuildFiles: make(map[string]cachedDirFiles), 56 } 57 } 58 59 func (l *loader) abs(filename string) string { 60 if !isLocalImport(filename) { 61 return filename 62 } 63 return filepath.Join(l.cfg.Dir, filename) 64 } 65 66 func (l *loader) errPkgf(importPos []token.Pos, format string, args ...interface{}) *PackageError { 67 err := &PackageError{ 68 ImportStack: l.stk.Copy(), 69 Message: errors.NewMessagef(format, args...), 70 } 71 err.fillPos(l.cfg.Dir, importPos) 72 return err 73 } 74 75 // cueFilesPackage creates a package for building a collection of CUE files 76 // (typically named on the command line). 77 func (l *loader) cueFilesPackage(files []*build.File) *build.Instance { 78 // ModInit() // TODO: support modules 79 pkg := l.cfg.Context.NewInstance(l.cfg.Dir, nil) 80 81 for _, bf := range files { 82 f := bf.Filename 83 if f == "-" { 84 continue 85 } 86 if !filepath.IsAbs(f) { 87 f = filepath.Join(l.cfg.Dir, f) 88 } 89 fi, err := l.cfg.fileSystem.stat(f) 90 if err != nil { 91 return l.cfg.newErrInstance(errors.Wrapf(err, token.NoPos, "could not find file %v", f)) 92 } 93 if fi.IsDir() { 94 return l.cfg.newErrInstance(errors.Newf(token.NoPos, "file is a directory %v", f)) 95 } 96 } 97 98 fp := newFileProcessor(l.cfg, pkg, l.tagger) 99 if l.cfg.Package == "*" { 100 fp.allPackages = true 101 pkg.PkgName = "_" 102 } 103 for _, bf := range files { 104 fp.add(l.cfg.Dir, bf, allowAnonymous|allowExcludedFiles) 105 } 106 107 // TODO: ModImportFromFiles(files) 108 pkg.Dir = l.cfg.Dir 109 rewriteFiles(pkg, pkg.Dir, true) 110 for _, err := range errors.Errors(fp.finalize(pkg)) { // ImportDir(&ctxt, dir, 0) 111 var x *NoFilesError 112 if len(pkg.OrphanedFiles) == 0 || !errors.As(err, &x) { 113 pkg.ReportError(err) 114 } 115 } 116 // TODO: Support module importing. 117 // if ModDirImportPath != nil { 118 // // Use the effective import path of the directory 119 // // for deciding visibility during pkg.load. 120 // bp.ImportPath = ModDirImportPath(dir) 121 // } 122 123 pkg.User = true 124 l.addFiles(pkg) 125 126 _ = pkg.Complete() 127 pkg.DisplayPath = "command-line-arguments" 128 129 return pkg 130 } 131 132 // addFiles populates p.Files by reading CUE syntax from p.BuildFiles. 133 func (l *loader) addFiles(p *build.Instance) { 134 for _, bf := range p.BuildFiles { 135 f, err := l.cfg.fileSystem.getCUESyntax(bf) 136 if err != nil { 137 p.ReportError(errors.Promote(err, "load")) 138 } 139 _ = p.AddSyntax(f) 140 } 141 }