Source file src/go/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  // Package gcimporter implements Import for gc-generated object files.
     6  package gcimporter // import "go/internal/gcimporter"
     7  
     8  import (
     9  	"bufio"
    10  	"fmt"
    11  	"go/token"
    12  	"go/types"
    13  	"internal/exportdata"
    14  	"internal/pkgbits"
    15  	"io"
    16  	"os"
    17  )
    18  
    19  // Import imports a gc-generated package given its import path and srcDir, adds
    20  // the corresponding package object to the packages map, and returns the object.
    21  // The packages map must contain all packages already imported.
    22  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) {
    23  	var rc io.ReadCloser
    24  	var id string
    25  	if lookup != nil {
    26  		// With custom lookup specified, assume that caller has
    27  		// converted path to a canonical import path for use in the map.
    28  		if path == "unsafe" {
    29  			return types.Unsafe, nil
    30  		}
    31  		id = path
    32  
    33  		// No need to re-import if the package was imported completely before.
    34  		if pkg = packages[id]; pkg != nil && pkg.Complete() {
    35  			return
    36  		}
    37  		f, err := lookup(path)
    38  		if err != nil {
    39  			return nil, err
    40  		}
    41  		rc = f
    42  	} else {
    43  		var filename string
    44  		filename, id, err = exportdata.FindPkg(path, srcDir)
    45  		if filename == "" {
    46  			if path == "unsafe" {
    47  				return types.Unsafe, nil
    48  			}
    49  			return nil, err
    50  		}
    51  
    52  		// no need to re-import if the package was imported completely before
    53  		if pkg = packages[id]; pkg != nil && pkg.Complete() {
    54  			return
    55  		}
    56  
    57  		// open file
    58  		f, err := os.Open(filename)
    59  		if err != nil {
    60  			return nil, err
    61  		}
    62  		defer func() {
    63  			if err != nil {
    64  				// add file name to error
    65  				err = fmt.Errorf("%s: %v", filename, err)
    66  			}
    67  		}()
    68  		rc = f
    69  	}
    70  	defer rc.Close()
    71  
    72  	buf := bufio.NewReader(rc)
    73  	data, err := exportdata.ReadUnified(buf)
    74  	if err != nil {
    75  		err = fmt.Errorf("import %q: %v", path, err)
    76  		return
    77  	}
    78  	s := string(data)
    79  
    80  	input := pkgbits.NewPkgDecoder(id, s)
    81  	pkg = readUnifiedPackage(fset, nil, packages, input)
    82  
    83  	return
    84  }
    85  

View as plain text