// Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package gcexportdata import ( "fmt" "go/token" "go/types" "os" ) // NewImporter returns a new instance of the types.Importer interface // that reads type information from export data files written by gc. // The Importer also satisfies types.ImporterFrom. // // Export data files are located using "go build" workspace conventions // and the build.Default context. // // Use this importer instead of go/importer.For("gc", ...) to avoid the // version-skew problems described in the documentation of this package, // or to control the FileSet or access the imports map populated during // package loading. // func NewImporter(fset *token.FileSet, imports map[string]*types.Package) types.ImporterFrom { return importer{fset, imports} } type importer struct { fset *token.FileSet imports map[string]*types.Package } func (imp importer) Import(importPath string) (*types.Package, error) { return imp.ImportFrom(importPath, "", 0) } func (imp importer) ImportFrom(importPath, srcDir string, mode types.ImportMode) (_ *types.Package, err error) { filename, path := Find(importPath, srcDir) if filename == "" { if importPath == "unsafe" { // Even for unsafe, call Find first in case // the package was vendored. return types.Unsafe, nil } return nil, fmt.Errorf("can't find import: %s", importPath) } if pkg, ok := imp.imports[path]; ok && pkg.Complete() { return pkg, nil // cache hit } // open file f, err := os.Open(filename) if err != nil { return nil, err } defer func() { f.Close() if err != nil { // add file name to error err = fmt.Errorf("reading export data: %s: %v", filename, err) } }() r, err := NewReader(f) if err != nil { return nil, err } return Read(r, imp.fset, imp.imports, path) }