// 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.
package gcimporter // import "golang.org/x/tools/internal/gcimporter"import ()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)varexportMapsync.Map// package dir → func() (string, bool)// lookupGorootExport returns the location of the export data// (normally found in the build cache, but located in GOROOT/pkg// in prior Go releases) for the package located in pkgDir.//// (We use the package's directory instead of its import path// mainly to simplify handling of the packages in src/vendor// and cmd/vendor.)func ( string) (string, bool) { , := exportMap.Load()if ! {var (sync.Oncestring ) , _ = exportMap.LoadOrStore(, func() (string, bool) { .Do(func() { := exec.Command("go", "list", "-export", "-f", "{{.Export}}", ) .Dir = build.Default.GOROOTvar []byte , := .Output()if != nil {return } := strings.Split(string(bytes.TrimSpace()), "\n")iflen() != 1 {return } = [0] })return , != "" }) }return .(func() (string, bool))()}varpkgExts = [...]string{".a", ".o"}// FindPkg returns the filename and unique package id for an import// path based on package information provided by build.Import (using// the build.Default build.Context). A relative srcDir is interpreted// relative to the current working directory.// If no file was found, an empty filename is returned.func (, string) (, string) {if == "" {return }varstringswitch {default:// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" // Don't require the source files to be present.if , := filepath.Abs(); == nil { // see issue 14282 = } , := build.Import(, , build.FindOnly|build.AllowBinary)if .PkgObj == "" {varboolif .Goroot && .Dir != "" { , = lookupGorootExport(.Dir) }if ! { = // make sure we have an id to print in error messagereturn } } else { = strings.TrimSuffix(.PkgObj, ".a") = .ImportPath }casebuild.IsLocalImport():// "./x" -> "/this/directory/x.ext", "/this/directory/x" = filepath.Join(, ) = casefilepath.IsAbs():// for completeness only - go/build.Import // does not support absolute imports // "/x" -> "/x.ext", "/x" = = }iffalse { // for debuggingif != {fmt.Printf("%s -> %s\n", , ) } }if != "" {if , := os.Stat(); == nil && !.IsDir() {return } }// try extensionsfor , := rangepkgExts { = + if , := os.Stat(); == nil && !.IsDir() {return } } = ""// not foundreturn}// 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.func ( map[string]*types.Package, , string, func( string) (io.ReadCloser, error)) ( *types.Package, error) {vario.ReadCloservar , stringif != nil {// With custom lookup specified, assume that caller has // converted path to a canonical import path for use in the map.if == "unsafe" {returntypes.Unsafe, nil } = // No need to re-import if the package was imported completely before.if = []; != nil && .Complete() {return } , := ()if != nil {returnnil, } = } else { , = FindPkg(, )if == "" {if == "unsafe" {returntypes.Unsafe, nil }returnnil, fmt.Errorf("can't find import: %q", ) }// no need to re-import if the package was imported completely beforeif = []; != nil && .Complete() {return }// open file , := os.Open()if != nil {returnnil, }deferfunc() {if != nil {// add file name to error = fmt.Errorf("%s: %v", , ) } }() = }defer .Close()varstringvarint64 := bufio.NewReader()if , , = FindExportData(); != nil {return }switch {case"$$B\n":var []byte , = ioutil.ReadAll()if != nil {break }// TODO(gri): allow clients of go/importer to provide a FileSet. // Or, define a new standard go/types/gcexportdata package. := token.NewFileSet()// The indexed export format starts with an 'i'; the older // binary export format starts with a 'c', 'd', or 'v' // (from "version"). Select appropriate importer.iflen() > 0 {switch [0] {case'i': , , := IImportData(, , [1:], )return , case'v', 'c', 'd': , , := BImportData(, , , )return , case'u': , , := UImportData(, , [1:], )return , default: := len()if > 10 { = 10 }returnnil, fmt.Errorf("unexpected export data with prefix %q for path %s", string([:]), ) } }default: = fmt.Errorf("unknown export data header: %q", ) }return}func ( types.Type) types.Type {if , := .(*types.Pointer); != nil {return .Elem() }return}typebyPath []*types.Packagefunc ( byPath) () int { returnlen() }func ( byPath) (, int) { [], [] = [], [] }func ( byPath) (, int) bool { return [].Path() < [].Path() }
The pages are generated with Goldsv0.4.9. (GOOS=linux GOARCH=amd64)