gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/golang.org/x/tools/go/gcexportdata/importer.go (about)

     1  // Copyright 2016 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 gcexportdata
     6  
     7  import (
     8  	"fmt"
     9  	"go/token"
    10  	"go/types"
    11  	"os"
    12  )
    13  
    14  // NewImporter returns a new instance of the types.Importer interface
    15  // that reads type information from export data files written by gc.
    16  // The Importer also satisfies types.ImporterFrom.
    17  //
    18  // Export data files are located using "go build" workspace conventions
    19  // and the build.Default context.
    20  //
    21  // Use this importer instead of go/importer.For("gc", ...) to avoid the
    22  // version-skew problems described in the documentation of this package,
    23  // or to control the FileSet or access the imports map populated during
    24  // package loading.
    25  //
    26  func NewImporter(fset *token.FileSet, imports map[string]*types.Package) types.ImporterFrom {
    27  	return importer{fset, imports}
    28  }
    29  
    30  type importer struct {
    31  	fset    *token.FileSet
    32  	imports map[string]*types.Package
    33  }
    34  
    35  func (imp importer) Import(importPath string) (*types.Package, error) {
    36  	return imp.ImportFrom(importPath, "", 0)
    37  }
    38  
    39  func (imp importer) ImportFrom(importPath, srcDir string, mode types.ImportMode) (_ *types.Package, err error) {
    40  	filename, path := Find(importPath, srcDir)
    41  	if filename == "" {
    42  		if importPath == "unsafe" {
    43  			// Even for unsafe, call Find first in case
    44  			// the package was vendored.
    45  			return types.Unsafe, nil
    46  		}
    47  		return nil, fmt.Errorf("can't find import: %s", importPath)
    48  	}
    49  
    50  	if pkg, ok := imp.imports[path]; ok && pkg.Complete() {
    51  		return pkg, nil // cache hit
    52  	}
    53  
    54  	// open file
    55  	f, err := os.Open(filename)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	defer func() {
    60  		f.Close()
    61  		if err != nil {
    62  			// add file name to error
    63  			err = fmt.Errorf("reading export data: %s: %v", filename, err)
    64  		}
    65  	}()
    66  
    67  	r, err := NewReader(f)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	return Read(r, imp.fset, imp.imports, path)
    73  }