GoPLS Viewer

Home|gopls/go/gcexportdata/gcexportdata.go
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 provides functions for locating, reading, and
6// writing export data files containing type information produced by the
7// gc compiler.  This package supports go1.7 export data format and all
8// later versions.
9//
10// Although it might seem convenient for this package to live alongside
11// go/types in the standard library, this would cause version skew
12// problems for developer tools that use it, since they must be able to
13// consume the outputs of the gc compiler both before and after a Go
14// update such as from Go 1.7 to Go 1.8.  Because this package lives in
15// golang.org/x/tools, sites can update their version of this repo some
16// time before the Go 1.8 release and rebuild and redeploy their
17// developer tools, which will then be able to consume both Go 1.7 and
18// Go 1.8 export data files, so they will work before and after the
19// Go update. (See discussion at https://golang.org/issue/15651.)
20package gcexportdata // import "golang.org/x/tools/go/gcexportdata"
21
22import (
23    "bufio"
24    "bytes"
25    "encoding/json"
26    "fmt"
27    "go/token"
28    "go/types"
29    "io"
30    "os/exec"
31
32    "golang.org/x/tools/internal/gcimporter"
33)
34
35// Find returns the name of an object (.o) or archive (.a) file
36// containing type information for the specified import path,
37// using the go command.
38// If no file was found, an empty filename is returned.
39//
40// A relative srcDir is interpreted relative to the current working directory.
41//
42// Find also returns the package's resolved (canonical) import path,
43// reflecting the effects of srcDir and vendoring on importPath.
44//
45// Deprecated: Use the higher-level API in golang.org/x/tools/go/packages,
46// which is more efficient.
47func Find(importPathsrcDir string) (filenamepath string) {
48    cmd := exec.Command("go""list""-json""-export""--"importPath)
49    cmd.Dir = srcDir
50    outerr := cmd.CombinedOutput()
51    if err != nil {
52        return """"
53    }
54    var data struct {
55        ImportPath string
56        Export     string
57    }
58    json.Unmarshal(out, &data)
59    return data.Exportdata.ImportPath
60}
61
62// NewReader returns a reader for the export data section of an object
63// (.o) or archive (.a) file read from r.  The new reader may provide
64// additional trailing data beyond the end of the export data.
65func NewReader(r io.Reader) (io.Readererror) {
66    buf := bufio.NewReader(r)
67    _sizeerr := gcimporter.FindExportData(buf)
68    if err != nil {
69        return nilerr
70    }
71
72    if size >= 0 {
73        // We were given an archive and found the __.PKGDEF in it.
74        // This tells us the size of the export data, and we don't
75        // need to return the entire file.
76        return &io.LimitedReader{
77            Rbuf,
78            Nsize,
79        }, nil
80    } else {
81        // We were given an object file. As such, we don't know how large
82        // the export data is and must return the entire file.
83        return bufnil
84    }
85}
86
87// readAll works the same way as io.ReadAll, but avoids allocations and copies
88// by preallocating a byte slice of the necessary size if the size is known up
89// front. This is always possible when the input is an archive. In that case,
90// NewReader will return the known size using an io.LimitedReader.
91func readAll(r io.Reader) ([]byteerror) {
92    if lrok := r.(*io.LimitedReader); ok {
93        data := make([]bytelr.N)
94        _err := io.ReadFull(lrdata)
95        return dataerr
96    }
97    return io.ReadAll(r)
98}
99
100// Read reads export data from in, decodes it, and returns type
101// information for the package.
102//
103// The package path (effectively its linker symbol prefix) is
104// specified by path, since unlike the package name, this information
105// may not be recorded in the export data.
106//
107// File position information is added to fset.
108//
109// Read may inspect and add to the imports map to ensure that references
110// within the export data to other packages are consistent.  The caller
111// must ensure that imports[path] does not exist, or exists but is
112// incomplete (see types.Package.Complete), and Read inserts the
113// resulting package into this map entry.
114//
115// On return, the state of the reader is undefined.
116func Read(in io.Readerfset *token.FileSetimports map[string]*types.Packagepath string) (*types.Packageerror) {
117    dataerr := readAll(in)
118    if err != nil {
119        return nilfmt.Errorf("reading export data for %q: %v"patherr)
120    }
121
122    if bytes.HasPrefix(data, []byte("!<arch>")) {
123        return nilfmt.Errorf("can't read export data for %q directly from an archive file (call gcexportdata.NewReader first to extract export data)"path)
124    }
125
126    // The indexed export format starts with an 'i'; the older
127    // binary export format starts with a 'c', 'd', or 'v'
128    // (from "version"). Select appropriate importer.
129    if len(data) > 0 {
130        switch data[0] {
131        case 'i':
132            _pkgerr := gcimporter.IImportData(fsetimportsdata[1:], path)
133            return pkgerr
134
135        case 'v''c''d':
136            _pkgerr := gcimporter.BImportData(fsetimportsdatapath)
137            return pkgerr
138
139        case 'u':
140            _pkgerr := gcimporter.UImportData(fsetimportsdata[1:], path)
141            return pkgerr
142
143        default:
144            l := len(data)
145            if l > 10 {
146                l = 10
147            }
148            return nilfmt.Errorf("unexpected export data with prefix %q for path %s"string(data[:l]), path)
149        }
150    }
151    return nilfmt.Errorf("empty export data for %s"path)
152}
153
154// Write writes encoded type information for the specified package to out.
155// The FileSet provides file position information for named objects.
156func Write(out io.Writerfset *token.FileSetpkg *types.Packageerror {
157    if _err := io.WriteString(out"i"); err != nil {
158        return err
159    }
160    return gcimporter.IExportData(outfsetpkg)
161}
162
163// ReadBundle reads an export bundle from in, decodes it, and returns type
164// information for the packages.
165// File position information is added to fset.
166//
167// ReadBundle may inspect and add to the imports map to ensure that references
168// within the export bundle to other packages are consistent.
169//
170// On return, the state of the reader is undefined.
171//
172// Experimental: This API is experimental and may change in the future.
173func ReadBundle(in io.Readerfset *token.FileSetimports map[string]*types.Package) ([]*types.Packageerror) {
174    dataerr := readAll(in)
175    if err != nil {
176        return nilfmt.Errorf("reading export bundle: %v"err)
177    }
178    return gcimporter.IImportBundle(fsetimportsdata)
179}
180
181// WriteBundle writes encoded type information for the specified packages to out.
182// The FileSet provides file position information for named objects.
183//
184// Experimental: This API is experimental and may change in the future.
185func WriteBundle(out io.Writerfset *token.FileSetpkgs []*types.Packageerror {
186    return gcimporter.IExportBundle(outfsetpkgs)
187}
188
MembersX
Find.importPath
Read.path
Write.pkg
ReadBundle.imports
ReadBundle.err
WriteBundle.fset
io
exec
NewReader.buf
readAll.r
Read.imports
Read.BlockStmt.BlockStmt.pkg
Write
Write.err
Find.srcDir
NewReader
ReadBundle.fset
WriteBundle.pkgs
Find.path
Find.err
Read.BlockStmt.BlockStmt._
Read.BlockStmt.BlockStmt.err
ReadBundle
WriteBundle.out
json
Read.in
readAll.BlockStmt.err
Read.BlockStmt.BlockStmt.l
Write.out
Write._
gcimporter
Find
readAll.BlockStmt.data
Read.fset
Read.data
ReadBundle.data
bytes
NewReader.size
NewReader.r
NewReader.err
readAll
readAll.BlockStmt._
ReadBundle.in
bufio
Find.out
NewReader._
Read
Read.err
Write.fset
WriteBundle
Find.filename
Find.cmd
Members
X