github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/gcexportdata/importer.go (about) 1 // Copyright 2016 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 package gcexportdata 6 7 import ( 8 "fmt" 9 "go/token" 10 "go/types" 11 "os" 12 ) 13 14 // NewImporter returns a new instance of the types.Importer interface 15 // that reads type information from export data files written by gc. 16 // The Importer also satisfies types.ImporterFrom. 17 // 18 // Export data files are located using "go build" workspace conventions 19 // and the build.Default context. 20 // 21 // Use this importer instead of go/importer.For("gc", ...) to avoid the 22 // version-skew problems described in the documentation of this package, 23 // or to control the FileSet or access the imports map populated during 24 // package loading. 25 // 26 // Deprecated: Use the higher-level API in golang.org/x/tools/go/packages, 27 // which is more efficient. 28 func NewImporter(fset *token.FileSet, imports map[string]*types.Package) types.ImporterFrom { 29 return importer{fset, imports} 30 } 31 32 type importer struct { 33 fset *token.FileSet 34 imports map[string]*types.Package 35 } 36 37 func (imp importer) Import(importPath string) (*types.Package, error) { 38 return imp.ImportFrom(importPath, "", 0) 39 } 40 41 func (imp importer) ImportFrom(importPath, srcDir string, mode types.ImportMode) (_ *types.Package, err error) { 42 filename, path := Find(importPath, srcDir) 43 if filename == "" { 44 if importPath == "unsafe" { 45 // Even for unsafe, call Find first in case 46 // the package was vendored. 47 return types.Unsafe, nil 48 } 49 return nil, fmt.Errorf("can't find import: %s", importPath) 50 } 51 52 if pkg, ok := imp.imports[path]; ok && pkg.Complete() { 53 return pkg, nil // cache hit 54 } 55 56 // open file 57 f, err := os.Open(filename) 58 if err != nil { 59 return nil, err 60 } 61 defer func() { 62 f.Close() 63 if err != nil { 64 // add file name to error 65 err = fmt.Errorf("reading export data: %s: %v", filename, err) 66 } 67 }() 68 69 r, err := NewReader(f) 70 if err != nil { 71 return nil, err 72 } 73 74 return Read(r, imp.fset, imp.imports, path) 75 }