1
0
mirror of https://github.com/golang/go synced 2024-11-22 09:34:54 -07:00

exp/types: Replace String method with TypeString function

This is more in sync with the rest of the package;
for instance, we have functions (not methods) to
deref or find the underlying type of a Type.

In the process use a single bytes.Buffer to create
the string representation for a type rather than
the (occasional) string concatenation.

R=r
CC=golang-dev
https://golang.org/cl/6458057
This commit is contained in:
Robert Griesemer 2012-07-31 19:30:18 -07:00
parent dcb6f59811
commit 152279f203
2 changed files with 107 additions and 104 deletions

View File

@ -17,7 +17,6 @@ import (
// All types implement the Type interface.
type Type interface {
isType()
String() string
}
// All concrete types embed implementsType which
@ -32,21 +31,12 @@ type Bad struct {
Msg string // for better error reporting/debugging
}
func (t *Bad) String() string {
return fmt.Sprintf("badType(%s)", t.Msg)
}
// A Basic represents a (unnamed) basic type.
type Basic struct {
implementsType
// TODO(gri) need a field specifying the exact basic type
}
func (t *Basic) String() string {
// TODO(gri) print actual type information
return "basicType"
}
// An Array represents an array type [Len]Elt.
type Array struct {
implementsType
@ -54,20 +44,12 @@ type Array struct {
Elt Type
}
func (t *Array) String() string {
return fmt.Sprintf("[%d]%s", t.Len, t.Elt)
}
// A Slice represents a slice type []Elt.
type Slice struct {
implementsType
Elt Type
}
func (t *Slice) String() string {
return "[]" + t.Elt.String()
}
// A Struct represents a struct type struct{...}.
// Anonymous fields are represented by objects with empty names.
type Struct struct {
@ -80,35 +62,12 @@ type Struct struct {
// - there is no scope for fast lookup (but the parser creates one)
}
func (t *Struct) String() string {
buf := bytes.NewBufferString("struct{")
for i, fld := range t.Fields {
if i > 0 {
buf.WriteString("; ")
}
if fld.Name != "" {
buf.WriteString(fld.Name)
buf.WriteByte(' ')
}
buf.WriteString(fld.Type.(Type).String())
if i < len(t.Tags) && t.Tags[i] != "" {
fmt.Fprintf(buf, " %q", t.Tags[i])
}
}
buf.WriteByte('}')
return buf.String()
}
// A Pointer represents a pointer type *Base.
type Pointer struct {
implementsType
Base Type
}
func (t *Pointer) String() string {
return "*" + t.Base.String()
}
// A Func represents a function type func(...) (...).
// Unnamed parameters are represented by objects with empty names.
type Func struct {
@ -119,6 +78,33 @@ type Func struct {
IsVariadic bool // true if the last parameter's type is of the form ...T
}
// An Interface represents an interface type interface{...}.
type Interface struct {
implementsType
Methods ObjList // interface methods sorted by name; or nil
}
// A Map represents a map type map[Key]Elt.
type Map struct {
implementsType
Key, Elt Type
}
// A Chan represents a channel type chan Elt, <-chan Elt, or chan<-Elt.
type Chan struct {
implementsType
Dir ast.ChanDir
Elt Type
}
// A Name represents a named type as declared in a type declaration.
type Name struct {
implementsType
Underlying Type // nil if not fully declared
Obj *ast.Object // corresponding declared object
// TODO(gri) need to remember fields and methods.
}
func writeParams(buf *bytes.Buffer, params ObjList, isVariadic bool) {
buf.WriteByte('(')
for i, par := range params {
@ -132,7 +118,7 @@ func writeParams(buf *bytes.Buffer, params ObjList, isVariadic bool) {
if isVariadic && i == len(params)-1 {
buf.WriteString("...")
}
buf.WriteString(par.Type.(Type).String())
writeType(buf, par.Type.(Type))
}
buf.WriteByte(')')
}
@ -147,7 +133,7 @@ func writeSignature(buf *bytes.Buffer, t *Func) {
buf.WriteByte(' ')
if len(t.Results) == 1 && t.Results[0].Name == "" {
// single unnamed result
buf.WriteString(t.Results[0].Type.(Type).String())
writeType(buf, t.Results[0].Type.(Type))
return
}
@ -155,20 +141,49 @@ func writeSignature(buf *bytes.Buffer, t *Func) {
writeParams(buf, t.Results, false)
}
func (t *Func) String() string {
buf := bytes.NewBufferString("func")
func writeType(buf *bytes.Buffer, typ Type) {
switch t := typ.(type) {
case *Bad:
fmt.Fprintf(buf, "badType(%s)", t.Msg)
case *Basic:
buf.WriteString("basicType") // TODO(gri) print actual type information
case *Array:
fmt.Fprintf(buf, "[%d]", t.Len)
writeType(buf, t.Elt)
case *Slice:
buf.WriteString("[]")
writeType(buf, t.Elt)
case *Struct:
buf.WriteString("struct{")
for i, fld := range t.Fields {
if i > 0 {
buf.WriteString("; ")
}
if fld.Name != "" {
buf.WriteString(fld.Name)
buf.WriteByte(' ')
}
writeType(buf, fld.Type.(Type))
if i < len(t.Tags) && t.Tags[i] != "" {
fmt.Fprintf(buf, " %q", t.Tags[i])
}
}
buf.WriteByte('}')
case *Pointer:
buf.WriteByte('*')
writeType(buf, t.Base)
case *Func:
buf.WriteString("func")
writeSignature(buf, t)
return buf.String()
}
// An Interface represents an interface type interface{...}.
type Interface struct {
implementsType
Methods ObjList // interface methods sorted by name; or nil
}
func (t *Interface) String() string {
buf := bytes.NewBufferString("interface{")
case *Interface:
buf.WriteString("interface{")
for i, m := range t.Methods {
if i > 0 {
buf.WriteString("; ")
@ -177,27 +192,14 @@ func (t *Interface) String() string {
writeSignature(buf, m.Type.(*Func))
}
buf.WriteByte('}')
return buf.String()
}
// A Map represents a map type map[Key]Elt.
type Map struct {
implementsType
Key, Elt Type
}
case *Map:
buf.WriteString("map[")
writeType(buf, t.Key)
buf.WriteByte(']')
writeType(buf, t.Elt)
func (t *Map) String() string {
return fmt.Sprintf("map[%s]%s", t.Key, t.Elt)
}
// A Chan represents a channel type chan Elt, <-chan Elt, or chan<-Elt.
type Chan struct {
implementsType
Dir ast.ChanDir
Elt Type
}
func (t *Chan) String() string {
case *Chan:
var s string
switch t.Dir {
case ast.SEND:
@ -207,19 +209,20 @@ func (t *Chan) String() string {
default:
s = "chan "
}
return s + t.Elt.String()
buf.WriteString(s)
writeType(buf, t.Elt)
case *Name:
buf.WriteString(t.Obj.Name)
}
}
// A Name represents a named type as declared in a type declaration.
type Name struct {
implementsType
Underlying Type // nil if not fully declared
Obj *ast.Object // corresponding declared object
// TODO(gri) need to remember fields and methods.
}
func (t *Name) String() string {
return t.Obj.Name
// TypeString returns a string representation for typ.
func TypeString(typ Type) string {
var buf bytes.Buffer
writeType(&buf, typ)
return buf.String()
}
// If typ is a pointer type, Deref returns the pointer's base type;

View File

@ -120,7 +120,7 @@ func TestTypes(t *testing.T) {
continue
}
typ := Underlying(pkg.Scope.Lookup("T").Type.(Type))
str := typ.String()
str := TypeString(typ)
if str != test.str {
t.Errorf("%s: got %s, want %s", test.src, str, test.str)
}