src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

gcimporter.go (3136B)


      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 // This file is a reduced copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go.
      6 
      7 // Package gcimporter provides various functions for reading
      8 // gc-generated object files that can be used to implement the
      9 // Importer interface defined by the Go 1.5 standard library package.
     10 //
     11 // The encoding is deterministic: if the encoder is applied twice to
     12 // the same types.Package data structure, both encodings are equal.
     13 // This property may be important to avoid spurious changes in
     14 // applications such as build systems.
     15 //
     16 // However, the encoder is not necessarily idempotent. Importing an
     17 // exported package may yield a types.Package that, while it
     18 // represents the same set of Go types as the original, may differ in
     19 // the details of its internal representation. Because of these
     20 // differences, re-encoding the imported package may yield a
     21 // different, but equally valid, encoding of the package.
     22 package gcimporter // import "golang.org/x/tools/internal/gcimporter"
     23 
     24 import (
     25 	"bufio"
     26 	"fmt"
     27 	"go/token"
     28 	"go/types"
     29 	"io"
     30 	"os"
     31 )
     32 
     33 const (
     34 	// Enable debug during development: it adds some additional checks, and
     35 	// prevents errors from being recovered.
     36 	debug = false
     37 
     38 	// If trace is set, debugging output is printed to std out.
     39 	trace = false
     40 )
     41 
     42 // Import imports a gc-generated package given its import path and srcDir, adds
     43 // the corresponding package object to the packages map, and returns the object.
     44 // The packages map must contain all packages already imported.
     45 //
     46 // Import is only used in tests.
     47 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) {
     48 	var rc io.ReadCloser
     49 	var id string
     50 	if lookup != nil {
     51 		// With custom lookup specified, assume that caller has
     52 		// converted path to a canonical import path for use in the map.
     53 		if path == "unsafe" {
     54 			return types.Unsafe, nil
     55 		}
     56 		id = path
     57 
     58 		// No need to re-import if the package was imported completely before.
     59 		if pkg = packages[id]; pkg != nil && pkg.Complete() {
     60 			return
     61 		}
     62 		f, err := lookup(path)
     63 		if err != nil {
     64 			return nil, err
     65 		}
     66 		rc = f
     67 	} else {
     68 		var filename string
     69 		filename, id, err = FindPkg(path, srcDir)
     70 		if filename == "" {
     71 			if path == "unsafe" {
     72 				return types.Unsafe, nil
     73 			}
     74 			return nil, err
     75 		}
     76 
     77 		// no need to re-import if the package was imported completely before
     78 		if pkg = packages[id]; pkg != nil && pkg.Complete() {
     79 			return
     80 		}
     81 
     82 		// open file
     83 		f, err := os.Open(filename)
     84 		if err != nil {
     85 			return nil, err
     86 		}
     87 		defer func() {
     88 			if err != nil {
     89 				// add file name to error
     90 				err = fmt.Errorf("%s: %v", filename, err)
     91 			}
     92 		}()
     93 		rc = f
     94 	}
     95 	defer rc.Close()
     96 
     97 	buf := bufio.NewReader(rc)
     98 	data, err := ReadUnified(buf)
     99 	if err != nil {
    100 		err = fmt.Errorf("import %q: %v", path, err)
    101 		return
    102 	}
    103 
    104 	// unified: emitted by cmd/compile since go1.20.
    105 	_, pkg, err = UImportData(fset, packages, data, id)
    106 
    107 	return
    108 }