Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / go / internal / gcimporter / iexport.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/go/internal/gcimporter/iexport.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/go/internal/gcimporter/iexport.go
new file mode 100644 (file)
index 0000000..4be32a2
--- /dev/null
@@ -0,0 +1,739 @@
+// 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.
+
+// Indexed binary package export.
+// This file was derived from $GOROOT/src/cmd/compile/internal/gc/iexport.go;
+// see that file for specification of the format.
+
+package gcimporter
+
+import (
+       "bytes"
+       "encoding/binary"
+       "go/ast"
+       "go/constant"
+       "go/token"
+       "go/types"
+       "io"
+       "math/big"
+       "reflect"
+       "sort"
+)
+
+// Current indexed export format version. Increase with each format change.
+// 0: Go1.11 encoding
+const iexportVersion = 0
+
+// IExportData returns the binary export data for pkg.
+//
+// If no file set is provided, position info will be missing.
+// The package path of the top-level package will not be recorded,
+// so that calls to IImportData can override with a provided package path.
+func IExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) {
+       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 := iexporter{
+               out:         bytes.NewBuffer(nil),
+               fset:        fset,
+               allPkgs:     map[*types.Package]bool{},
+               stringIndex: map[string]uint64{},
+               declIndex:   map[types.Object]uint64{},
+               typIndex:    map[types.Type]uint64{},
+               localpkg:    pkg,
+       }
+
+       for i, pt := range predeclared() {
+               p.typIndex[pt] = uint64(i)
+       }
+       if len(p.typIndex) > predeclReserved {
+               panic(internalErrorf("too many predeclared types: %d > %d", len(p.typIndex), predeclReserved))
+       }
+
+       // Initialize work queue with exported declarations.
+       scope := pkg.Scope()
+       for _, name := range scope.Names() {
+               if ast.IsExported(name) {
+                       p.pushDecl(scope.Lookup(name))
+               }
+       }
+
+       // Loop until no more work.
+       for !p.declTodo.empty() {
+               p.doDecl(p.declTodo.popHead())
+       }
+
+       // Append indices to data0 section.
+       dataLen := uint64(p.data0.Len())
+       w := p.newWriter()
+       w.writeIndex(p.declIndex)
+       w.flush()
+
+       // Assemble header.
+       var hdr intWriter
+       hdr.WriteByte('i')
+       hdr.uint64(iexportVersion)
+       hdr.uint64(uint64(p.strings.Len()))
+       hdr.uint64(dataLen)
+
+       // Flush output.
+       io.Copy(p.out, &hdr)
+       io.Copy(p.out, &p.strings)
+       io.Copy(p.out, &p.data0)
+
+       return p.out.Bytes(), nil
+}
+
+// writeIndex writes out an object index. mainIndex indicates whether
+// we're writing out the main index, which is also read by
+// non-compiler tools and includes a complete package description
+// (i.e., name and height).
+func (w *exportWriter) writeIndex(index map[types.Object]uint64) {
+       // Build a map from packages to objects from that package.
+       pkgObjs := map[*types.Package][]types.Object{}
+
+       // For the main index, make sure to include every package that
+       // we reference, even if we're not exporting (or reexporting)
+       // any symbols from it.
+       pkgObjs[w.p.localpkg] = nil
+       for pkg := range w.p.allPkgs {
+               pkgObjs[pkg] = nil
+       }
+
+       for obj := range index {
+               pkgObjs[obj.Pkg()] = append(pkgObjs[obj.Pkg()], obj)
+       }
+
+       var pkgs []*types.Package
+       for pkg, objs := range pkgObjs {
+               pkgs = append(pkgs, pkg)
+
+               sort.Slice(objs, func(i, j int) bool {
+                       return objs[i].Name() < objs[j].Name()
+               })
+       }
+
+       sort.Slice(pkgs, func(i, j int) bool {
+               return w.exportPath(pkgs[i]) < w.exportPath(pkgs[j])
+       })
+
+       w.uint64(uint64(len(pkgs)))
+       for _, pkg := range pkgs {
+               w.string(w.exportPath(pkg))
+               w.string(pkg.Name())
+               w.uint64(uint64(0)) // package height is not needed for go/types
+
+               objs := pkgObjs[pkg]
+               w.uint64(uint64(len(objs)))
+               for _, obj := range objs {
+                       w.string(obj.Name())
+                       w.uint64(index[obj])
+               }
+       }
+}
+
+type iexporter struct {
+       fset *token.FileSet
+       out  *bytes.Buffer
+
+       localpkg *types.Package
+
+       // allPkgs tracks all packages that have been referenced by
+       // the export data, so we can ensure to include them in the
+       // main index.
+       allPkgs map[*types.Package]bool
+
+       declTodo objQueue
+
+       strings     intWriter
+       stringIndex map[string]uint64
+
+       data0     intWriter
+       declIndex map[types.Object]uint64
+       typIndex  map[types.Type]uint64
+}
+
+// stringOff returns the offset of s within the string section.
+// If not already present, it's added to the end.
+func (p *iexporter) stringOff(s string) uint64 {
+       off, ok := p.stringIndex[s]
+       if !ok {
+               off = uint64(p.strings.Len())
+               p.stringIndex[s] = off
+
+               p.strings.uint64(uint64(len(s)))
+               p.strings.WriteString(s)
+       }
+       return off
+}
+
+// pushDecl adds n to the declaration work queue, if not already present.
+func (p *iexporter) pushDecl(obj types.Object) {
+       // Package unsafe is known to the compiler and predeclared.
+       assert(obj.Pkg() != types.Unsafe)
+
+       if _, ok := p.declIndex[obj]; ok {
+               return
+       }
+
+       p.declIndex[obj] = ^uint64(0) // mark n present in work queue
+       p.declTodo.pushTail(obj)
+}
+
+// exportWriter handles writing out individual data section chunks.
+type exportWriter struct {
+       p *iexporter
+
+       data     intWriter
+       currPkg  *types.Package
+       prevFile string
+       prevLine int64
+}
+
+func (w *exportWriter) exportPath(pkg *types.Package) string {
+       if pkg == w.p.localpkg {
+               return ""
+       }
+       return pkg.Path()
+}
+
+func (p *iexporter) doDecl(obj types.Object) {
+       w := p.newWriter()
+       w.setPkg(obj.Pkg(), false)
+
+       switch obj := obj.(type) {
+       case *types.Var:
+               w.tag('V')
+               w.pos(obj.Pos())
+               w.typ(obj.Type(), obj.Pkg())
+
+       case *types.Func:
+               sig, _ := obj.Type().(*types.Signature)
+               if sig.Recv() != nil {
+                       panic(internalErrorf("unexpected method: %v", sig))
+               }
+               w.tag('F')
+               w.pos(obj.Pos())
+               w.signature(sig)
+
+       case *types.Const:
+               w.tag('C')
+               w.pos(obj.Pos())
+               w.value(obj.Type(), obj.Val())
+
+       case *types.TypeName:
+               if obj.IsAlias() {
+                       w.tag('A')
+                       w.pos(obj.Pos())
+                       w.typ(obj.Type(), obj.Pkg())
+                       break
+               }
+
+               // Defined type.
+               w.tag('T')
+               w.pos(obj.Pos())
+
+               underlying := obj.Type().Underlying()
+               w.typ(underlying, obj.Pkg())
+
+               t := obj.Type()
+               if types.IsInterface(t) {
+                       break
+               }
+
+               named, ok := t.(*types.Named)
+               if !ok {
+                       panic(internalErrorf("%s is not a defined type", t))
+               }
+
+               n := named.NumMethods()
+               w.uint64(uint64(n))
+               for i := 0; i < n; i++ {
+                       m := named.Method(i)
+                       w.pos(m.Pos())
+                       w.string(m.Name())
+                       sig, _ := m.Type().(*types.Signature)
+                       w.param(sig.Recv())
+                       w.signature(sig)
+               }
+
+       default:
+               panic(internalErrorf("unexpected object: %v", obj))
+       }
+
+       p.declIndex[obj] = w.flush()
+}
+
+func (w *exportWriter) tag(tag byte) {
+       w.data.WriteByte(tag)
+}
+
+func (w *exportWriter) pos(pos token.Pos) {
+       if w.p.fset == nil {
+               w.int64(0)
+               return
+       }
+
+       p := w.p.fset.Position(pos)
+       file := p.Filename
+       line := int64(p.Line)
+
+       // When file is the same as the last position (common case),
+       // we can save a few bytes by delta encoding just the line
+       // number.
+       //
+       // Note: Because data objects may be read out of order (or not
+       // at all), we can only apply delta encoding within a single
+       // object. This is handled implicitly by tracking prevFile and
+       // prevLine as fields of exportWriter.
+
+       if file == w.prevFile {
+               delta := line - w.prevLine
+               w.int64(delta)
+               if delta == deltaNewFile {
+                       w.int64(-1)
+               }
+       } else {
+               w.int64(deltaNewFile)
+               w.int64(line) // line >= 0
+               w.string(file)
+               w.prevFile = file
+       }
+       w.prevLine = line
+}
+
+func (w *exportWriter) pkg(pkg *types.Package) {
+       // Ensure any referenced packages are declared in the main index.
+       w.p.allPkgs[pkg] = true
+
+       w.string(w.exportPath(pkg))
+}
+
+func (w *exportWriter) qualifiedIdent(obj types.Object) {
+       // Ensure any referenced declarations are written out too.
+       w.p.pushDecl(obj)
+
+       w.string(obj.Name())
+       w.pkg(obj.Pkg())
+}
+
+func (w *exportWriter) typ(t types.Type, pkg *types.Package) {
+       w.data.uint64(w.p.typOff(t, pkg))
+}
+
+func (p *iexporter) newWriter() *exportWriter {
+       return &exportWriter{p: p}
+}
+
+func (w *exportWriter) flush() uint64 {
+       off := uint64(w.p.data0.Len())
+       io.Copy(&w.p.data0, &w.data)
+       return off
+}
+
+func (p *iexporter) typOff(t types.Type, pkg *types.Package) uint64 {
+       off, ok := p.typIndex[t]
+       if !ok {
+               w := p.newWriter()
+               w.doTyp(t, pkg)
+               off = predeclReserved + w.flush()
+               p.typIndex[t] = off
+       }
+       return off
+}
+
+func (w *exportWriter) startType(k itag) {
+       w.data.uint64(uint64(k))
+}
+
+func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
+       switch t := t.(type) {
+       case *types.Named:
+               w.startType(definedType)
+               w.qualifiedIdent(t.Obj())
+
+       case *types.Pointer:
+               w.startType(pointerType)
+               w.typ(t.Elem(), pkg)
+
+       case *types.Slice:
+               w.startType(sliceType)
+               w.typ(t.Elem(), pkg)
+
+       case *types.Array:
+               w.startType(arrayType)
+               w.uint64(uint64(t.Len()))
+               w.typ(t.Elem(), pkg)
+
+       case *types.Chan:
+               w.startType(chanType)
+               // 1 RecvOnly; 2 SendOnly; 3 SendRecv
+               var dir uint64
+               switch t.Dir() {
+               case types.RecvOnly:
+                       dir = 1
+               case types.SendOnly:
+                       dir = 2
+               case types.SendRecv:
+                       dir = 3
+               }
+               w.uint64(dir)
+               w.typ(t.Elem(), pkg)
+
+       case *types.Map:
+               w.startType(mapType)
+               w.typ(t.Key(), pkg)
+               w.typ(t.Elem(), pkg)
+
+       case *types.Signature:
+               w.startType(signatureType)
+               w.setPkg(pkg, true)
+               w.signature(t)
+
+       case *types.Struct:
+               w.startType(structType)
+               w.setPkg(pkg, true)
+
+               n := t.NumFields()
+               w.uint64(uint64(n))
+               for i := 0; i < n; i++ {
+                       f := t.Field(i)
+                       w.pos(f.Pos())
+                       w.string(f.Name())
+                       w.typ(f.Type(), pkg)
+                       w.bool(f.Anonymous())
+                       w.string(t.Tag(i)) // note (or tag)
+               }
+
+       case *types.Interface:
+               w.startType(interfaceType)
+               w.setPkg(pkg, true)
+
+               n := t.NumEmbeddeds()
+               w.uint64(uint64(n))
+               for i := 0; i < n; i++ {
+                       f := t.Embedded(i)
+                       w.pos(f.Obj().Pos())
+                       w.typ(f.Obj().Type(), f.Obj().Pkg())
+               }
+
+               n = t.NumExplicitMethods()
+               w.uint64(uint64(n))
+               for i := 0; i < n; i++ {
+                       m := t.ExplicitMethod(i)
+                       w.pos(m.Pos())
+                       w.string(m.Name())
+                       sig, _ := m.Type().(*types.Signature)
+                       w.signature(sig)
+               }
+
+       default:
+               panic(internalErrorf("unexpected type: %v, %v", t, reflect.TypeOf(t)))
+       }
+}
+
+func (w *exportWriter) setPkg(pkg *types.Package, write bool) {
+       if write {
+               w.pkg(pkg)
+       }
+
+       w.currPkg = pkg
+}
+
+func (w *exportWriter) signature(sig *types.Signature) {
+       w.paramList(sig.Params())
+       w.paramList(sig.Results())
+       if sig.Params().Len() > 0 {
+               w.bool(sig.Variadic())
+       }
+}
+
+func (w *exportWriter) paramList(tup *types.Tuple) {
+       n := tup.Len()
+       w.uint64(uint64(n))
+       for i := 0; i < n; i++ {
+               w.param(tup.At(i))
+       }
+}
+
+func (w *exportWriter) param(obj types.Object) {
+       w.pos(obj.Pos())
+       w.localIdent(obj)
+       w.typ(obj.Type(), obj.Pkg())
+}
+
+func (w *exportWriter) value(typ types.Type, v constant.Value) {
+       w.typ(typ, nil)
+
+       switch v.Kind() {
+       case constant.Bool:
+               w.bool(constant.BoolVal(v))
+       case constant.Int:
+               var i big.Int
+               if i64, exact := constant.Int64Val(v); exact {
+                       i.SetInt64(i64)
+               } else if ui64, exact := constant.Uint64Val(v); exact {
+                       i.SetUint64(ui64)
+               } else {
+                       i.SetString(v.ExactString(), 10)
+               }
+               w.mpint(&i, typ)
+       case constant.Float:
+               f := constantToFloat(v)
+               w.mpfloat(f, typ)
+       case constant.Complex:
+               w.mpfloat(constantToFloat(constant.Real(v)), typ)
+               w.mpfloat(constantToFloat(constant.Imag(v)), typ)
+       case constant.String:
+               w.string(constant.StringVal(v))
+       case constant.Unknown:
+               // package contains type errors
+       default:
+               panic(internalErrorf("unexpected value %v (%T)", v, v))
+       }
+}
+
+// constantToFloat converts a constant.Value with kind constant.Float to a
+// big.Float.
+func constantToFloat(x constant.Value) *big.Float {
+       assert(x.Kind() == constant.Float)
+       // Use the same floating-point precision (512) as cmd/compile
+       // (see Mpprec in cmd/compile/internal/gc/mpfloat.go).
+       const mpprec = 512
+       var f big.Float
+       f.SetPrec(mpprec)
+       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.
+               n := valueToRat(num)
+               d := valueToRat(denom)
+               f.SetRat(n.Quo(n, d))
+       } else {
+               // Value too large to represent as a fraction => inaccessible.
+               // TODO(gri): add big.Float accessor to constant.Value.
+               _, ok := f.SetString(x.ExactString())
+               assert(ok)
+       }
+       return &f
+}
+
+// mpint exports a multi-precision integer.
+//
+// For unsigned types, small values are written out as a single
+// byte. Larger values are written out as a length-prefixed big-endian
+// byte string, where the length prefix is encoded as its complement.
+// For example, bytes 0, 1, and 2 directly represent the integer
+// values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-,
+// 2-, and 3-byte big-endian string follow.
+//
+// Encoding for signed types use the same general approach as for
+// unsigned types, except small values use zig-zag encoding and the
+// bottom bit of length prefix byte for large values is reserved as a
+// sign bit.
+//
+// The exact boundary between small and large encodings varies
+// according to the maximum number of bytes needed to encode a value
+// of type typ. As a special case, 8-bit types are always encoded as a
+// single byte.
+//
+// TODO(mdempsky): Is this level of complexity really worthwhile?
+func (w *exportWriter) mpint(x *big.Int, typ types.Type) {
+       basic, ok := typ.Underlying().(*types.Basic)
+       if !ok {
+               panic(internalErrorf("unexpected type %v (%T)", typ.Underlying(), typ.Underlying()))
+       }
+
+       signed, maxBytes := intSize(basic)
+
+       negative := x.Sign() < 0
+       if !signed && negative {
+               panic(internalErrorf("negative unsigned integer; type %v, value %v", typ, x))
+       }
+
+       b := x.Bytes()
+       if len(b) > 0 && b[0] == 0 {
+               panic(internalErrorf("leading zeros"))
+       }
+       if uint(len(b)) > maxBytes {
+               panic(internalErrorf("bad mpint length: %d > %d (type %v, value %v)", len(b), maxBytes, typ, x))
+       }
+
+       maxSmall := 256 - maxBytes
+       if signed {
+               maxSmall = 256 - 2*maxBytes
+       }
+       if maxBytes == 1 {
+               maxSmall = 256
+       }
+
+       // Check if x can use small value encoding.
+       if len(b) <= 1 {
+               var ux uint
+               if len(b) == 1 {
+                       ux = uint(b[0])
+               }
+               if signed {
+                       ux <<= 1
+                       if negative {
+                               ux--
+                       }
+               }
+               if ux < maxSmall {
+                       w.data.WriteByte(byte(ux))
+                       return
+               }
+       }
+
+       n := 256 - uint(len(b))
+       if signed {
+               n = 256 - 2*uint(len(b))
+               if negative {
+                       n |= 1
+               }
+       }
+       if n < maxSmall || n >= 256 {
+               panic(internalErrorf("encoding mistake: %d, %v, %v => %d", len(b), signed, negative, n))
+       }
+
+       w.data.WriteByte(byte(n))
+       w.data.Write(b)
+}
+
+// mpfloat exports a multi-precision floating point number.
+//
+// The number's value is decomposed into mantissa × 2**exponent, where
+// mantissa is an integer. The value is written out as mantissa (as a
+// multi-precision integer) and then the exponent, except exponent is
+// omitted if mantissa is zero.
+func (w *exportWriter) mpfloat(f *big.Float, typ types.Type) {
+       if f.IsInf() {
+               panic("infinite constant")
+       }
+
+       // Break into f = mant × 2**exp, with 0.5 <= mant < 1.
+       var mant big.Float
+       exp := int64(f.MantExp(&mant))
+
+       // Scale so that mant is an integer.
+       prec := mant.MinPrec()
+       mant.SetMantExp(&mant, int(prec))
+       exp -= int64(prec)
+
+       manti, acc := mant.Int(nil)
+       if acc != big.Exact {
+               panic(internalErrorf("mantissa scaling failed for %f (%s)", f, acc))
+       }
+       w.mpint(manti, typ)
+       if manti.Sign() != 0 {
+               w.int64(exp)
+       }
+}
+
+func (w *exportWriter) bool(b bool) bool {
+       var x uint64
+       if b {
+               x = 1
+       }
+       w.uint64(x)
+       return b
+}
+
+func (w *exportWriter) int64(x int64)   { w.data.int64(x) }
+func (w *exportWriter) uint64(x uint64) { w.data.uint64(x) }
+func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
+
+func (w *exportWriter) localIdent(obj types.Object) {
+       // Anonymous parameters.
+       if obj == nil {
+               w.string("")
+               return
+       }
+
+       name := obj.Name()
+       if name == "_" {
+               w.string("_")
+               return
+       }
+
+       w.string(name)
+}
+
+type intWriter struct {
+       bytes.Buffer
+}
+
+func (w *intWriter) int64(x int64) {
+       var buf [binary.MaxVarintLen64]byte
+       n := binary.PutVarint(buf[:], x)
+       w.Write(buf[:n])
+}
+
+func (w *intWriter) uint64(x uint64) {
+       var buf [binary.MaxVarintLen64]byte
+       n := binary.PutUvarint(buf[:], x)
+       w.Write(buf[:n])
+}
+
+func assert(cond bool) {
+       if !cond {
+               panic("internal error: assertion failed")
+       }
+}
+
+// The below is copied from go/src/cmd/compile/internal/gc/syntax.go.
+
+// objQueue is a FIFO queue of types.Object. The zero value of objQueue is
+// a ready-to-use empty queue.
+type objQueue struct {
+       ring       []types.Object
+       head, tail int
+}
+
+// empty returns true if q contains no Nodes.
+func (q *objQueue) empty() bool {
+       return q.head == q.tail
+}
+
+// pushTail appends n to the tail of the queue.
+func (q *objQueue) pushTail(obj types.Object) {
+       if len(q.ring) == 0 {
+               q.ring = make([]types.Object, 16)
+       } else if q.head+len(q.ring) == q.tail {
+               // Grow the ring.
+               nring := make([]types.Object, len(q.ring)*2)
+               // Copy the old elements.
+               part := q.ring[q.head%len(q.ring):]
+               if q.tail-q.head <= len(part) {
+                       part = part[:q.tail-q.head]
+                       copy(nring, part)
+               } else {
+                       pos := copy(nring, part)
+                       copy(nring[pos:], q.ring[:q.tail%len(q.ring)])
+               }
+               q.ring, q.head, q.tail = nring, 0, q.tail-q.head
+       }
+
+       q.ring[q.tail%len(q.ring)] = obj
+       q.tail++
+}
+
+// popHead pops a node from the head of the queue. It panics if q is empty.
+func (q *objQueue) popHead() types.Object {
+       if q.empty() {
+               panic("dequeue empty")
+       }
+       obj := q.ring[q.head%len(q.ring)]
+       q.head++
+       return obj
+}