// Copyright 2011 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. // This file is a reduced copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go. // Package gcimporter provides various functions for reading // gc-generated object files that can be used to implement the // Importer interface defined by the Go 1.5 standard library package. // // The encoding is deterministic: if the encoder is applied twice to // the same types.Package data structure, both encodings are equal. // This property may be important to avoid spurious changes in // applications such as build systems. // // However, the encoder is not necessarily idempotent. Importing an // exported package may yield a types.Package that, while it // represents the same set of Go types as the original, may differ in // the details of its internal representation. Because of these // differences, re-encoding the imported package may yield a // different, but equally valid, encoding of the package. package gcimporter // import "golang.org/x/tools/internal/gcimporter" import ( "bufio" "fmt" "go/token" "go/types" "io" "os" ) const ( // Enable debug during development: it adds some additional checks, and // prevents errors from being recovered. debug = false // If trace is set, debugging output is printed to std out. trace = false ) // Import imports a gc-generated package given its import path and srcDir, adds // the corresponding package object to the packages map, and returns the object. // The packages map must contain all packages already imported. // // Import is only used in tests. 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) { var rc io.ReadCloser var id string if lookup != nil { // With custom lookup specified, assume that caller has // converted path to a canonical import path for use in the map. if path == "unsafe" { return types.Unsafe, nil } id = path // No need to re-import if the package was imported completely before. if pkg = packages[id]; pkg != nil && pkg.Complete() { return } f, err := lookup(path) if err != nil { return nil, err } rc = f } else { var filename string filename, id, err = FindPkg(path, srcDir) if filename == "" { if path == "unsafe" { return types.Unsafe, nil } return nil, err } // no need to re-import if the package was imported completely before if pkg = packages[id]; pkg != nil && pkg.Complete() { return } // open file f, err := os.Open(filename) if err != nil { return nil, err } defer func() { if err != nil { // add file name to error err = fmt.Errorf("%s: %v", filename, err) } }() rc = f } defer rc.Close() buf := bufio.NewReader(rc) data, err := ReadUnified(buf) if err != nil { err = fmt.Errorf("import %q: %v", path, err) return } // unified: emitted by cmd/compile since go1.20. _, pkg, err = UImportData(fset, packages, data, id) return }