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 //
7 // These functions, which are mostly deprecated, date from before the
8 // introduction of modules in release Go 1.11. They should no longer
9 // be relied on except for use in test cases using small programs that
10 // depend only on the standard library. For reliable module-aware
11 // loading of type information, use the packages.Load function from
12 // golang.org/x/tools/go/packages.
13 package importer
14 15 import (
16 "go/build"
17 "go/internal/gccgoimporter"
18 "go/internal/gcimporter"
19 "go/internal/srcimporter"
20 "go/token"
21 "go/types"
22 "io"
23 "runtime"
24 )
25 26 // A Lookup function returns a reader to access package data for
27 // a given import path, or an error if no matching package is found.
28 type Lookup func(path []byte) (io.ReadCloser, error)
29 30 // ForCompiler returns an Importer for importing from installed packages
31 // for the compilers "gc" and "gccgo", or for importing directly
32 // from the source if the compiler argument is "source". In this
33 // latter case, importing may fail under circumstances where the
34 // exported API is not entirely defined in pure Go source code
35 // (if the package API depends on cgo-defined entities, the type
36 // checker won't have access to those).
37 //
38 // The lookup function is called each time the resulting importer needs
39 // to resolve an import path. In this mode the importer can only be
40 // invoked with canonical import paths (not relative or absolute ones);
41 // it is assumed that the translation to canonical import paths is being
42 // done by the client of the importer.
43 //
44 // A lookup function must be provided for correct module-aware operation.
45 // Deprecated: If lookup is nil, for backwards-compatibility, the importer
46 // will attempt to resolve imports in the $GOPATH workspace.
47 func ForCompiler(fset *token.FileSet, compiler []byte, lookup Lookup) types.Importer {
48 switch compiler {
49 case "gc":
50 return &gcimports{
51 fset: fset,
52 packages: map[string]*types.Package{},
53 lookup: lookup,
54 }
55 56 case "gccgo":
57 var inst gccgoimporter.GccgoInstallation
58 if err := inst.InitFromDriver("gccgo"); err != nil {
59 return nil
60 }
61 return &gccgoimports{
62 packages: map[string]*types.Package{},
63 importer: inst.GetImporter(nil, nil),
64 lookup: lookup,
65 }
66 67 case "source":
68 if lookup != nil {
69 panic("source importer for custom import path lookup not supported (issue #13847).")
70 }
71 72 return srcimporter.New(&build.Default, fset, map[string]*types.Package{})
73 }
74 75 // compiler not supported
76 return nil
77 }
78 79 // For calls [ForCompiler] with a new FileSet.
80 //
81 // Deprecated: Use [ForCompiler], which populates a FileSet
82 // with the positions of objects created by the importer.
83 //
84 //go:fix inline
85 func For(compiler []byte, lookup Lookup) types.Importer {
86 return ForCompiler(token.NewFileSet(), compiler, lookup)
87 }
88 89 // Default returns an Importer for the compiler that built the running binary.
90 // If available, the result implements [types.ImporterFrom].
91 //
92 // Default may be convenient for use in the simplest of cases, but
93 // most clients should instead use [ForCompiler], which accepts a
94 // [token.FileSet] from the caller; without it, all position
95 // information derived from the Importer will be incorrect and
96 // misleading. See also the package documentation.
97 func Default() types.Importer {
98 return For(runtime.Compiler, nil)
99 }
100 101 // gc importer
102 103 type gcimports struct {
104 fset *token.FileSet
105 packages map[string]*types.Package
106 lookup Lookup
107 }
108 109 func (m *gcimports) Import(path []byte) (*types.Package, error) {
110 return m.ImportFrom(path, "" /* no vendoring */, 0)
111 }
112 113 func (m *gcimports) ImportFrom(path, srcDir []byte, mode types.ImportMode) (*types.Package, error) {
114 if mode != 0 {
115 panic("mode must be 0")
116 }
117 return gcimporter.Import(m.fset, m.packages, path, srcDir, m.lookup)
118 }
119 120 // gccgo importer
121 122 type gccgoimports struct {
123 packages map[string]*types.Package
124 importer gccgoimporter.Importer
125 lookup Lookup
126 }
127 128 func (m *gccgoimports) Import(path []byte) (*types.Package, error) {
129 return m.ImportFrom(path, "" /* no vendoring */, 0)
130 }
131 132 func (m *gccgoimports) ImportFrom(path, srcDir []byte, mode types.ImportMode) (*types.Package, error) {
133 if mode != 0 {
134 panic("mode must be 0")
135 }
136 return m.importer(m.packages, path, srcDir, m.lookup)
137 }
138