From ed5ac0e6f15914e9e55217bc43ba5279b6219f53 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 11 Jul 2013 12:57:56 -0700 Subject: [PATCH] go.tools/go/types: provide Object.String method R=adonovan CC=golang-dev https://golang.org/cl/11178043 --- go/types/errors.go | 8 +------- go/types/objects.go | 46 ++++++++++++++++++++++++++++++++++++++++----- go/types/scope.go | 7 ++----- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/go/types/errors.go b/go/types/errors.go index c11a3f82..d2befaa1 100644 --- a/go/types/errors.go +++ b/go/types/errors.go @@ -32,16 +32,10 @@ func (check *checker) formatMsg(format string, args []interface{}) string { args[i] = "" case operand: panic("internal error: should always pass *operand") - case *operand: - args[i] = a.String() case token.Pos: - args[i] = check.fset.Position(a).String() + args[i] = check.fset.Position(a) case ast.Expr: args[i] = exprString(a) - case Type: - args[i] = typeString(a) - case Object: - args[i] = fmt.Sprintf("%s (%T)", a.Name(), a) } } return fmt.Sprintf(format, args...) diff --git a/go/types/objects.go b/go/types/objects.go index 82a90404..cced70dc 100644 --- a/go/types/objects.go +++ b/go/types/objects.go @@ -5,6 +5,7 @@ package types import ( + "bytes" "go/ast" "go/token" @@ -19,15 +20,14 @@ import ( // All objects implement the Object interface. // type Object interface { - Parent() *Scope // the scope in which this object is declared + Parent() *Scope // scope in which this object is declared Pos() token.Pos // position of object identifier in declaration Pkg() *Package // nil for objects in the Universe scope and labels - Name() string // the package local object name - Type() Type // the object type + Name() string // package local object name + Type() Type // object type + String() string setParent(*Scope) - - // TODO(gri) provide String method! } // An object implements the common parts of an Object. @@ -45,6 +45,31 @@ func (obj *object) Pkg() *Package { return obj.pkg } func (obj *object) Name() string { return obj.name } func (obj *object) Type() Type { return obj.typ } +func (obj *object) toString(kind string) string { + var buf bytes.Buffer + + buf.WriteString(kind) + buf.WriteByte(' ') + + // qualified name + if obj.pkg != nil { + buf.WriteString(obj.pkg.name) + buf.WriteByte('.') + } + buf.WriteString(obj.name) + + // type + if t := obj.typ; t == nil { + buf.WriteString("") + } else if u := t.Underlying(); u == nil { + buf.WriteString("") + } else { + buf.WriteString(u.String()) + } + + return buf.String() +} + func (obj *object) setParent(parent *Scope) { obj.parent = parent } // A Package represents the contents (objects) of a Go package. @@ -62,6 +87,7 @@ func NewPackage(pos token.Pos, path, name string, scope *Scope, imports map[stri return obj } +func (obj *Package) String() string { return obj.toString("package") } func (obj *Package) Path() string { return obj.path } func (obj *Package) Scope() *Scope { return obj.scope } func (obj *Package) Imports() map[string]*Package { return obj.imports } @@ -79,6 +105,7 @@ func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val exact.Valu return &Const{object{nil, pos, pkg, name, typ}, val, false} } +func (obj *Const) String() string { return obj.toString("const") } func (obj *Const) Val() exact.Value { return obj.val } // A TypeName represents a declared type. @@ -90,6 +117,8 @@ func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName { return &TypeName{object{nil, pos, pkg, name, typ}} } +func (obj *TypeName) String() string { return obj.toString("type") } + // A Variable represents a declared variable (including function parameters and results). type Var struct { object @@ -101,6 +130,8 @@ func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var { return &Var{object{nil, pos, pkg, name, typ}, false} } +func (obj *Var) String() string { return obj.toString("var") } + // A Field represents a struct field. type Field struct { object @@ -111,6 +142,7 @@ func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool return &Field{object{nil, pos, pkg, name, typ}, anonymous} } +func (obj *Field) String() string { return obj.toString("field") } func (obj *Field) Anonymous() bool { return obj.anonymous } func (f *Field) isMatch(pkg *Package, name string) bool { @@ -136,6 +168,8 @@ func NewFunc(pos token.Pos, pkg *Package, name string, typ Type) *Func { return &Func{object{nil, pos, pkg, name, typ}, nil} } +func (obj *Func) String() string { return obj.toString("func") } + // A Label represents a declared label. type Label struct { object @@ -144,3 +178,5 @@ type Label struct { func NewLabel(pos token.Pos, name string) *Label { return &Label{object{nil, pos, nil, name, nil}} } + +func (obj *Label) String() string { return obj.toString("label") } diff --git a/go/types/scope.go b/go/types/scope.go index 7922bc85..604c2d45 100644 --- a/go/types/scope.go +++ b/go/types/scope.go @@ -134,15 +134,12 @@ func (s *Scope) Insert(obj Object) Object { // String returns a string representation of the scope, for debugging. func (s *Scope) String() string { - if s == nil { - return "scope {}" - } var buf bytes.Buffer fmt.Fprintf(&buf, "scope %p {", s) - if s != nil && len(s.entries) > 0 { + if s.NumEntries() > 0 { fmt.Fprintln(&buf) for _, obj := range s.entries { - fmt.Fprintf(&buf, "\t%s\t%T\n", obj.Name(), obj) + fmt.Fprintf(&buf, "\t%s\n", obj) } } fmt.Fprintf(&buf, "}\n")