Home | History | Annotate | Download | only in importer
      1 // Copyright 2015 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 importer provides access to export data importers.
      6 package importer
      7 
      8 import (
      9 	"go/build"
     10 	"go/internal/gccgoimporter"
     11 	"go/internal/gcimporter"
     12 	"go/internal/srcimporter"
     13 	"go/token"
     14 	"go/types"
     15 	"io"
     16 	"runtime"
     17 )
     18 
     19 // A Lookup function returns a reader to access package data for
     20 // a given import path, or an error if no matching package is found.
     21 type Lookup func(path string) (io.ReadCloser, error)
     22 
     23 // For returns an Importer for importing from installed packages
     24 // for the compilers "gc" and "gccgo", or for importing directly
     25 // from the source if the compiler argument is "source". In this
     26 // latter case, importing may fail under circumstances where the
     27 // exported API is not entirely defined in pure Go source code
     28 // (if the package API depends on cgo-defined entities, the type
     29 // checker won't have access to those).
     30 //
     31 // If lookup is nil, the default package lookup mechanism for the
     32 // given compiler is used, and the resulting importer attempts
     33 // to resolve relative and absolute import paths to canonical
     34 // import path IDs before finding the imported file.
     35 //
     36 // If lookup is non-nil, then the returned importer calls lookup
     37 // each time it needs to resolve an import path. In this mode
     38 // the importer can only be invoked with canonical import paths
     39 // (not relative or absolute ones); it is assumed that the translation
     40 // to canonical import paths is being done by the client of the
     41 // importer.
     42 func For(compiler string, lookup Lookup) types.Importer {
     43 	switch compiler {
     44 	case "gc":
     45 		return &gcimports{
     46 			packages: make(map[string]*types.Package),
     47 			lookup:   lookup,
     48 		}
     49 
     50 	case "gccgo":
     51 		var inst gccgoimporter.GccgoInstallation
     52 		if err := inst.InitFromDriver("gccgo"); err != nil {
     53 			return nil
     54 		}
     55 		return &gccgoimports{
     56 			packages: make(map[string]*types.Package),
     57 			importer: inst.GetImporter(nil, nil),
     58 			lookup:   lookup,
     59 		}
     60 
     61 	case "source":
     62 		if lookup != nil {
     63 			panic("source importer for custom import path lookup not supported (issue #13847).")
     64 		}
     65 
     66 		return srcimporter.New(&build.Default, token.NewFileSet(), make(map[string]*types.Package))
     67 	}
     68 
     69 	// compiler not supported
     70 	return nil
     71 }
     72 
     73 // Default returns an Importer for the compiler that built the running binary.
     74 // If available, the result implements types.ImporterFrom.
     75 func Default() types.Importer {
     76 	return For(runtime.Compiler, nil)
     77 }
     78 
     79 // gc importer
     80 
     81 type gcimports struct {
     82 	packages map[string]*types.Package
     83 	lookup   Lookup
     84 }
     85 
     86 func (m *gcimports) Import(path string) (*types.Package, error) {
     87 	return m.ImportFrom(path, "" /* no vendoring */, 0)
     88 }
     89 
     90 func (m *gcimports) ImportFrom(path, srcDir string, mode types.ImportMode) (*types.Package, error) {
     91 	if mode != 0 {
     92 		panic("mode must be 0")
     93 	}
     94 	return gcimporter.Import(m.packages, path, srcDir, m.lookup)
     95 }
     96 
     97 // gccgo importer
     98 
     99 type gccgoimports struct {
    100 	packages map[string]*types.Package
    101 	importer gccgoimporter.Importer
    102 	lookup   Lookup
    103 }
    104 
    105 func (m *gccgoimports) Import(path string) (*types.Package, error) {
    106 	return m.ImportFrom(path, "" /* no vendoring */, 0)
    107 }
    108 
    109 func (m *gccgoimports) ImportFrom(path, srcDir string, mode types.ImportMode) (*types.Package, error) {
    110 	if mode != 0 {
    111 		panic("mode must be 0")
    112 	}
    113 	return m.importer(m.packages, path, srcDir, m.lookup)
    114 }
    115