build(deps): bump github.com/onsi/ginkgo/v2 from 2.9.2 to 2.11.0
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.9.2 to 2.11.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.9.2...v2.11.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
59
vendor/golang.org/x/tools/internal/event/tag/tag.go
generated
vendored
Normal file
59
vendor/golang.org/x/tools/internal/event/tag/tag.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package tag provides the labels used for telemetry throughout gopls.
|
||||
package tag
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/internal/event/keys"
|
||||
)
|
||||
|
||||
var (
|
||||
// create the label keys we use
|
||||
Method = keys.NewString("method", "")
|
||||
StatusCode = keys.NewString("status.code", "")
|
||||
StatusMessage = keys.NewString("status.message", "")
|
||||
RPCID = keys.NewString("id", "")
|
||||
RPCDirection = keys.NewString("direction", "")
|
||||
File = keys.NewString("file", "")
|
||||
Directory = keys.New("directory", "")
|
||||
URI = keys.New("URI", "")
|
||||
Package = keys.NewString("package", "") // Package ID
|
||||
PackagePath = keys.NewString("package_path", "")
|
||||
Query = keys.New("query", "")
|
||||
Snapshot = keys.NewUInt64("snapshot", "")
|
||||
Operation = keys.NewString("operation", "")
|
||||
|
||||
Position = keys.New("position", "")
|
||||
Category = keys.NewString("category", "")
|
||||
PackageCount = keys.NewInt("packages", "")
|
||||
Files = keys.New("files", "")
|
||||
Port = keys.NewInt("port", "")
|
||||
Type = keys.New("type", "")
|
||||
HoverKind = keys.NewString("hoverkind", "")
|
||||
|
||||
NewServer = keys.NewString("new_server", "A new server was added")
|
||||
EndServer = keys.NewString("end_server", "A server was shut down")
|
||||
|
||||
ServerID = keys.NewString("server", "The server ID an event is related to")
|
||||
Logfile = keys.NewString("logfile", "")
|
||||
DebugAddress = keys.NewString("debug_address", "")
|
||||
GoplsPath = keys.NewString("gopls_path", "")
|
||||
ClientID = keys.NewString("client_id", "")
|
||||
|
||||
Level = keys.NewInt("level", "The logging level")
|
||||
)
|
||||
|
||||
var (
|
||||
// create the stats we measure
|
||||
Started = keys.NewInt64("started", "Count of started RPCs.")
|
||||
ReceivedBytes = keys.NewInt64("received_bytes", "Bytes received.") //, unit.Bytes)
|
||||
SentBytes = keys.NewInt64("sent_bytes", "Bytes sent.") //, unit.Bytes)
|
||||
Latency = keys.NewFloat64("latency_ms", "Elapsed time in milliseconds") //, unit.Milliseconds)
|
||||
)
|
||||
|
||||
const (
|
||||
Inbound = "in"
|
||||
Outbound = "out"
|
||||
)
|
852
vendor/golang.org/x/tools/internal/gcimporter/bexport.go
generated
vendored
852
vendor/golang.org/x/tools/internal/gcimporter/bexport.go
generated
vendored
@ -1,852 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Binary package export.
|
||||
// This file was derived from $GOROOT/src/cmd/compile/internal/gc/bexport.go;
|
||||
// see that file for specification of the format.
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"math"
|
||||
"math/big"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// If debugFormat is set, each integer and string value is preceded by a marker
|
||||
// and position information in the encoding. This mechanism permits an importer
|
||||
// to recognize immediately when it is out of sync. The importer recognizes this
|
||||
// mode automatically (i.e., it can import export data produced with debugging
|
||||
// support even if debugFormat is not set at the time of import). This mode will
|
||||
// lead to massively larger export data (by a factor of 2 to 3) and should only
|
||||
// be enabled during development and debugging.
|
||||
//
|
||||
// NOTE: This flag is the first flag to enable if importing dies because of
|
||||
// (suspected) format errors, and whenever a change is made to the format.
|
||||
const debugFormat = false // default: false
|
||||
|
||||
// Current export format version. Increase with each format change.
|
||||
//
|
||||
// Note: The latest binary (non-indexed) export format is at version 6.
|
||||
// This exporter is still at level 4, but it doesn't matter since
|
||||
// the binary importer can handle older versions just fine.
|
||||
//
|
||||
// 6: package height (CL 105038) -- NOT IMPLEMENTED HERE
|
||||
// 5: improved position encoding efficiency (issue 20080, CL 41619) -- NOT IMPLEMENTED HERE
|
||||
// 4: type name objects support type aliases, uses aliasTag
|
||||
// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used)
|
||||
// 2: removed unused bool in ODCL export (compiler only)
|
||||
// 1: header format change (more regular), export package for _ struct fields
|
||||
// 0: Go1.7 encoding
|
||||
const exportVersion = 4
|
||||
|
||||
// trackAllTypes enables cycle tracking for all types, not just named
|
||||
// types. The existing compiler invariants assume that unnamed types
|
||||
// that are not completely set up are not used, or else there are spurious
|
||||
// errors.
|
||||
// If disabled, only named types are tracked, possibly leading to slightly
|
||||
// less efficient encoding in rare cases. It also prevents the export of
|
||||
// some corner-case type declarations (but those are not handled correctly
|
||||
// with with the textual export format either).
|
||||
// TODO(gri) enable and remove once issues caused by it are fixed
|
||||
const trackAllTypes = false
|
||||
|
||||
type exporter struct {
|
||||
fset *token.FileSet
|
||||
out bytes.Buffer
|
||||
|
||||
// object -> index maps, indexed in order of serialization
|
||||
strIndex map[string]int
|
||||
pkgIndex map[*types.Package]int
|
||||
typIndex map[types.Type]int
|
||||
|
||||
// position encoding
|
||||
posInfoFormat bool
|
||||
prevFile string
|
||||
prevLine int
|
||||
|
||||
// debugging support
|
||||
written int // bytes written
|
||||
indent int // for trace
|
||||
}
|
||||
|
||||
// internalError represents an error generated inside this package.
|
||||
type internalError string
|
||||
|
||||
func (e internalError) Error() string { return "gcimporter: " + string(e) }
|
||||
|
||||
func internalErrorf(format string, args ...interface{}) error {
|
||||
return internalError(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// BExportData returns binary export data for pkg.
|
||||
// If no file set is provided, position info will be missing.
|
||||
func BExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) {
|
||||
if !debug {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
if ierr, ok := e.(internalError); ok {
|
||||
err = ierr
|
||||
return
|
||||
}
|
||||
// Not an internal error; panic again.
|
||||
panic(e)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
p := exporter{
|
||||
fset: fset,
|
||||
strIndex: map[string]int{"": 0}, // empty string is mapped to 0
|
||||
pkgIndex: make(map[*types.Package]int),
|
||||
typIndex: make(map[types.Type]int),
|
||||
posInfoFormat: true, // TODO(gri) might become a flag, eventually
|
||||
}
|
||||
|
||||
// write version info
|
||||
// The version string must start with "version %d" where %d is the version
|
||||
// number. Additional debugging information may follow after a blank; that
|
||||
// text is ignored by the importer.
|
||||
p.rawStringln(fmt.Sprintf("version %d", exportVersion))
|
||||
var debug string
|
||||
if debugFormat {
|
||||
debug = "debug"
|
||||
}
|
||||
p.rawStringln(debug) // cannot use p.bool since it's affected by debugFormat; also want to see this clearly
|
||||
p.bool(trackAllTypes)
|
||||
p.bool(p.posInfoFormat)
|
||||
|
||||
// --- generic export data ---
|
||||
|
||||
// populate type map with predeclared "known" types
|
||||
for index, typ := range predeclared() {
|
||||
p.typIndex[typ] = index
|
||||
}
|
||||
if len(p.typIndex) != len(predeclared()) {
|
||||
return nil, internalError("duplicate entries in type map?")
|
||||
}
|
||||
|
||||
// write package data
|
||||
p.pkg(pkg, true)
|
||||
if trace {
|
||||
p.tracef("\n")
|
||||
}
|
||||
|
||||
// write objects
|
||||
objcount := 0
|
||||
scope := pkg.Scope()
|
||||
for _, name := range scope.Names() {
|
||||
if !token.IsExported(name) {
|
||||
continue
|
||||
}
|
||||
if trace {
|
||||
p.tracef("\n")
|
||||
}
|
||||
p.obj(scope.Lookup(name))
|
||||
objcount++
|
||||
}
|
||||
|
||||
// indicate end of list
|
||||
if trace {
|
||||
p.tracef("\n")
|
||||
}
|
||||
p.tag(endTag)
|
||||
|
||||
// for self-verification only (redundant)
|
||||
p.int(objcount)
|
||||
|
||||
if trace {
|
||||
p.tracef("\n")
|
||||
}
|
||||
|
||||
// --- end of export data ---
|
||||
|
||||
return p.out.Bytes(), nil
|
||||
}
|
||||
|
||||
func (p *exporter) pkg(pkg *types.Package, emptypath bool) {
|
||||
if pkg == nil {
|
||||
panic(internalError("unexpected nil pkg"))
|
||||
}
|
||||
|
||||
// if we saw the package before, write its index (>= 0)
|
||||
if i, ok := p.pkgIndex[pkg]; ok {
|
||||
p.index('P', i)
|
||||
return
|
||||
}
|
||||
|
||||
// otherwise, remember the package, write the package tag (< 0) and package data
|
||||
if trace {
|
||||
p.tracef("P%d = { ", len(p.pkgIndex))
|
||||
defer p.tracef("} ")
|
||||
}
|
||||
p.pkgIndex[pkg] = len(p.pkgIndex)
|
||||
|
||||
p.tag(packageTag)
|
||||
p.string(pkg.Name())
|
||||
if emptypath {
|
||||
p.string("")
|
||||
} else {
|
||||
p.string(pkg.Path())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) obj(obj types.Object) {
|
||||
switch obj := obj.(type) {
|
||||
case *types.Const:
|
||||
p.tag(constTag)
|
||||
p.pos(obj)
|
||||
p.qualifiedName(obj)
|
||||
p.typ(obj.Type())
|
||||
p.value(obj.Val())
|
||||
|
||||
case *types.TypeName:
|
||||
if obj.IsAlias() {
|
||||
p.tag(aliasTag)
|
||||
p.pos(obj)
|
||||
p.qualifiedName(obj)
|
||||
} else {
|
||||
p.tag(typeTag)
|
||||
}
|
||||
p.typ(obj.Type())
|
||||
|
||||
case *types.Var:
|
||||
p.tag(varTag)
|
||||
p.pos(obj)
|
||||
p.qualifiedName(obj)
|
||||
p.typ(obj.Type())
|
||||
|
||||
case *types.Func:
|
||||
p.tag(funcTag)
|
||||
p.pos(obj)
|
||||
p.qualifiedName(obj)
|
||||
sig := obj.Type().(*types.Signature)
|
||||
p.paramList(sig.Params(), sig.Variadic())
|
||||
p.paramList(sig.Results(), false)
|
||||
|
||||
default:
|
||||
panic(internalErrorf("unexpected object %v (%T)", obj, obj))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) pos(obj types.Object) {
|
||||
if !p.posInfoFormat {
|
||||
return
|
||||
}
|
||||
|
||||
file, line := p.fileLine(obj)
|
||||
if file == p.prevFile {
|
||||
// common case: write line delta
|
||||
// delta == 0 means different file or no line change
|
||||
delta := line - p.prevLine
|
||||
p.int(delta)
|
||||
if delta == 0 {
|
||||
p.int(-1) // -1 means no file change
|
||||
}
|
||||
} else {
|
||||
// different file
|
||||
p.int(0)
|
||||
// Encode filename as length of common prefix with previous
|
||||
// filename, followed by (possibly empty) suffix. Filenames
|
||||
// frequently share path prefixes, so this can save a lot
|
||||
// of space and make export data size less dependent on file
|
||||
// path length. The suffix is unlikely to be empty because
|
||||
// file names tend to end in ".go".
|
||||
n := commonPrefixLen(p.prevFile, file)
|
||||
p.int(n) // n >= 0
|
||||
p.string(file[n:]) // write suffix only
|
||||
p.prevFile = file
|
||||
p.int(line)
|
||||
}
|
||||
p.prevLine = line
|
||||
}
|
||||
|
||||
func (p *exporter) fileLine(obj types.Object) (file string, line int) {
|
||||
if p.fset != nil {
|
||||
pos := p.fset.Position(obj.Pos())
|
||||
file = pos.Filename
|
||||
line = pos.Line
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func commonPrefixLen(a, b string) int {
|
||||
if len(a) > len(b) {
|
||||
a, b = b, a
|
||||
}
|
||||
// len(a) <= len(b)
|
||||
i := 0
|
||||
for i < len(a) && a[i] == b[i] {
|
||||
i++
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (p *exporter) qualifiedName(obj types.Object) {
|
||||
p.string(obj.Name())
|
||||
p.pkg(obj.Pkg(), false)
|
||||
}
|
||||
|
||||
func (p *exporter) typ(t types.Type) {
|
||||
if t == nil {
|
||||
panic(internalError("nil type"))
|
||||
}
|
||||
|
||||
// Possible optimization: Anonymous pointer types *T where
|
||||
// T is a named type are common. We could canonicalize all
|
||||
// such types *T to a single type PT = *T. This would lead
|
||||
// to at most one *T entry in typIndex, and all future *T's
|
||||
// would be encoded as the respective index directly. Would
|
||||
// save 1 byte (pointerTag) per *T and reduce the typIndex
|
||||
// size (at the cost of a canonicalization map). We can do
|
||||
// this later, without encoding format change.
|
||||
|
||||
// if we saw the type before, write its index (>= 0)
|
||||
if i, ok := p.typIndex[t]; ok {
|
||||
p.index('T', i)
|
||||
return
|
||||
}
|
||||
|
||||
// otherwise, remember the type, write the type tag (< 0) and type data
|
||||
if trackAllTypes {
|
||||
if trace {
|
||||
p.tracef("T%d = {>\n", len(p.typIndex))
|
||||
defer p.tracef("<\n} ")
|
||||
}
|
||||
p.typIndex[t] = len(p.typIndex)
|
||||
}
|
||||
|
||||
switch t := t.(type) {
|
||||
case *types.Named:
|
||||
if !trackAllTypes {
|
||||
// if we don't track all types, track named types now
|
||||
p.typIndex[t] = len(p.typIndex)
|
||||
}
|
||||
|
||||
p.tag(namedTag)
|
||||
p.pos(t.Obj())
|
||||
p.qualifiedName(t.Obj())
|
||||
p.typ(t.Underlying())
|
||||
if !types.IsInterface(t) {
|
||||
p.assocMethods(t)
|
||||
}
|
||||
|
||||
case *types.Array:
|
||||
p.tag(arrayTag)
|
||||
p.int64(t.Len())
|
||||
p.typ(t.Elem())
|
||||
|
||||
case *types.Slice:
|
||||
p.tag(sliceTag)
|
||||
p.typ(t.Elem())
|
||||
|
||||
case *dddSlice:
|
||||
p.tag(dddTag)
|
||||
p.typ(t.elem)
|
||||
|
||||
case *types.Struct:
|
||||
p.tag(structTag)
|
||||
p.fieldList(t)
|
||||
|
||||
case *types.Pointer:
|
||||
p.tag(pointerTag)
|
||||
p.typ(t.Elem())
|
||||
|
||||
case *types.Signature:
|
||||
p.tag(signatureTag)
|
||||
p.paramList(t.Params(), t.Variadic())
|
||||
p.paramList(t.Results(), false)
|
||||
|
||||
case *types.Interface:
|
||||
p.tag(interfaceTag)
|
||||
p.iface(t)
|
||||
|
||||
case *types.Map:
|
||||
p.tag(mapTag)
|
||||
p.typ(t.Key())
|
||||
p.typ(t.Elem())
|
||||
|
||||
case *types.Chan:
|
||||
p.tag(chanTag)
|
||||
p.int(int(3 - t.Dir())) // hack
|
||||
p.typ(t.Elem())
|
||||
|
||||
default:
|
||||
panic(internalErrorf("unexpected type %T: %s", t, t))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) assocMethods(named *types.Named) {
|
||||
// Sort methods (for determinism).
|
||||
var methods []*types.Func
|
||||
for i := 0; i < named.NumMethods(); i++ {
|
||||
methods = append(methods, named.Method(i))
|
||||
}
|
||||
sort.Sort(methodsByName(methods))
|
||||
|
||||
p.int(len(methods))
|
||||
|
||||
if trace && methods != nil {
|
||||
p.tracef("associated methods {>\n")
|
||||
}
|
||||
|
||||
for i, m := range methods {
|
||||
if trace && i > 0 {
|
||||
p.tracef("\n")
|
||||
}
|
||||
|
||||
p.pos(m)
|
||||
name := m.Name()
|
||||
p.string(name)
|
||||
if !exported(name) {
|
||||
p.pkg(m.Pkg(), false)
|
||||
}
|
||||
|
||||
sig := m.Type().(*types.Signature)
|
||||
p.paramList(types.NewTuple(sig.Recv()), false)
|
||||
p.paramList(sig.Params(), sig.Variadic())
|
||||
p.paramList(sig.Results(), false)
|
||||
p.int(0) // dummy value for go:nointerface pragma - ignored by importer
|
||||
}
|
||||
|
||||
if trace && methods != nil {
|
||||
p.tracef("<\n} ")
|
||||
}
|
||||
}
|
||||
|
||||
type methodsByName []*types.Func
|
||||
|
||||
func (x methodsByName) Len() int { return len(x) }
|
||||
func (x methodsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
func (x methodsByName) Less(i, j int) bool { return x[i].Name() < x[j].Name() }
|
||||
|
||||
func (p *exporter) fieldList(t *types.Struct) {
|
||||
if trace && t.NumFields() > 0 {
|
||||
p.tracef("fields {>\n")
|
||||
defer p.tracef("<\n} ")
|
||||
}
|
||||
|
||||
p.int(t.NumFields())
|
||||
for i := 0; i < t.NumFields(); i++ {
|
||||
if trace && i > 0 {
|
||||
p.tracef("\n")
|
||||
}
|
||||
p.field(t.Field(i))
|
||||
p.string(t.Tag(i))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) field(f *types.Var) {
|
||||
if !f.IsField() {
|
||||
panic(internalError("field expected"))
|
||||
}
|
||||
|
||||
p.pos(f)
|
||||
p.fieldName(f)
|
||||
p.typ(f.Type())
|
||||
}
|
||||
|
||||
func (p *exporter) iface(t *types.Interface) {
|
||||
// TODO(gri): enable importer to load embedded interfaces,
|
||||
// then emit Embeddeds and ExplicitMethods separately here.
|
||||
p.int(0)
|
||||
|
||||
n := t.NumMethods()
|
||||
if trace && n > 0 {
|
||||
p.tracef("methods {>\n")
|
||||
defer p.tracef("<\n} ")
|
||||
}
|
||||
p.int(n)
|
||||
for i := 0; i < n; i++ {
|
||||
if trace && i > 0 {
|
||||
p.tracef("\n")
|
||||
}
|
||||
p.method(t.Method(i))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) method(m *types.Func) {
|
||||
sig := m.Type().(*types.Signature)
|
||||
if sig.Recv() == nil {
|
||||
panic(internalError("method expected"))
|
||||
}
|
||||
|
||||
p.pos(m)
|
||||
p.string(m.Name())
|
||||
if m.Name() != "_" && !token.IsExported(m.Name()) {
|
||||
p.pkg(m.Pkg(), false)
|
||||
}
|
||||
|
||||
// interface method; no need to encode receiver.
|
||||
p.paramList(sig.Params(), sig.Variadic())
|
||||
p.paramList(sig.Results(), false)
|
||||
}
|
||||
|
||||
func (p *exporter) fieldName(f *types.Var) {
|
||||
name := f.Name()
|
||||
|
||||
if f.Anonymous() {
|
||||
// anonymous field - we distinguish between 3 cases:
|
||||
// 1) field name matches base type name and is exported
|
||||
// 2) field name matches base type name and is not exported
|
||||
// 3) field name doesn't match base type name (alias name)
|
||||
bname := basetypeName(f.Type())
|
||||
if name == bname {
|
||||
if token.IsExported(name) {
|
||||
name = "" // 1) we don't need to know the field name or package
|
||||
} else {
|
||||
name = "?" // 2) use unexported name "?" to force package export
|
||||
}
|
||||
} else {
|
||||
// 3) indicate alias and export name as is
|
||||
// (this requires an extra "@" but this is a rare case)
|
||||
p.string("@")
|
||||
}
|
||||
}
|
||||
|
||||
p.string(name)
|
||||
if name != "" && !token.IsExported(name) {
|
||||
p.pkg(f.Pkg(), false)
|
||||
}
|
||||
}
|
||||
|
||||
func basetypeName(typ types.Type) string {
|
||||
switch typ := deref(typ).(type) {
|
||||
case *types.Basic:
|
||||
return typ.Name()
|
||||
case *types.Named:
|
||||
return typ.Obj().Name()
|
||||
default:
|
||||
return "" // unnamed type
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) paramList(params *types.Tuple, variadic bool) {
|
||||
// use negative length to indicate unnamed parameters
|
||||
// (look at the first parameter only since either all
|
||||
// names are present or all are absent)
|
||||
n := params.Len()
|
||||
if n > 0 && params.At(0).Name() == "" {
|
||||
n = -n
|
||||
}
|
||||
p.int(n)
|
||||
for i := 0; i < params.Len(); i++ {
|
||||
q := params.At(i)
|
||||
t := q.Type()
|
||||
if variadic && i == params.Len()-1 {
|
||||
t = &dddSlice{t.(*types.Slice).Elem()}
|
||||
}
|
||||
p.typ(t)
|
||||
if n > 0 {
|
||||
name := q.Name()
|
||||
p.string(name)
|
||||
if name != "_" {
|
||||
p.pkg(q.Pkg(), false)
|
||||
}
|
||||
}
|
||||
p.string("") // no compiler-specific info
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) value(x constant.Value) {
|
||||
if trace {
|
||||
p.tracef("= ")
|
||||
}
|
||||
|
||||
switch x.Kind() {
|
||||
case constant.Bool:
|
||||
tag := falseTag
|
||||
if constant.BoolVal(x) {
|
||||
tag = trueTag
|
||||
}
|
||||
p.tag(tag)
|
||||
|
||||
case constant.Int:
|
||||
if v, exact := constant.Int64Val(x); exact {
|
||||
// common case: x fits into an int64 - use compact encoding
|
||||
p.tag(int64Tag)
|
||||
p.int64(v)
|
||||
return
|
||||
}
|
||||
// uncommon case: large x - use float encoding
|
||||
// (powers of 2 will be encoded efficiently with exponent)
|
||||
p.tag(floatTag)
|
||||
p.float(constant.ToFloat(x))
|
||||
|
||||
case constant.Float:
|
||||
p.tag(floatTag)
|
||||
p.float(x)
|
||||
|
||||
case constant.Complex:
|
||||
p.tag(complexTag)
|
||||
p.float(constant.Real(x))
|
||||
p.float(constant.Imag(x))
|
||||
|
||||
case constant.String:
|
||||
p.tag(stringTag)
|
||||
p.string(constant.StringVal(x))
|
||||
|
||||
case constant.Unknown:
|
||||
// package contains type errors
|
||||
p.tag(unknownTag)
|
||||
|
||||
default:
|
||||
panic(internalErrorf("unexpected value %v (%T)", x, x))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *exporter) float(x constant.Value) {
|
||||
if x.Kind() != constant.Float {
|
||||
panic(internalErrorf("unexpected constant %v, want float", x))
|
||||
}
|
||||
// extract sign (there is no -0)
|
||||
sign := constant.Sign(x)
|
||||
if sign == 0 {
|
||||
// x == 0
|
||||
p.int(0)
|
||||
return
|
||||
}
|
||||
// x != 0
|
||||
|
||||
var f big.Float
|
||||
if v, exact := constant.Float64Val(x); exact {
|
||||
// float64
|
||||
f.SetFloat64(v)
|
||||
} else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int {
|
||||
// TODO(gri): add big.Rat accessor to constant.Value.
|
||||
r := valueToRat(num)
|
||||
f.SetRat(r.Quo(r, valueToRat(denom)))
|
||||
} else {
|
||||
// Value too large to represent as a fraction => inaccessible.
|
||||
// TODO(gri): add big.Float accessor to constant.Value.
|
||||
f.SetFloat64(math.MaxFloat64) // FIXME
|
||||
}
|
||||
|
||||
// extract exponent such that 0.5 <= m < 1.0
|
||||
var m big.Float
|
||||
exp := f.MantExp(&m)
|
||||
|
||||
// extract mantissa as *big.Int
|
||||
// - set exponent large enough so mant satisfies mant.IsInt()
|
||||
// - get *big.Int from mant
|
||||
m.SetMantExp(&m, int(m.MinPrec()))
|
||||
mant, acc := m.Int(nil)
|
||||
if acc != big.Exact {
|
||||
panic(internalError("internal error"))
|
||||
}
|
||||
|
||||
p.int(sign)
|
||||
p.int(exp)
|
||||
p.string(string(mant.Bytes()))
|
||||
}
|
||||
|
||||
func valueToRat(x constant.Value) *big.Rat {
|
||||
// Convert little-endian to big-endian.
|
||||
// I can't believe this is necessary.
|
||||
bytes := constant.Bytes(x)
|
||||
for i := 0; i < len(bytes)/2; i++ {
|
||||
bytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i]
|
||||
}
|
||||
return new(big.Rat).SetInt(new(big.Int).SetBytes(bytes))
|
||||
}
|
||||
|
||||
func (p *exporter) bool(b bool) bool {
|
||||
if trace {
|
||||
p.tracef("[")
|
||||
defer p.tracef("= %v] ", b)
|
||||
}
|
||||
|
||||
x := 0
|
||||
if b {
|
||||
x = 1
|
||||
}
|
||||
p.int(x)
|
||||
return b
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Low-level encoders
|
||||
|
||||
func (p *exporter) index(marker byte, index int) {
|
||||
if index < 0 {
|
||||
panic(internalError("invalid index < 0"))
|
||||
}
|
||||
if debugFormat {
|
||||
p.marker('t')
|
||||
}
|
||||
if trace {
|
||||
p.tracef("%c%d ", marker, index)
|
||||
}
|
||||
p.rawInt64(int64(index))
|
||||
}
|
||||
|
||||
func (p *exporter) tag(tag int) {
|
||||
if tag >= 0 {
|
||||
panic(internalError("invalid tag >= 0"))
|
||||
}
|
||||
if debugFormat {
|
||||
p.marker('t')
|
||||
}
|
||||
if trace {
|
||||
p.tracef("%s ", tagString[-tag])
|
||||
}
|
||||
p.rawInt64(int64(tag))
|
||||
}
|
||||
|
||||
func (p *exporter) int(x int) {
|
||||
p.int64(int64(x))
|
||||
}
|
||||
|
||||
func (p *exporter) int64(x int64) {
|
||||
if debugFormat {
|
||||
p.marker('i')
|
||||
}
|
||||
if trace {
|
||||
p.tracef("%d ", x)
|
||||
}
|
||||
p.rawInt64(x)
|
||||
}
|
||||
|
||||
func (p *exporter) string(s string) {
|
||||
if debugFormat {
|
||||
p.marker('s')
|
||||
}
|
||||
if trace {
|
||||
p.tracef("%q ", s)
|
||||
}
|
||||
// if we saw the string before, write its index (>= 0)
|
||||
// (the empty string is mapped to 0)
|
||||
if i, ok := p.strIndex[s]; ok {
|
||||
p.rawInt64(int64(i))
|
||||
return
|
||||
}
|
||||
// otherwise, remember string and write its negative length and bytes
|
||||
p.strIndex[s] = len(p.strIndex)
|
||||
p.rawInt64(-int64(len(s)))
|
||||
for i := 0; i < len(s); i++ {
|
||||
p.rawByte(s[i])
|
||||
}
|
||||
}
|
||||
|
||||
// marker emits a marker byte and position information which makes
|
||||
// it easy for a reader to detect if it is "out of sync". Used for
|
||||
// debugFormat format only.
|
||||
func (p *exporter) marker(m byte) {
|
||||
p.rawByte(m)
|
||||
// Enable this for help tracking down the location
|
||||
// of an incorrect marker when running in debugFormat.
|
||||
if false && trace {
|
||||
p.tracef("#%d ", p.written)
|
||||
}
|
||||
p.rawInt64(int64(p.written))
|
||||
}
|
||||
|
||||
// rawInt64 should only be used by low-level encoders.
|
||||
func (p *exporter) rawInt64(x int64) {
|
||||
var tmp [binary.MaxVarintLen64]byte
|
||||
n := binary.PutVarint(tmp[:], x)
|
||||
for i := 0; i < n; i++ {
|
||||
p.rawByte(tmp[i])
|
||||
}
|
||||
}
|
||||
|
||||
// rawStringln should only be used to emit the initial version string.
|
||||
func (p *exporter) rawStringln(s string) {
|
||||
for i := 0; i < len(s); i++ {
|
||||
p.rawByte(s[i])
|
||||
}
|
||||
p.rawByte('\n')
|
||||
}
|
||||
|
||||
// rawByte is the bottleneck interface to write to p.out.
|
||||
// rawByte escapes b as follows (any encoding does that
|
||||
// hides '$'):
|
||||
//
|
||||
// '$' => '|' 'S'
|
||||
// '|' => '|' '|'
|
||||
//
|
||||
// Necessary so other tools can find the end of the
|
||||
// export data by searching for "$$".
|
||||
// rawByte should only be used by low-level encoders.
|
||||
func (p *exporter) rawByte(b byte) {
|
||||
switch b {
|
||||
case '$':
|
||||
// write '$' as '|' 'S'
|
||||
b = 'S'
|
||||
fallthrough
|
||||
case '|':
|
||||
// write '|' as '|' '|'
|
||||
p.out.WriteByte('|')
|
||||
p.written++
|
||||
}
|
||||
p.out.WriteByte(b)
|
||||
p.written++
|
||||
}
|
||||
|
||||
// tracef is like fmt.Printf but it rewrites the format string
|
||||
// to take care of indentation.
|
||||
func (p *exporter) tracef(format string, args ...interface{}) {
|
||||
if strings.ContainsAny(format, "<>\n") {
|
||||
var buf bytes.Buffer
|
||||
for i := 0; i < len(format); i++ {
|
||||
// no need to deal with runes
|
||||
ch := format[i]
|
||||
switch ch {
|
||||
case '>':
|
||||
p.indent++
|
||||
continue
|
||||
case '<':
|
||||
p.indent--
|
||||
continue
|
||||
}
|
||||
buf.WriteByte(ch)
|
||||
if ch == '\n' {
|
||||
for j := p.indent; j > 0; j-- {
|
||||
buf.WriteString(". ")
|
||||
}
|
||||
}
|
||||
}
|
||||
format = buf.String()
|
||||
}
|
||||
fmt.Printf(format, args...)
|
||||
}
|
||||
|
||||
// Debugging support.
|
||||
// (tagString is only used when tracing is enabled)
|
||||
var tagString = [...]string{
|
||||
// Packages
|
||||
-packageTag: "package",
|
||||
|
||||
// Types
|
||||
-namedTag: "named type",
|
||||
-arrayTag: "array",
|
||||
-sliceTag: "slice",
|
||||
-dddTag: "ddd",
|
||||
-structTag: "struct",
|
||||
-pointerTag: "pointer",
|
||||
-signatureTag: "signature",
|
||||
-interfaceTag: "interface",
|
||||
-mapTag: "map",
|
||||
-chanTag: "chan",
|
||||
|
||||
// Values
|
||||
-falseTag: "false",
|
||||
-trueTag: "true",
|
||||
-int64Tag: "int64",
|
||||
-floatTag: "float",
|
||||
-fractionTag: "fraction",
|
||||
-complexTag: "complex",
|
||||
-stringTag: "string",
|
||||
-unknownTag: "unknown",
|
||||
|
||||
// Type aliases
|
||||
-aliasTag: "alias",
|
||||
}
|
907
vendor/golang.org/x/tools/internal/gcimporter/bimport.go
generated
vendored
907
vendor/golang.org/x/tools/internal/gcimporter/bimport.go
generated
vendored
@ -2,340 +2,24 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file is a copy of $GOROOT/src/go/internal/gcimporter/bimport.go.
|
||||
// This file contains the remaining vestiges of
|
||||
// $GOROOT/src/go/internal/gcimporter/bimport.go.
|
||||
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type importer struct {
|
||||
imports map[string]*types.Package
|
||||
data []byte
|
||||
importpath string
|
||||
buf []byte // for reading strings
|
||||
version int // export format version
|
||||
|
||||
// object lists
|
||||
strList []string // in order of appearance
|
||||
pathList []string // in order of appearance
|
||||
pkgList []*types.Package // in order of appearance
|
||||
typList []types.Type // in order of appearance
|
||||
interfaceList []*types.Interface // for delayed completion only
|
||||
trackAllTypes bool
|
||||
|
||||
// position encoding
|
||||
posInfoFormat bool
|
||||
prevFile string
|
||||
prevLine int
|
||||
fake fakeFileSet
|
||||
|
||||
// debugging support
|
||||
debugFormat bool
|
||||
read int // bytes read
|
||||
}
|
||||
|
||||
// BImportData imports a package from the serialized package data
|
||||
// and returns the number of bytes consumed and a reference to the package.
|
||||
// If the export data version is not recognized or the format is otherwise
|
||||
// compromised, an error is returned.
|
||||
func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
||||
// catch panics and return them as errors
|
||||
const currentVersion = 6
|
||||
version := -1 // unknown version
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
// Return a (possibly nil or incomplete) package unchanged (see #16088).
|
||||
if version > currentVersion {
|
||||
err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
|
||||
} else {
|
||||
err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
p := importer{
|
||||
imports: imports,
|
||||
data: data,
|
||||
importpath: path,
|
||||
version: version,
|
||||
strList: []string{""}, // empty string is mapped to 0
|
||||
pathList: []string{""}, // empty string is mapped to 0
|
||||
fake: fakeFileSet{
|
||||
fset: fset,
|
||||
files: make(map[string]*fileInfo),
|
||||
},
|
||||
}
|
||||
defer p.fake.setLines() // set lines for files in fset
|
||||
|
||||
// read version info
|
||||
var versionstr string
|
||||
if b := p.rawByte(); b == 'c' || b == 'd' {
|
||||
// Go1.7 encoding; first byte encodes low-level
|
||||
// encoding format (compact vs debug).
|
||||
// For backward-compatibility only (avoid problems with
|
||||
// old installed packages). Newly compiled packages use
|
||||
// the extensible format string.
|
||||
// TODO(gri) Remove this support eventually; after Go1.8.
|
||||
if b == 'd' {
|
||||
p.debugFormat = true
|
||||
}
|
||||
p.trackAllTypes = p.rawByte() == 'a'
|
||||
p.posInfoFormat = p.int() != 0
|
||||
versionstr = p.string()
|
||||
if versionstr == "v1" {
|
||||
version = 0
|
||||
}
|
||||
} else {
|
||||
// Go1.8 extensible encoding
|
||||
// read version string and extract version number (ignore anything after the version number)
|
||||
versionstr = p.rawStringln(b)
|
||||
if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
|
||||
if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
|
||||
version = v
|
||||
}
|
||||
}
|
||||
}
|
||||
p.version = version
|
||||
|
||||
// read version specific flags - extend as necessary
|
||||
switch p.version {
|
||||
// case currentVersion:
|
||||
// ...
|
||||
// fallthrough
|
||||
case currentVersion, 5, 4, 3, 2, 1:
|
||||
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
|
||||
p.trackAllTypes = p.int() != 0
|
||||
p.posInfoFormat = p.int() != 0
|
||||
case 0:
|
||||
// Go1.7 encoding format - nothing to do here
|
||||
default:
|
||||
errorf("unknown bexport format version %d (%q)", p.version, versionstr)
|
||||
}
|
||||
|
||||
// --- generic export data ---
|
||||
|
||||
// populate typList with predeclared "known" types
|
||||
p.typList = append(p.typList, predeclared()...)
|
||||
|
||||
// read package data
|
||||
pkg = p.pkg()
|
||||
|
||||
// read objects of phase 1 only (see cmd/compile/internal/gc/bexport.go)
|
||||
objcount := 0
|
||||
for {
|
||||
tag := p.tagOrIndex()
|
||||
if tag == endTag {
|
||||
break
|
||||
}
|
||||
p.obj(tag)
|
||||
objcount++
|
||||
}
|
||||
|
||||
// self-verification
|
||||
if count := p.int(); count != objcount {
|
||||
errorf("got %d objects; want %d", objcount, count)
|
||||
}
|
||||
|
||||
// ignore compiler-specific import data
|
||||
|
||||
// complete interfaces
|
||||
// TODO(gri) re-investigate if we still need to do this in a delayed fashion
|
||||
for _, typ := range p.interfaceList {
|
||||
typ.Complete()
|
||||
}
|
||||
|
||||
// record all referenced packages as imports
|
||||
list := append(([]*types.Package)(nil), p.pkgList[1:]...)
|
||||
sort.Sort(byPath(list))
|
||||
pkg.SetImports(list)
|
||||
|
||||
// package was imported completely and without errors
|
||||
pkg.MarkComplete()
|
||||
|
||||
return p.read, pkg, nil
|
||||
}
|
||||
|
||||
func errorf(format string, args ...interface{}) {
|
||||
panic(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (p *importer) pkg() *types.Package {
|
||||
// if the package was seen before, i is its index (>= 0)
|
||||
i := p.tagOrIndex()
|
||||
if i >= 0 {
|
||||
return p.pkgList[i]
|
||||
}
|
||||
|
||||
// otherwise, i is the package tag (< 0)
|
||||
if i != packageTag {
|
||||
errorf("unexpected package tag %d version %d", i, p.version)
|
||||
}
|
||||
|
||||
// read package data
|
||||
name := p.string()
|
||||
var path string
|
||||
if p.version >= 5 {
|
||||
path = p.path()
|
||||
} else {
|
||||
path = p.string()
|
||||
}
|
||||
if p.version >= 6 {
|
||||
p.int() // package height; unused by go/types
|
||||
}
|
||||
|
||||
// we should never see an empty package name
|
||||
if name == "" {
|
||||
errorf("empty package name in import")
|
||||
}
|
||||
|
||||
// an empty path denotes the package we are currently importing;
|
||||
// it must be the first package we see
|
||||
if (path == "") != (len(p.pkgList) == 0) {
|
||||
errorf("package path %q for pkg index %d", path, len(p.pkgList))
|
||||
}
|
||||
|
||||
// if the package was imported before, use that one; otherwise create a new one
|
||||
if path == "" {
|
||||
path = p.importpath
|
||||
}
|
||||
pkg := p.imports[path]
|
||||
if pkg == nil {
|
||||
pkg = types.NewPackage(path, name)
|
||||
p.imports[path] = pkg
|
||||
} else if pkg.Name() != name {
|
||||
errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path)
|
||||
}
|
||||
p.pkgList = append(p.pkgList, pkg)
|
||||
|
||||
return pkg
|
||||
}
|
||||
|
||||
// objTag returns the tag value for each object kind.
|
||||
func objTag(obj types.Object) int {
|
||||
switch obj.(type) {
|
||||
case *types.Const:
|
||||
return constTag
|
||||
case *types.TypeName:
|
||||
return typeTag
|
||||
case *types.Var:
|
||||
return varTag
|
||||
case *types.Func:
|
||||
return funcTag
|
||||
default:
|
||||
errorf("unexpected object: %v (%T)", obj, obj) // panics
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func sameObj(a, b types.Object) bool {
|
||||
// Because unnamed types are not canonicalized, we cannot simply compare types for
|
||||
// (pointer) identity.
|
||||
// Ideally we'd check equality of constant values as well, but this is good enough.
|
||||
return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type())
|
||||
}
|
||||
|
||||
func (p *importer) declare(obj types.Object) {
|
||||
pkg := obj.Pkg()
|
||||
if alt := pkg.Scope().Insert(obj); alt != nil {
|
||||
// This can only trigger if we import a (non-type) object a second time.
|
||||
// Excluding type aliases, this cannot happen because 1) we only import a package
|
||||
// once; and b) we ignore compiler-specific export data which may contain
|
||||
// functions whose inlined function bodies refer to other functions that
|
||||
// were already imported.
|
||||
// However, type aliases require reexporting the original type, so we need
|
||||
// to allow it (see also the comment in cmd/compile/internal/gc/bimport.go,
|
||||
// method importer.obj, switch case importing functions).
|
||||
// TODO(gri) review/update this comment once the gc compiler handles type aliases.
|
||||
if !sameObj(obj, alt) {
|
||||
errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importer) obj(tag int) {
|
||||
switch tag {
|
||||
case constTag:
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
typ := p.typ(nil, nil)
|
||||
val := p.value()
|
||||
p.declare(types.NewConst(pos, pkg, name, typ, val))
|
||||
|
||||
case aliasTag:
|
||||
// TODO(gri) verify type alias hookup is correct
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
typ := p.typ(nil, nil)
|
||||
p.declare(types.NewTypeName(pos, pkg, name, typ))
|
||||
|
||||
case typeTag:
|
||||
p.typ(nil, nil)
|
||||
|
||||
case varTag:
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
typ := p.typ(nil, nil)
|
||||
p.declare(types.NewVar(pos, pkg, name, typ))
|
||||
|
||||
case funcTag:
|
||||
pos := p.pos()
|
||||
pkg, name := p.qualifiedName()
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
sig := types.NewSignature(nil, params, result, isddd)
|
||||
p.declare(types.NewFunc(pos, pkg, name, sig))
|
||||
|
||||
default:
|
||||
errorf("unexpected object tag %d", tag)
|
||||
}
|
||||
}
|
||||
|
||||
const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go
|
||||
|
||||
func (p *importer) pos() token.Pos {
|
||||
if !p.posInfoFormat {
|
||||
return token.NoPos
|
||||
}
|
||||
|
||||
file := p.prevFile
|
||||
line := p.prevLine
|
||||
delta := p.int()
|
||||
line += delta
|
||||
if p.version >= 5 {
|
||||
if delta == deltaNewFile {
|
||||
if n := p.int(); n >= 0 {
|
||||
// file changed
|
||||
file = p.path()
|
||||
line = n
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if delta == 0 {
|
||||
if n := p.int(); n >= 0 {
|
||||
// file changed
|
||||
file = p.prevFile[:n] + p.string()
|
||||
line = p.int()
|
||||
}
|
||||
}
|
||||
}
|
||||
p.prevFile = file
|
||||
p.prevLine = line
|
||||
|
||||
return p.fake.pos(file, line, 0)
|
||||
}
|
||||
|
||||
// Synthesize a token.Pos
|
||||
type fakeFileSet struct {
|
||||
fset *token.FileSet
|
||||
@ -389,205 +73,6 @@ var (
|
||||
fakeLinesOnce sync.Once
|
||||
)
|
||||
|
||||
func (p *importer) qualifiedName() (pkg *types.Package, name string) {
|
||||
name = p.string()
|
||||
pkg = p.pkg()
|
||||
return
|
||||
}
|
||||
|
||||
func (p *importer) record(t types.Type) {
|
||||
p.typList = append(p.typList, t)
|
||||
}
|
||||
|
||||
// A dddSlice is a types.Type representing ...T parameters.
|
||||
// It only appears for parameter types and does not escape
|
||||
// the importer.
|
||||
type dddSlice struct {
|
||||
elem types.Type
|
||||
}
|
||||
|
||||
func (t *dddSlice) Underlying() types.Type { return t }
|
||||
func (t *dddSlice) String() string { return "..." + t.elem.String() }
|
||||
|
||||
// parent is the package which declared the type; parent == nil means
|
||||
// the package currently imported. The parent package is needed for
|
||||
// exported struct fields and interface methods which don't contain
|
||||
// explicit package information in the export data.
|
||||
//
|
||||
// A non-nil tname is used as the "owner" of the result type; i.e.,
|
||||
// the result type is the underlying type of tname. tname is used
|
||||
// to give interface methods a named receiver type where possible.
|
||||
func (p *importer) typ(parent *types.Package, tname *types.Named) types.Type {
|
||||
// if the type was seen before, i is its index (>= 0)
|
||||
i := p.tagOrIndex()
|
||||
if i >= 0 {
|
||||
return p.typList[i]
|
||||
}
|
||||
|
||||
// otherwise, i is the type tag (< 0)
|
||||
switch i {
|
||||
case namedTag:
|
||||
// read type object
|
||||
pos := p.pos()
|
||||
parent, name := p.qualifiedName()
|
||||
scope := parent.Scope()
|
||||
obj := scope.Lookup(name)
|
||||
|
||||
// if the object doesn't exist yet, create and insert it
|
||||
if obj == nil {
|
||||
obj = types.NewTypeName(pos, parent, name, nil)
|
||||
scope.Insert(obj)
|
||||
}
|
||||
|
||||
if _, ok := obj.(*types.TypeName); !ok {
|
||||
errorf("pkg = %s, name = %s => %s", parent, name, obj)
|
||||
}
|
||||
|
||||
// associate new named type with obj if it doesn't exist yet
|
||||
t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
|
||||
|
||||
// but record the existing type, if any
|
||||
tname := obj.Type().(*types.Named) // tname is either t0 or the existing type
|
||||
p.record(tname)
|
||||
|
||||
// read underlying type
|
||||
t0.SetUnderlying(p.typ(parent, t0))
|
||||
|
||||
// interfaces don't have associated methods
|
||||
if types.IsInterface(t0) {
|
||||
return tname
|
||||
}
|
||||
|
||||
// read associated methods
|
||||
for i := p.int(); i > 0; i-- {
|
||||
// TODO(gri) replace this with something closer to fieldName
|
||||
pos := p.pos()
|
||||
name := p.string()
|
||||
if !exported(name) {
|
||||
p.pkg()
|
||||
}
|
||||
|
||||
recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
p.int() // go:nointerface pragma - discarded
|
||||
|
||||
sig := types.NewSignature(recv.At(0), params, result, isddd)
|
||||
t0.AddMethod(types.NewFunc(pos, parent, name, sig))
|
||||
}
|
||||
|
||||
return tname
|
||||
|
||||
case arrayTag:
|
||||
t := new(types.Array)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
n := p.int64()
|
||||
*t = *types.NewArray(p.typ(parent, nil), n)
|
||||
return t
|
||||
|
||||
case sliceTag:
|
||||
t := new(types.Slice)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
*t = *types.NewSlice(p.typ(parent, nil))
|
||||
return t
|
||||
|
||||
case dddTag:
|
||||
t := new(dddSlice)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
t.elem = p.typ(parent, nil)
|
||||
return t
|
||||
|
||||
case structTag:
|
||||
t := new(types.Struct)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
*t = *types.NewStruct(p.fieldList(parent))
|
||||
return t
|
||||
|
||||
case pointerTag:
|
||||
t := new(types.Pointer)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
*t = *types.NewPointer(p.typ(parent, nil))
|
||||
return t
|
||||
|
||||
case signatureTag:
|
||||
t := new(types.Signature)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
*t = *types.NewSignature(nil, params, result, isddd)
|
||||
return t
|
||||
|
||||
case interfaceTag:
|
||||
// Create a dummy entry in the type list. This is safe because we
|
||||
// cannot expect the interface type to appear in a cycle, as any
|
||||
// such cycle must contain a named type which would have been
|
||||
// first defined earlier.
|
||||
// TODO(gri) Is this still true now that we have type aliases?
|
||||
// See issue #23225.
|
||||
n := len(p.typList)
|
||||
if p.trackAllTypes {
|
||||
p.record(nil)
|
||||
}
|
||||
|
||||
var embeddeds []types.Type
|
||||
for n := p.int(); n > 0; n-- {
|
||||
p.pos()
|
||||
embeddeds = append(embeddeds, p.typ(parent, nil))
|
||||
}
|
||||
|
||||
t := newInterface(p.methodList(parent, tname), embeddeds)
|
||||
p.interfaceList = append(p.interfaceList, t)
|
||||
if p.trackAllTypes {
|
||||
p.typList[n] = t
|
||||
}
|
||||
return t
|
||||
|
||||
case mapTag:
|
||||
t := new(types.Map)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
key := p.typ(parent, nil)
|
||||
val := p.typ(parent, nil)
|
||||
*t = *types.NewMap(key, val)
|
||||
return t
|
||||
|
||||
case chanTag:
|
||||
t := new(types.Chan)
|
||||
if p.trackAllTypes {
|
||||
p.record(t)
|
||||
}
|
||||
|
||||
dir := chanDir(p.int())
|
||||
val := p.typ(parent, nil)
|
||||
*t = *types.NewChan(dir, val)
|
||||
return t
|
||||
|
||||
default:
|
||||
errorf("unexpected type tag %d", i) // panics
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func chanDir(d int) types.ChanDir {
|
||||
// tag values must match the constants in cmd/compile/internal/gc/go.go
|
||||
switch d {
|
||||
@ -603,394 +88,6 @@ func chanDir(d int) types.ChanDir {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags []string) {
|
||||
if n := p.int(); n > 0 {
|
||||
fields = make([]*types.Var, n)
|
||||
tags = make([]string, n)
|
||||
for i := range fields {
|
||||
fields[i], tags[i] = p.field(parent)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *importer) field(parent *types.Package) (*types.Var, string) {
|
||||
pos := p.pos()
|
||||
pkg, name, alias := p.fieldName(parent)
|
||||
typ := p.typ(parent, nil)
|
||||
tag := p.string()
|
||||
|
||||
anonymous := false
|
||||
if name == "" {
|
||||
// anonymous field - typ must be T or *T and T must be a type name
|
||||
switch typ := deref(typ).(type) {
|
||||
case *types.Basic: // basic types are named types
|
||||
pkg = nil // // objects defined in Universe scope have no package
|
||||
name = typ.Name()
|
||||
case *types.Named:
|
||||
name = typ.Obj().Name()
|
||||
default:
|
||||
errorf("named base type expected")
|
||||
}
|
||||
anonymous = true
|
||||
} else if alias {
|
||||
// anonymous field: we have an explicit name because it's an alias
|
||||
anonymous = true
|
||||
}
|
||||
|
||||
return types.NewField(pos, pkg, name, typ, anonymous), tag
|
||||
}
|
||||
|
||||
func (p *importer) methodList(parent *types.Package, baseType *types.Named) (methods []*types.Func) {
|
||||
if n := p.int(); n > 0 {
|
||||
methods = make([]*types.Func, n)
|
||||
for i := range methods {
|
||||
methods[i] = p.method(parent, baseType)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *importer) method(parent *types.Package, baseType *types.Named) *types.Func {
|
||||
pos := p.pos()
|
||||
pkg, name, _ := p.fieldName(parent)
|
||||
// If we don't have a baseType, use a nil receiver.
|
||||
// A receiver using the actual interface type (which
|
||||
// we don't know yet) will be filled in when we call
|
||||
// types.Interface.Complete.
|
||||
var recv *types.Var
|
||||
if baseType != nil {
|
||||
recv = types.NewVar(token.NoPos, parent, "", baseType)
|
||||
}
|
||||
params, isddd := p.paramList()
|
||||
result, _ := p.paramList()
|
||||
sig := types.NewSignature(recv, params, result, isddd)
|
||||
return types.NewFunc(pos, pkg, name, sig)
|
||||
}
|
||||
|
||||
func (p *importer) fieldName(parent *types.Package) (pkg *types.Package, name string, alias bool) {
|
||||
name = p.string()
|
||||
pkg = parent
|
||||
if pkg == nil {
|
||||
// use the imported package instead
|
||||
pkg = p.pkgList[0]
|
||||
}
|
||||
if p.version == 0 && name == "_" {
|
||||
// version 0 didn't export a package for _ fields
|
||||
return
|
||||
}
|
||||
switch name {
|
||||
case "":
|
||||
// 1) field name matches base type name and is exported: nothing to do
|
||||
case "?":
|
||||
// 2) field name matches base type name and is not exported: need package
|
||||
name = ""
|
||||
pkg = p.pkg()
|
||||
case "@":
|
||||
// 3) field name doesn't match type name (alias)
|
||||
name = p.string()
|
||||
alias = true
|
||||
fallthrough
|
||||
default:
|
||||
if !exported(name) {
|
||||
pkg = p.pkg()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *importer) paramList() (*types.Tuple, bool) {
|
||||
n := p.int()
|
||||
if n == 0 {
|
||||
return nil, false
|
||||
}
|
||||
// negative length indicates unnamed parameters
|
||||
named := true
|
||||
if n < 0 {
|
||||
n = -n
|
||||
named = false
|
||||
}
|
||||
// n > 0
|
||||
params := make([]*types.Var, n)
|
||||
isddd := false
|
||||
for i := range params {
|
||||
params[i], isddd = p.param(named)
|
||||
}
|
||||
return types.NewTuple(params...), isddd
|
||||
}
|
||||
|
||||
func (p *importer) param(named bool) (*types.Var, bool) {
|
||||
t := p.typ(nil, nil)
|
||||
td, isddd := t.(*dddSlice)
|
||||
if isddd {
|
||||
t = types.NewSlice(td.elem)
|
||||
}
|
||||
|
||||
var pkg *types.Package
|
||||
var name string
|
||||
if named {
|
||||
name = p.string()
|
||||
if name == "" {
|
||||
errorf("expected named parameter")
|
||||
}
|
||||
if name != "_" {
|
||||
pkg = p.pkg()
|
||||
}
|
||||
if i := strings.Index(name, "·"); i > 0 {
|
||||
name = name[:i] // cut off gc-specific parameter numbering
|
||||
}
|
||||
}
|
||||
|
||||
// read and discard compiler-specific info
|
||||
p.string()
|
||||
|
||||
return types.NewVar(token.NoPos, pkg, name, t), isddd
|
||||
}
|
||||
|
||||
func exported(name string) bool {
|
||||
ch, _ := utf8.DecodeRuneInString(name)
|
||||
return unicode.IsUpper(ch)
|
||||
}
|
||||
|
||||
func (p *importer) value() constant.Value {
|
||||
switch tag := p.tagOrIndex(); tag {
|
||||
case falseTag:
|
||||
return constant.MakeBool(false)
|
||||
case trueTag:
|
||||
return constant.MakeBool(true)
|
||||
case int64Tag:
|
||||
return constant.MakeInt64(p.int64())
|
||||
case floatTag:
|
||||
return p.float()
|
||||
case complexTag:
|
||||
re := p.float()
|
||||
im := p.float()
|
||||
return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
|
||||
case stringTag:
|
||||
return constant.MakeString(p.string())
|
||||
case unknownTag:
|
||||
return constant.MakeUnknown()
|
||||
default:
|
||||
errorf("unexpected value tag %d", tag) // panics
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *importer) float() constant.Value {
|
||||
sign := p.int()
|
||||
if sign == 0 {
|
||||
return constant.MakeInt64(0)
|
||||
}
|
||||
|
||||
exp := p.int()
|
||||
mant := []byte(p.string()) // big endian
|
||||
|
||||
// remove leading 0's if any
|
||||
for len(mant) > 0 && mant[0] == 0 {
|
||||
mant = mant[1:]
|
||||
}
|
||||
|
||||
// convert to little endian
|
||||
// TODO(gri) go/constant should have a more direct conversion function
|
||||
// (e.g., once it supports a big.Float based implementation)
|
||||
for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
|
||||
mant[i], mant[j] = mant[j], mant[i]
|
||||
}
|
||||
|
||||
// adjust exponent (constant.MakeFromBytes creates an integer value,
|
||||
// but mant represents the mantissa bits such that 0.5 <= mant < 1.0)
|
||||
exp -= len(mant) << 3
|
||||
if len(mant) > 0 {
|
||||
for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
|
||||
exp++
|
||||
}
|
||||
}
|
||||
|
||||
x := constant.MakeFromBytes(mant)
|
||||
switch {
|
||||
case exp < 0:
|
||||
d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
|
||||
x = constant.BinaryOp(x, token.QUO, d)
|
||||
case exp > 0:
|
||||
x = constant.Shift(x, token.SHL, uint(exp))
|
||||
}
|
||||
|
||||
if sign < 0 {
|
||||
x = constant.UnaryOp(token.SUB, x, 0)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Low-level decoders
|
||||
|
||||
func (p *importer) tagOrIndex() int {
|
||||
if p.debugFormat {
|
||||
p.marker('t')
|
||||
}
|
||||
|
||||
return int(p.rawInt64())
|
||||
}
|
||||
|
||||
func (p *importer) int() int {
|
||||
x := p.int64()
|
||||
if int64(int(x)) != x {
|
||||
errorf("exported integer too large")
|
||||
}
|
||||
return int(x)
|
||||
}
|
||||
|
||||
func (p *importer) int64() int64 {
|
||||
if p.debugFormat {
|
||||
p.marker('i')
|
||||
}
|
||||
|
||||
return p.rawInt64()
|
||||
}
|
||||
|
||||
func (p *importer) path() string {
|
||||
if p.debugFormat {
|
||||
p.marker('p')
|
||||
}
|
||||
// if the path was seen before, i is its index (>= 0)
|
||||
// (the empty string is at index 0)
|
||||
i := p.rawInt64()
|
||||
if i >= 0 {
|
||||
return p.pathList[i]
|
||||
}
|
||||
// otherwise, i is the negative path length (< 0)
|
||||
a := make([]string, -i)
|
||||
for n := range a {
|
||||
a[n] = p.string()
|
||||
}
|
||||
s := strings.Join(a, "/")
|
||||
p.pathList = append(p.pathList, s)
|
||||
return s
|
||||
}
|
||||
|
||||
func (p *importer) string() string {
|
||||
if p.debugFormat {
|
||||
p.marker('s')
|
||||
}
|
||||
// if the string was seen before, i is its index (>= 0)
|
||||
// (the empty string is at index 0)
|
||||
i := p.rawInt64()
|
||||
if i >= 0 {
|
||||
return p.strList[i]
|
||||
}
|
||||
// otherwise, i is the negative string length (< 0)
|
||||
if n := int(-i); n <= cap(p.buf) {
|
||||
p.buf = p.buf[:n]
|
||||
} else {
|
||||
p.buf = make([]byte, n)
|
||||
}
|
||||
for i := range p.buf {
|
||||
p.buf[i] = p.rawByte()
|
||||
}
|
||||
s := string(p.buf)
|
||||
p.strList = append(p.strList, s)
|
||||
return s
|
||||
}
|
||||
|
||||
func (p *importer) marker(want byte) {
|
||||
if got := p.rawByte(); got != want {
|
||||
errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
|
||||
}
|
||||
|
||||
pos := p.read
|
||||
if n := int(p.rawInt64()); n != pos {
|
||||
errorf("incorrect position: got %d; want %d", n, pos)
|
||||
}
|
||||
}
|
||||
|
||||
// rawInt64 should only be used by low-level decoders.
|
||||
func (p *importer) rawInt64() int64 {
|
||||
i, err := binary.ReadVarint(p)
|
||||
if err != nil {
|
||||
errorf("read error: %v", err)
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// rawStringln should only be used to read the initial version string.
|
||||
func (p *importer) rawStringln(b byte) string {
|
||||
p.buf = p.buf[:0]
|
||||
for b != '\n' {
|
||||
p.buf = append(p.buf, b)
|
||||
b = p.rawByte()
|
||||
}
|
||||
return string(p.buf)
|
||||
}
|
||||
|
||||
// needed for binary.ReadVarint in rawInt64
|
||||
func (p *importer) ReadByte() (byte, error) {
|
||||
return p.rawByte(), nil
|
||||
}
|
||||
|
||||
// byte is the bottleneck interface for reading p.data.
|
||||
// It unescapes '|' 'S' to '$' and '|' '|' to '|'.
|
||||
// rawByte should only be used by low-level decoders.
|
||||
func (p *importer) rawByte() byte {
|
||||
b := p.data[0]
|
||||
r := 1
|
||||
if b == '|' {
|
||||
b = p.data[1]
|
||||
r = 2
|
||||
switch b {
|
||||
case 'S':
|
||||
b = '$'
|
||||
case '|':
|
||||
// nothing to do
|
||||
default:
|
||||
errorf("unexpected escape sequence in export data")
|
||||
}
|
||||
}
|
||||
p.data = p.data[r:]
|
||||
p.read += r
|
||||
return b
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Export format
|
||||
|
||||
// Tags. Must be < 0.
|
||||
const (
|
||||
// Objects
|
||||
packageTag = -(iota + 1)
|
||||
constTag
|
||||
typeTag
|
||||
varTag
|
||||
funcTag
|
||||
endTag
|
||||
|
||||
// Types
|
||||
namedTag
|
||||
arrayTag
|
||||
sliceTag
|
||||
dddTag
|
||||
structTag
|
||||
pointerTag
|
||||
signatureTag
|
||||
interfaceTag
|
||||
mapTag
|
||||
chanTag
|
||||
|
||||
// Values
|
||||
falseTag
|
||||
trueTag
|
||||
int64Tag
|
||||
floatTag
|
||||
fractionTag // not used by gc
|
||||
complexTag
|
||||
stringTag
|
||||
nilTag // only used by gc (appears in exported inlined function bodies)
|
||||
unknownTag // not used by gc (only appears in packages with errors)
|
||||
|
||||
// Type aliases
|
||||
aliasTag
|
||||
)
|
||||
|
||||
var predeclOnce sync.Once
|
||||
var predecl []types.Type // initialized lazily
|
||||
|
||||
|
15
vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go
generated
vendored
15
vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go
generated
vendored
@ -230,20 +230,17 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
|
||||
// Or, define a new standard go/types/gcexportdata package.
|
||||
fset := token.NewFileSet()
|
||||
|
||||
// The indexed export format starts with an 'i'; the older
|
||||
// binary export format starts with a 'c', 'd', or 'v'
|
||||
// (from "version"). Select appropriate importer.
|
||||
// Select appropriate importer.
|
||||
if len(data) > 0 {
|
||||
switch data[0] {
|
||||
case 'i':
|
||||
case 'v', 'c', 'd': // binary, till go1.10
|
||||
return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0])
|
||||
|
||||
case 'i': // indexed, till go1.19
|
||||
_, pkg, err := IImportData(fset, packages, data[1:], id)
|
||||
return pkg, err
|
||||
|
||||
case 'v', 'c', 'd':
|
||||
_, pkg, err := BImportData(fset, packages, data, id)
|
||||
return pkg, err
|
||||
|
||||
case 'u':
|
||||
case 'u': // unified, from go1.20
|
||||
_, pkg, err := UImportData(fset, packages, data[1:size], id)
|
||||
return pkg, err
|
||||
|
||||
|
27
vendor/golang.org/x/tools/internal/gcimporter/iexport.go
generated
vendored
27
vendor/golang.org/x/tools/internal/gcimporter/iexport.go
generated
vendored
@ -44,12 +44,12 @@ func IExportShallow(fset *token.FileSet, pkg *types.Package) ([]byte, error) {
|
||||
return out.Bytes(), err
|
||||
}
|
||||
|
||||
// IImportShallow decodes "shallow" types.Package data encoded by IExportShallow
|
||||
// in the same executable. This function cannot import data from
|
||||
// IImportShallow decodes "shallow" types.Package data encoded by
|
||||
// IExportShallow in the same executable. This function cannot import data from
|
||||
// cmd/compile or gcexportdata.Write.
|
||||
func IImportShallow(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string, insert InsertType) (*types.Package, error) {
|
||||
func IImportShallow(fset *token.FileSet, getPackage GetPackageFunc, data []byte, path string, insert InsertType) (*types.Package, error) {
|
||||
const bundle = false
|
||||
pkgs, err := iimportCommon(fset, imports, data, bundle, path, insert)
|
||||
pkgs, err := iimportCommon(fset, getPackage, data, bundle, path, insert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -969,6 +969,16 @@ func constantToFloat(x constant.Value) *big.Float {
|
||||
return &f
|
||||
}
|
||||
|
||||
func valueToRat(x constant.Value) *big.Rat {
|
||||
// Convert little-endian to big-endian.
|
||||
// I can't believe this is necessary.
|
||||
bytes := constant.Bytes(x)
|
||||
for i := 0; i < len(bytes)/2; i++ {
|
||||
bytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i]
|
||||
}
|
||||
return new(big.Rat).SetInt(new(big.Int).SetBytes(bytes))
|
||||
}
|
||||
|
||||
// mpint exports a multi-precision integer.
|
||||
//
|
||||
// For unsigned types, small values are written out as a single
|
||||
@ -1178,3 +1188,12 @@ func (q *objQueue) popHead() types.Object {
|
||||
q.head++
|
||||
return obj
|
||||
}
|
||||
|
||||
// internalError represents an error generated inside this package.
|
||||
type internalError string
|
||||
|
||||
func (e internalError) Error() string { return "gcimporter: " + string(e) }
|
||||
|
||||
func internalErrorf(format string, args ...interface{}) error {
|
||||
return internalError(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
43
vendor/golang.org/x/tools/internal/gcimporter/iimport.go
generated
vendored
43
vendor/golang.org/x/tools/internal/gcimporter/iimport.go
generated
vendored
@ -85,7 +85,7 @@ const (
|
||||
// If the export data version is not recognized or the format is otherwise
|
||||
// compromised, an error is returned.
|
||||
func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
|
||||
pkgs, err := iimportCommon(fset, imports, data, false, path, nil)
|
||||
pkgs, err := iimportCommon(fset, GetPackageFromMap(imports), data, false, path, nil)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
@ -94,10 +94,33 @@ func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
||||
|
||||
// IImportBundle imports a set of packages from the serialized package bundle.
|
||||
func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) {
|
||||
return iimportCommon(fset, imports, data, true, "", nil)
|
||||
return iimportCommon(fset, GetPackageFromMap(imports), data, true, "", nil)
|
||||
}
|
||||
|
||||
func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string, insert InsertType) (pkgs []*types.Package, err error) {
|
||||
// A GetPackageFunc is a function that gets the package with the given path
|
||||
// from the importer state, creating it (with the specified name) if necessary.
|
||||
// It is an abstraction of the map historically used to memoize package creation.
|
||||
//
|
||||
// Two calls with the same path must return the same package.
|
||||
//
|
||||
// If the given getPackage func returns nil, the import will fail.
|
||||
type GetPackageFunc = func(path, name string) *types.Package
|
||||
|
||||
// GetPackageFromMap returns a GetPackageFunc that retrieves packages from the
|
||||
// given map of package path -> package.
|
||||
//
|
||||
// The resulting func may mutate m: if a requested package is not found, a new
|
||||
// package will be inserted into m.
|
||||
func GetPackageFromMap(m map[string]*types.Package) GetPackageFunc {
|
||||
return func(path, name string) *types.Package {
|
||||
if _, ok := m[path]; !ok {
|
||||
m[path] = types.NewPackage(path, name)
|
||||
}
|
||||
return m[path]
|
||||
}
|
||||
}
|
||||
|
||||
func iimportCommon(fset *token.FileSet, getPackage GetPackageFunc, data []byte, bundle bool, path string, insert InsertType) (pkgs []*types.Package, err error) {
|
||||
const currentVersion = iexportVersionCurrent
|
||||
version := int64(-1)
|
||||
if !debug {
|
||||
@ -108,7 +131,7 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
||||
} else if version > currentVersion {
|
||||
err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
|
||||
} else {
|
||||
err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
|
||||
err = fmt.Errorf("internal error while importing %q (%v); please report an issue", path, e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
@ -117,11 +140,8 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
||||
r := &intReader{bytes.NewReader(data), path}
|
||||
|
||||
if bundle {
|
||||
bundleVersion := r.uint64()
|
||||
switch bundleVersion {
|
||||
case bundleVersion:
|
||||
default:
|
||||
errorf("unknown bundle format version %d", bundleVersion)
|
||||
if v := r.uint64(); v != bundleVersion {
|
||||
errorf("unknown bundle format version %d", v)
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,10 +215,9 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
||||
if pkgPath == "" {
|
||||
pkgPath = path
|
||||
}
|
||||
pkg := imports[pkgPath]
|
||||
pkg := getPackage(pkgPath, pkgName)
|
||||
if pkg == nil {
|
||||
pkg = types.NewPackage(pkgPath, pkgName)
|
||||
imports[pkgPath] = pkg
|
||||
errorf("internal error: getPackage returned nil package for %s", pkgPath)
|
||||
} else if pkg.Name() != pkgName {
|
||||
errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
|
||||
}
|
||||
|
9
vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go
generated
vendored
9
vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go
generated
vendored
@ -10,6 +10,7 @@
|
||||
package gcimporter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"sort"
|
||||
@ -63,6 +64,14 @@ type typeInfo struct {
|
||||
}
|
||||
|
||||
func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
||||
if !debug {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
err = fmt.Errorf("internal error in importing %q (%v); please report an issue", path, x)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
s := string(data)
|
||||
s = s[:strings.LastIndex(s, "\n$$\n")]
|
||||
input := pkgbits.NewPkgDecoder(path, s)
|
||||
|
146
vendor/golang.org/x/tools/internal/gocommand/invoke.go
generated
vendored
146
vendor/golang.org/x/tools/internal/gocommand/invoke.go
generated
vendored
@ -8,10 +8,12 @@ package gocommand
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@ -22,6 +24,9 @@ import (
|
||||
exec "golang.org/x/sys/execabs"
|
||||
|
||||
"golang.org/x/tools/internal/event"
|
||||
"golang.org/x/tools/internal/event/keys"
|
||||
"golang.org/x/tools/internal/event/label"
|
||||
"golang.org/x/tools/internal/event/tag"
|
||||
)
|
||||
|
||||
// An Runner will run go command invocations and serialize
|
||||
@ -51,9 +56,19 @@ func (runner *Runner) initialize() {
|
||||
// 1.14: go: updating go.mod: existing contents have changed since last read
|
||||
var modConcurrencyError = regexp.MustCompile(`go:.*go.mod.*contents have changed`)
|
||||
|
||||
// verb is an event label for the go command verb.
|
||||
var verb = keys.NewString("verb", "go command verb")
|
||||
|
||||
func invLabels(inv Invocation) []label.Label {
|
||||
return []label.Label{verb.Of(inv.Verb), tag.Directory.Of(inv.WorkingDir)}
|
||||
}
|
||||
|
||||
// Run is a convenience wrapper around RunRaw.
|
||||
// It returns only stdout and a "friendly" error.
|
||||
func (runner *Runner) Run(ctx context.Context, inv Invocation) (*bytes.Buffer, error) {
|
||||
ctx, done := event.Start(ctx, "gocommand.Runner.Run", invLabels(inv)...)
|
||||
defer done()
|
||||
|
||||
stdout, _, friendly, _ := runner.RunRaw(ctx, inv)
|
||||
return stdout, friendly
|
||||
}
|
||||
@ -61,6 +76,9 @@ func (runner *Runner) Run(ctx context.Context, inv Invocation) (*bytes.Buffer, e
|
||||
// RunPiped runs the invocation serially, always waiting for any concurrent
|
||||
// invocations to complete first.
|
||||
func (runner *Runner) RunPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) error {
|
||||
ctx, done := event.Start(ctx, "gocommand.Runner.RunPiped", invLabels(inv)...)
|
||||
defer done()
|
||||
|
||||
_, err := runner.runPiped(ctx, inv, stdout, stderr)
|
||||
return err
|
||||
}
|
||||
@ -68,6 +86,8 @@ func (runner *Runner) RunPiped(ctx context.Context, inv Invocation, stdout, stde
|
||||
// RunRaw runs the invocation, serializing requests only if they fight over
|
||||
// go.mod changes.
|
||||
func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {
|
||||
ctx, done := event.Start(ctx, "gocommand.Runner.RunRaw", invLabels(inv)...)
|
||||
defer done()
|
||||
// Make sure the runner is always initialized.
|
||||
runner.initialize()
|
||||
|
||||
@ -215,6 +235,18 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
||||
cmd := exec.Command("go", goArgs...)
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
|
||||
// cmd.WaitDelay was added only in go1.20 (see #50436).
|
||||
if waitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); waitDelay.IsValid() {
|
||||
// https://go.dev/issue/59541: don't wait forever copying stderr
|
||||
// after the command has exited.
|
||||
// After CL 484741 we copy stdout manually, so we we'll stop reading that as
|
||||
// soon as ctx is done. However, we also don't want to wait around forever
|
||||
// for stderr. Give a much-longer-than-reasonable delay and then assume that
|
||||
// something has wedged in the kernel or runtime.
|
||||
waitDelay.Set(reflect.ValueOf(30 * time.Second))
|
||||
}
|
||||
|
||||
// On darwin the cwd gets resolved to the real path, which breaks anything that
|
||||
// expects the working directory to keep the original path, including the
|
||||
// go command when dealing with modules.
|
||||
@ -229,6 +261,7 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
||||
cmd.Env = append(cmd.Env, "PWD="+i.WorkingDir)
|
||||
cmd.Dir = i.WorkingDir
|
||||
}
|
||||
|
||||
defer func(start time.Time) { log("%s for %v", time.Since(start), cmdDebugStr(cmd)) }(time.Now())
|
||||
|
||||
return runCmdContext(ctx, cmd)
|
||||
@ -242,10 +275,85 @@ var DebugHangingGoCommands = false
|
||||
|
||||
// runCmdContext is like exec.CommandContext except it sends os.Interrupt
|
||||
// before os.Kill.
|
||||
func runCmdContext(ctx context.Context, cmd *exec.Cmd) error {
|
||||
if err := cmd.Start(); err != nil {
|
||||
func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
|
||||
// If cmd.Stdout is not an *os.File, the exec package will create a pipe and
|
||||
// copy it to the Writer in a goroutine until the process has finished and
|
||||
// either the pipe reaches EOF or command's WaitDelay expires.
|
||||
//
|
||||
// However, the output from 'go list' can be quite large, and we don't want to
|
||||
// keep reading (and allocating buffers) if we've already decided we don't
|
||||
// care about the output. We don't want to wait for the process to finish, and
|
||||
// we don't wait to wait for the WaitDelay to expire either.
|
||||
//
|
||||
// Instead, if cmd.Stdout requires a copying goroutine we explicitly replace
|
||||
// it with a pipe (which is an *os.File), which we can close in order to stop
|
||||
// copying output as soon as we realize we don't care about it.
|
||||
var stdoutW *os.File
|
||||
if cmd.Stdout != nil {
|
||||
if _, ok := cmd.Stdout.(*os.File); !ok {
|
||||
var stdoutR *os.File
|
||||
stdoutR, stdoutW, err = os.Pipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prevStdout := cmd.Stdout
|
||||
cmd.Stdout = stdoutW
|
||||
|
||||
stdoutErr := make(chan error, 1)
|
||||
go func() {
|
||||
_, err := io.Copy(prevStdout, stdoutR)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("copying stdout: %w", err)
|
||||
}
|
||||
stdoutErr <- err
|
||||
}()
|
||||
defer func() {
|
||||
// We started a goroutine to copy a stdout pipe.
|
||||
// Wait for it to finish, or terminate it if need be.
|
||||
var err2 error
|
||||
select {
|
||||
case err2 = <-stdoutErr:
|
||||
stdoutR.Close()
|
||||
case <-ctx.Done():
|
||||
stdoutR.Close()
|
||||
// Per https://pkg.go.dev/os#File.Close, the call to stdoutR.Close
|
||||
// should cause the Read call in io.Copy to unblock and return
|
||||
// immediately, but we still need to receive from stdoutErr to confirm
|
||||
// that that has happened.
|
||||
<-stdoutErr
|
||||
err2 = ctx.Err()
|
||||
}
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
}()
|
||||
|
||||
// Per https://pkg.go.dev/os/exec#Cmd, “If Stdout and Stderr are the
|
||||
// same writer, and have a type that can be compared with ==, at most
|
||||
// one goroutine at a time will call Write.”
|
||||
//
|
||||
// Since we're starting a goroutine that writes to cmd.Stdout, we must
|
||||
// also update cmd.Stderr so that that still holds.
|
||||
func() {
|
||||
defer func() { recover() }()
|
||||
if cmd.Stderr == prevStdout {
|
||||
cmd.Stderr = cmd.Stdout
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
err = cmd.Start()
|
||||
if stdoutW != nil {
|
||||
// The child process has inherited the pipe file,
|
||||
// so close the copy held in this process.
|
||||
stdoutW.Close()
|
||||
stdoutW = nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resChan := make(chan error, 1)
|
||||
go func() {
|
||||
resChan <- cmd.Wait()
|
||||
@ -253,11 +361,14 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) error {
|
||||
|
||||
// If we're interested in debugging hanging Go commands, stop waiting after a
|
||||
// minute and panic with interesting information.
|
||||
if DebugHangingGoCommands {
|
||||
debug := DebugHangingGoCommands
|
||||
if debug {
|
||||
timer := time.NewTimer(1 * time.Minute)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case err := <-resChan:
|
||||
return err
|
||||
case <-time.After(1 * time.Minute):
|
||||
case <-timer.C:
|
||||
HandleHangingGoCommand(cmd.Process)
|
||||
case <-ctx.Done():
|
||||
}
|
||||
@ -270,30 +381,25 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) error {
|
||||
}
|
||||
|
||||
// Cancelled. Interrupt and see if it ends voluntarily.
|
||||
cmd.Process.Signal(os.Interrupt)
|
||||
select {
|
||||
case err := <-resChan:
|
||||
return err
|
||||
case <-time.After(time.Second):
|
||||
if err := cmd.Process.Signal(os.Interrupt); err == nil {
|
||||
// (We used to wait only 1s but this proved
|
||||
// fragile on loaded builder machines.)
|
||||
timer := time.NewTimer(5 * time.Second)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case err := <-resChan:
|
||||
return err
|
||||
case <-timer.C:
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't shut down in response to interrupt. Kill it hard.
|
||||
// TODO(rfindley): per advice from bcmills@, it may be better to send SIGQUIT
|
||||
// on certain platforms, such as unix.
|
||||
if err := cmd.Process.Kill(); err != nil && DebugHangingGoCommands {
|
||||
// Don't panic here as this reliably fails on windows with EINVAL.
|
||||
if err := cmd.Process.Kill(); err != nil && !errors.Is(err, os.ErrProcessDone) && debug {
|
||||
log.Printf("error killing the Go command: %v", err)
|
||||
}
|
||||
|
||||
// See above: don't wait indefinitely if we're debugging hanging Go commands.
|
||||
if DebugHangingGoCommands {
|
||||
select {
|
||||
case err := <-resChan:
|
||||
return err
|
||||
case <-time.After(10 * time.Second): // a shorter wait as resChan should return quickly following Kill
|
||||
HandleHangingGoCommand(cmd.Process)
|
||||
}
|
||||
}
|
||||
return <-resChan
|
||||
}
|
||||
|
||||
|
18
vendor/golang.org/x/tools/internal/gocommand/version.go
generated
vendored
18
vendor/golang.org/x/tools/internal/gocommand/version.go
generated
vendored
@ -23,21 +23,11 @@ import (
|
||||
func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) {
|
||||
inv.Verb = "list"
|
||||
inv.Args = []string{"-e", "-f", `{{context.ReleaseTags}}`, `--`, `unsafe`}
|
||||
inv.Env = append(append([]string{}, inv.Env...), "GO111MODULE=off")
|
||||
// Unset any unneeded flags, and remove them from BuildFlags, if they're
|
||||
// present.
|
||||
inv.ModFile = ""
|
||||
inv.BuildFlags = nil // This is not a build command.
|
||||
inv.ModFlag = ""
|
||||
var buildFlags []string
|
||||
for _, flag := range inv.BuildFlags {
|
||||
// Flags can be prefixed by one or two dashes.
|
||||
f := strings.TrimPrefix(strings.TrimPrefix(flag, "-"), "-")
|
||||
if strings.HasPrefix(f, "mod=") || strings.HasPrefix(f, "modfile=") {
|
||||
continue
|
||||
}
|
||||
buildFlags = append(buildFlags, flag)
|
||||
}
|
||||
inv.BuildFlags = buildFlags
|
||||
inv.ModFile = ""
|
||||
inv.Env = append(inv.Env[:len(inv.Env):len(inv.Env)], "GO111MODULE=off")
|
||||
|
||||
stdoutBytes, err := r.Run(ctx, inv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
92
vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go
generated
vendored
92
vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go
generated
vendored
@ -7,7 +7,9 @@
|
||||
package tokeninternal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"sort"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
@ -57,3 +59,93 @@ func GetLines(file *token.File) []int {
|
||||
panic("unexpected token.File size")
|
||||
}
|
||||
}
|
||||
|
||||
// AddExistingFiles adds the specified files to the FileSet if they
|
||||
// are not already present. It panics if any pair of files in the
|
||||
// resulting FileSet would overlap.
|
||||
func AddExistingFiles(fset *token.FileSet, files []*token.File) {
|
||||
// Punch through the FileSet encapsulation.
|
||||
type tokenFileSet struct {
|
||||
// This type remained essentially consistent from go1.16 to go1.21.
|
||||
mutex sync.RWMutex
|
||||
base int
|
||||
files []*token.File
|
||||
_ *token.File // changed to atomic.Pointer[token.File] in go1.19
|
||||
}
|
||||
|
||||
// If the size of token.FileSet changes, this will fail to compile.
|
||||
const delta = int64(unsafe.Sizeof(tokenFileSet{})) - int64(unsafe.Sizeof(token.FileSet{}))
|
||||
var _ [-delta * delta]int
|
||||
|
||||
type uP = unsafe.Pointer
|
||||
var ptr *tokenFileSet
|
||||
*(*uP)(uP(&ptr)) = uP(fset)
|
||||
ptr.mutex.Lock()
|
||||
defer ptr.mutex.Unlock()
|
||||
|
||||
// Merge and sort.
|
||||
newFiles := append(ptr.files, files...)
|
||||
sort.Slice(newFiles, func(i, j int) bool {
|
||||
return newFiles[i].Base() < newFiles[j].Base()
|
||||
})
|
||||
|
||||
// Reject overlapping files.
|
||||
// Discard adjacent identical files.
|
||||
out := newFiles[:0]
|
||||
for i, file := range newFiles {
|
||||
if i > 0 {
|
||||
prev := newFiles[i-1]
|
||||
if file == prev {
|
||||
continue
|
||||
}
|
||||
if prev.Base()+prev.Size()+1 > file.Base() {
|
||||
panic(fmt.Sprintf("file %s (%d-%d) overlaps with file %s (%d-%d)",
|
||||
prev.Name(), prev.Base(), prev.Base()+prev.Size(),
|
||||
file.Name(), file.Base(), file.Base()+file.Size()))
|
||||
}
|
||||
}
|
||||
out = append(out, file)
|
||||
}
|
||||
newFiles = out
|
||||
|
||||
ptr.files = newFiles
|
||||
|
||||
// Advance FileSet.Base().
|
||||
if len(newFiles) > 0 {
|
||||
last := newFiles[len(newFiles)-1]
|
||||
newBase := last.Base() + last.Size() + 1
|
||||
if ptr.base < newBase {
|
||||
ptr.base = newBase
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FileSetFor returns a new FileSet containing a sequence of new Files with
|
||||
// the same base, size, and line as the input files, for use in APIs that
|
||||
// require a FileSet.
|
||||
//
|
||||
// Precondition: the input files must be non-overlapping, and sorted in order
|
||||
// of their Base.
|
||||
func FileSetFor(files ...*token.File) *token.FileSet {
|
||||
fset := token.NewFileSet()
|
||||
for _, f := range files {
|
||||
f2 := fset.AddFile(f.Name(), f.Base(), f.Size())
|
||||
lines := GetLines(f)
|
||||
f2.SetLines(lines)
|
||||
}
|
||||
return fset
|
||||
}
|
||||
|
||||
// CloneFileSet creates a new FileSet holding all files in fset. It does not
|
||||
// create copies of the token.Files in fset: they are added to the resulting
|
||||
// FileSet unmodified.
|
||||
func CloneFileSet(fset *token.FileSet) *token.FileSet {
|
||||
var files []*token.File
|
||||
fset.Iterate(func(f *token.File) bool {
|
||||
files = append(files, f)
|
||||
return true
|
||||
})
|
||||
newFileSet := token.NewFileSet()
|
||||
AddExistingFiles(newFileSet, files)
|
||||
return newFileSet
|
||||
}
|
||||
|
9
vendor/golang.org/x/tools/internal/typesinternal/types.go
generated
vendored
9
vendor/golang.org/x/tools/internal/typesinternal/types.go
generated
vendored
@ -11,8 +11,6 @@ import (
|
||||
"go/types"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/tools/go/types/objectpath"
|
||||
)
|
||||
|
||||
func SetUsesCgo(conf *types.Config) bool {
|
||||
@ -52,10 +50,3 @@ func ReadGo116ErrorData(err types.Error) (code ErrorCode, start, end token.Pos,
|
||||
}
|
||||
|
||||
var SetGoVersion = func(conf *types.Config, version string) bool { return false }
|
||||
|
||||
// NewObjectpathEncoder returns a function closure equivalent to
|
||||
// objectpath.For but amortized for multiple (sequential) calls.
|
||||
// It is a temporary workaround, pending the approval of proposal 58668.
|
||||
//
|
||||
//go:linkname NewObjectpathFunc golang.org/x/tools/go/types/objectpath.newEncoderFor
|
||||
func NewObjectpathFunc() func(types.Object) (objectpath.Path, error)
|
||||
|
Reference in New Issue
Block a user