Source file src/cmd/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go
1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file is a reduced copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go. 6 7 // Package gcimporter provides various functions for reading 8 // gc-generated object files that can be used to implement the 9 // Importer interface defined by the Go 1.5 standard library package. 10 // 11 // The encoding is deterministic: if the encoder is applied twice to 12 // the same types.Package data structure, both encodings are equal. 13 // This property may be important to avoid spurious changes in 14 // applications such as build systems. 15 // 16 // However, the encoder is not necessarily idempotent. Importing an 17 // exported package may yield a types.Package that, while it 18 // represents the same set of Go types as the original, may differ in 19 // the details of its internal representation. Because of these 20 // differences, re-encoding the imported package may yield a 21 // different, but equally valid, encoding of the package. 22 package gcimporter // import "golang.org/x/tools/internal/gcimporter" 23 24 import ( 25 "bufio" 26 "fmt" 27 "go/token" 28 "go/types" 29 "io" 30 "os" 31 ) 32 33 const ( 34 // Enable debug during development: it adds some additional checks, and 35 // prevents errors from being recovered. 36 debug = false 37 38 // If trace is set, debugging output is printed to std out. 39 trace = false 40 ) 41 42 // Import imports a gc-generated package given its import path and srcDir, adds 43 // the corresponding package object to the packages map, and returns the object. 44 // The packages map must contain all packages already imported. 45 // 46 // Import is only used in tests. 47 func Import(fset *token.FileSet, packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) { 48 var rc io.ReadCloser 49 var id string 50 if lookup != nil { 51 // With custom lookup specified, assume that caller has 52 // converted path to a canonical import path for use in the map. 53 if path == "unsafe" { 54 return types.Unsafe, nil 55 } 56 id = path 57 58 // No need to re-import if the package was imported completely before. 59 if pkg = packages[id]; pkg != nil && pkg.Complete() { 60 return 61 } 62 f, err := lookup(path) 63 if err != nil { 64 return nil, err 65 } 66 rc = f 67 } else { 68 var filename string 69 filename, id, err = FindPkg(path, srcDir) 70 if filename == "" { 71 if path == "unsafe" { 72 return types.Unsafe, nil 73 } 74 return nil, err 75 } 76 77 // no need to re-import if the package was imported completely before 78 if pkg = packages[id]; pkg != nil && pkg.Complete() { 79 return 80 } 81 82 // open file 83 f, err := os.Open(filename) 84 if err != nil { 85 return nil, err 86 } 87 defer func() { 88 if err != nil { 89 // add file name to error 90 err = fmt.Errorf("%s: %v", filename, err) 91 } 92 }() 93 rc = f 94 } 95 defer rc.Close() 96 97 buf := bufio.NewReader(rc) 98 data, err := ReadUnified(buf) 99 if err != nil { 100 err = fmt.Errorf("import %q: %v", path, err) 101 return 102 } 103 104 // unified: emitted by cmd/compile since go1.20. 105 _, pkg, err = UImportData(fset, packages, data, id) 106 107 return 108 } 109