1
0
mirror of https://github.com/golang/go synced 2024-09-30 18:18:32 -06:00
go/cmd/godex/writetype.go
Robert Griesemer adaaa07486 x/tools: delete x/tools/go/types and dependent packages/client files
Per https://groups.google.com/forum/#!topic/golang-announce/qu_rAphYdxY
this change deletes the packages

  go/exact
  go/gccgoimporter
  go/gcimporter
  go/importer
  go/types
  cmd/vet

from the x/tools repo and any files depending on those packages
building against Go 1.4.

x/tools packages depending on any of these libraries must use the
respective versions from the std lib or use vendored versions if
building against 1.4.

Remaining packages may or may not build against Go 1.4 anymore
and will not be supported against 1.4.

Change-Id: I1c655fc30aee49b6c7326ebd4eb1bb0836ac97e0
Reviewed-on: https://go-review.googlesource.com/20810
Reviewed-by: Alan Donovan <adonovan@google.com>
2016-04-06 21:52:49 +00:00

245 lines
5.7 KiB
Go

// Copyright 2014 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.
// +build go1.5
// This file implements writing of types. The functionality is lifted
// directly from go/types, but now contains various modifications for
// nicer output.
//
// TODO(gri) back-port once we have a fixed interface and once the
// go/types API is not frozen anymore for the 1.3 release; and remove
// this implementation if possible.
package main
import "go/types"
func (p *printer) writeType(this *types.Package, typ types.Type) {
p.writeTypeInternal(this, typ, make([]types.Type, 8))
}
// From go/types - leave for now to ease back-porting this code.
const GcCompatibilityMode = false
func (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited []types.Type) {
// Theoretically, this is a quadratic lookup algorithm, but in
// practice deeply nested composite types with unnamed component
// types are uncommon. This code is likely more efficient than
// using a map.
for _, t := range visited {
if t == typ {
p.printf("○%T", typ) // cycle to typ
return
}
}
visited = append(visited, typ)
switch t := typ.(type) {
case nil:
p.print("<nil>")
case *types.Basic:
if t.Kind() == types.UnsafePointer {
p.print("unsafe.")
}
if GcCompatibilityMode {
// forget the alias names
switch t.Kind() {
case types.Byte:
t = types.Typ[types.Uint8]
case types.Rune:
t = types.Typ[types.Int32]
}
}
p.print(t.Name())
case *types.Array:
p.printf("[%d]", t.Len())
p.writeTypeInternal(this, t.Elem(), visited)
case *types.Slice:
p.print("[]")
p.writeTypeInternal(this, t.Elem(), visited)
case *types.Struct:
n := t.NumFields()
if n == 0 {
p.print("struct{}")
return
}
p.print("struct {\n")
p.indent++
for i := 0; i < n; i++ {
f := t.Field(i)
if !f.Anonymous() {
p.printf("%s ", f.Name())
}
p.writeTypeInternal(this, f.Type(), visited)
if tag := t.Tag(i); tag != "" {
p.printf(" %q", tag)
}
p.print("\n")
}
p.indent--
p.print("}")
case *types.Pointer:
p.print("*")
p.writeTypeInternal(this, t.Elem(), visited)
case *types.Tuple:
p.writeTuple(this, t, false, visited)
case *types.Signature:
p.print("func")
p.writeSignatureInternal(this, t, visited)
case *types.Interface:
// We write the source-level methods and embedded types rather
// than the actual method set since resolved method signatures
// may have non-printable cycles if parameters have anonymous
// interface types that (directly or indirectly) embed the
// current interface. For instance, consider the result type
// of m:
//
// type T interface{
// m() interface{ T }
// }
//
n := t.NumMethods()
if n == 0 {
p.print("interface{}")
return
}
p.print("interface {\n")
p.indent++
if GcCompatibilityMode {
// print flattened interface
// (useful to compare against gc-generated interfaces)
for i := 0; i < n; i++ {
m := t.Method(i)
p.print(m.Name())
p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
p.print("\n")
}
} else {
// print explicit interface methods and embedded types
for i, n := 0, t.NumExplicitMethods(); i < n; i++ {
m := t.ExplicitMethod(i)
p.print(m.Name())
p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
p.print("\n")
}
for i, n := 0, t.NumEmbeddeds(); i < n; i++ {
typ := t.Embedded(i)
p.writeTypeInternal(this, typ, visited)
p.print("\n")
}
}
p.indent--
p.print("}")
case *types.Map:
p.print("map[")
p.writeTypeInternal(this, t.Key(), visited)
p.print("]")
p.writeTypeInternal(this, t.Elem(), visited)
case *types.Chan:
var s string
var parens bool
switch t.Dir() {
case types.SendRecv:
s = "chan "
// chan (<-chan T) requires parentheses
if c, _ := t.Elem().(*types.Chan); c != nil && c.Dir() == types.RecvOnly {
parens = true
}
case types.SendOnly:
s = "chan<- "
case types.RecvOnly:
s = "<-chan "
default:
panic("unreachable")
}
p.print(s)
if parens {
p.print("(")
}
p.writeTypeInternal(this, t.Elem(), visited)
if parens {
p.print(")")
}
case *types.Named:
s := "<Named w/o object>"
if obj := t.Obj(); obj != nil {
if pkg := obj.Pkg(); pkg != nil {
if pkg != this {
p.print(pkg.Path())
p.print(".")
}
// TODO(gri): function-local named types should be displayed
// differently from named types at package level to avoid
// ambiguity.
}
s = obj.Name()
}
p.print(s)
default:
// For externally defined implementations of Type.
p.print(t.String())
}
}
func (p *printer) writeTuple(this *types.Package, tup *types.Tuple, variadic bool, visited []types.Type) {
p.print("(")
for i, n := 0, tup.Len(); i < n; i++ {
if i > 0 {
p.print(", ")
}
v := tup.At(i)
if name := v.Name(); name != "" {
p.print(name)
p.print(" ")
}
typ := v.Type()
if variadic && i == n-1 {
p.print("...")
typ = typ.(*types.Slice).Elem()
}
p.writeTypeInternal(this, typ, visited)
}
p.print(")")
}
func (p *printer) writeSignature(this *types.Package, sig *types.Signature) {
p.writeSignatureInternal(this, sig, make([]types.Type, 8))
}
func (p *printer) writeSignatureInternal(this *types.Package, sig *types.Signature, visited []types.Type) {
p.writeTuple(this, sig.Params(), sig.Variadic(), visited)
res := sig.Results()
n := res.Len()
if n == 0 {
// no result
return
}
p.print(" ")
if n == 1 && res.At(0).Name() == "" {
// single unnamed result
p.writeTypeInternal(this, res.At(0).Type(), visited)
return
}
// multiple or named result(s)
p.writeTuple(this, res, false, visited)
}