@@ -12,7 +12,6 @@ import (
12
12
"bytes"
13
13
"encoding/binary"
14
14
"fmt"
15
- "go/ast"
16
15
"go/constant"
17
16
"go/token"
18
17
"go/types"
@@ -26,6 +25,41 @@ import (
26
25
"golang.org/x/tools/internal/typeparams"
27
26
)
28
27
28
+ // IExportShallow encodes "shallow" export data for the specified package.
29
+ //
30
+ // No promises are made about the encoding other than that it can be
31
+ // decoded by the same version of IIExportShallow. If you plan to save
32
+ // export data in the file system, be sure to include a cryptographic
33
+ // digest of the executable in the key to avoid version skew.
34
+ func IExportShallow (fset * token.FileSet , pkg * types.Package ) ([]byte , error ) {
35
+ // In principle this operation can only fail if out.Write fails,
36
+ // but that's impossible for bytes.Buffer---and as a matter of
37
+ // fact iexportCommon doesn't even check for I/O errors.
38
+ // TODO(adonovan): handle I/O errors properly.
39
+ // TODO(adonovan): use byte slices throughout, avoiding copying.
40
+ const bundle , shallow = false , true
41
+ var out bytes.Buffer
42
+ err := iexportCommon (& out , fset , bundle , shallow , iexportVersion , []* types.Package {pkg })
43
+ return out .Bytes (), err
44
+ }
45
+
46
+ // IImportShallow decodes "shallow" types.Package data encoded by IExportShallow
47
+ // in the same executable. This function cannot import data from
48
+ // cmd/compile or gcexportdata.Write.
49
+ func IImportShallow (fset * token.FileSet , imports map [string ]* types.Package , data []byte , path string , insert InsertType ) (* types.Package , error ) {
50
+ const bundle = false
51
+ pkgs , err := iimportCommon (fset , imports , data , bundle , path , insert )
52
+ if err != nil {
53
+ return nil , err
54
+ }
55
+ return pkgs [0 ], nil
56
+ }
57
+
58
+ // InsertType is the type of a function that creates a types.TypeName
59
+ // object for a named type and inserts it into the scope of the
60
+ // specified Package.
61
+ type InsertType = func (pkg * types.Package , name string )
62
+
29
63
// Current bundled export format version. Increase with each format change.
30
64
// 0: initial implementation
31
65
const bundleVersion = 0
@@ -36,15 +70,17 @@ const bundleVersion = 0
36
70
// The package path of the top-level package will not be recorded,
37
71
// so that calls to IImportData can override with a provided package path.
38
72
func IExportData (out io.Writer , fset * token.FileSet , pkg * types.Package ) error {
39
- return iexportCommon (out , fset , false , iexportVersion , []* types.Package {pkg })
73
+ const bundle , shallow = false , false
74
+ return iexportCommon (out , fset , bundle , shallow , iexportVersion , []* types.Package {pkg })
40
75
}
41
76
42
77
// IExportBundle writes an indexed export bundle for pkgs to out.
43
78
func IExportBundle (out io.Writer , fset * token.FileSet , pkgs []* types.Package ) error {
44
- return iexportCommon (out , fset , true , iexportVersion , pkgs )
79
+ const bundle , shallow = true , false
80
+ return iexportCommon (out , fset , bundle , shallow , iexportVersion , pkgs )
45
81
}
46
82
47
- func iexportCommon (out io.Writer , fset * token.FileSet , bundle bool , version int , pkgs []* types.Package ) (err error ) {
83
+ func iexportCommon (out io.Writer , fset * token.FileSet , bundle , shallow bool , version int , pkgs []* types.Package ) (err error ) {
48
84
if ! debug {
49
85
defer func () {
50
86
if e := recover (); e != nil {
@@ -61,6 +97,7 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, version int,
61
97
p := iexporter {
62
98
fset : fset ,
63
99
version : version ,
100
+ shallow : shallow ,
64
101
allPkgs : map [* types.Package ]bool {},
65
102
stringIndex : map [string ]uint64 {},
66
103
declIndex : map [types.Object ]uint64 {},
@@ -82,7 +119,7 @@ func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, version int,
82
119
for _ , pkg := range pkgs {
83
120
scope := pkg .Scope ()
84
121
for _ , name := range scope .Names () {
85
- if ast .IsExported (name ) {
122
+ if token .IsExported (name ) {
86
123
p .pushDecl (scope .Lookup (name ))
87
124
}
88
125
}
@@ -205,7 +242,8 @@ type iexporter struct {
205
242
out * bytes.Buffer
206
243
version int
207
244
208
- localpkg * types.Package
245
+ shallow bool // don't put types from other packages in the index
246
+ localpkg * types.Package // (nil in bundle mode)
209
247
210
248
// allPkgs tracks all packages that have been referenced by
211
249
// the export data, so we can ensure to include them in the
@@ -256,6 +294,11 @@ func (p *iexporter) pushDecl(obj types.Object) {
256
294
panic ("cannot export package unsafe" )
257
295
}
258
296
297
+ // Shallow export data: don't index decls from other packages.
298
+ if p .shallow && obj .Pkg () != p .localpkg {
299
+ return
300
+ }
301
+
259
302
if _ , ok := p .declIndex [obj ]; ok {
260
303
return
261
304
}
@@ -497,7 +540,7 @@ func (w *exportWriter) pkg(pkg *types.Package) {
497
540
w .string (w .exportPath (pkg ))
498
541
}
499
542
500
- func (w * exportWriter ) qualifiedIdent (obj types.Object ) {
543
+ func (w * exportWriter ) qualifiedType (obj * types.TypeName ) {
501
544
name := w .p .exportName (obj )
502
545
503
546
// Ensure any referenced declarations are written out too.
@@ -556,11 +599,11 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
556
599
return
557
600
}
558
601
w .startType (definedType )
559
- w .qualifiedIdent (t .Obj ())
602
+ w .qualifiedType (t .Obj ())
560
603
561
604
case * typeparams.TypeParam :
562
605
w .startType (typeParamType )
563
- w .qualifiedIdent (t .Obj ())
606
+ w .qualifiedType (t .Obj ())
564
607
565
608
case * types.Pointer :
566
609
w .startType (pointerType )
0 commit comments