github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/go/types/object.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package types
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"go/ast"
    11  	"go/exact"
    12  	"go/token"
    13  )
    14  
    15  // TODO(gri) Document factory, accessor methods, and fields. General clean-up.
    16  
    17  // An Object describes a named language entity such as a package,
    18  // constant, type, variable, function (incl. methods), or label.
    19  // All objects implement the Object interface.
    20  //
    21  type Object interface {
    22  	Parent() *Scope // scope in which this object is declared
    23  	Pos() token.Pos // position of object identifier in declaration
    24  	Pkg() *Package  // nil for objects in the Universe scope and labels
    25  	Name() string   // package local object name
    26  	Type() Type     // object type
    27  	Exported() bool // reports whether the name starts with a capital letter
    28  	Id() string     // object id (see Id below)
    29  
    30  	// String returns a human-readable string of the object.
    31  	String() string
    32  
    33  	// order reflects a package-level object's source order: if object
    34  	// a is before object b in the source, then a.order() < b.order().
    35  	// order returns a value > 0 for package-level objects; it returns
    36  	// 0 for all other objects (including objects in file scopes).
    37  	order() uint32
    38  
    39  	// setOrder sets the order number of the object. It must be > 0.
    40  	setOrder(uint32)
    41  
    42  	// setParent sets the parent scope of the object.
    43  	setParent(*Scope)
    44  
    45  	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
    46  	sameId(pkg *Package, name string) bool
    47  }
    48  
    49  // Id returns name if it is exported, otherwise it
    50  // returns the name qualified with the package path.
    51  func Id(pkg *Package, name string) string {
    52  	if ast.IsExported(name) {
    53  		return name
    54  	}
    55  	// unexported names need the package path for differentiation
    56  	// (if there's no package, make sure we don't start with '.'
    57  	// as that may change the order of methods between a setup
    58  	// inside a package and outside a package - which breaks some
    59  	// tests)
    60  	path := "_"
    61  	// TODO(gri): shouldn't !ast.IsExported(name) => pkg != nil be an precondition?
    62  	// if pkg == nil {
    63  	// 	panic("nil package in lookup of unexported name")
    64  	// }
    65  	if pkg != nil {
    66  		path = pkg.path
    67  		if path == "" {
    68  			path = "_"
    69  		}
    70  	}
    71  	return path + "." + name
    72  }
    73  
    74  // An object implements the common parts of an Object.
    75  type object struct {
    76  	parent *Scope
    77  	pos    token.Pos
    78  	pkg    *Package
    79  	name   string
    80  	typ    Type
    81  	order_ uint32
    82  }
    83  
    84  func (obj *object) Parent() *Scope { return obj.parent }
    85  func (obj *object) Pos() token.Pos { return obj.pos }
    86  func (obj *object) Pkg() *Package  { return obj.pkg }
    87  func (obj *object) Name() string   { return obj.name }
    88  func (obj *object) Type() Type     { return obj.typ }
    89  func (obj *object) Exported() bool { return ast.IsExported(obj.name) }
    90  func (obj *object) Id() string     { return Id(obj.pkg, obj.name) }
    91  func (obj *object) String() string { panic("abstract") }
    92  func (obj *object) order() uint32  { return obj.order_ }
    93  
    94  func (obj *object) setOrder(order uint32)   { assert(order > 0); obj.order_ = order }
    95  func (obj *object) setParent(parent *Scope) { obj.parent = parent }
    96  
    97  func (obj *object) sameId(pkg *Package, name string) bool {
    98  	// spec:
    99  	// "Two identifiers are different if they are spelled differently,
   100  	// or if they appear in different packages and are not exported.
   101  	// Otherwise, they are the same."
   102  	if name != obj.name {
   103  		return false
   104  	}
   105  	// obj.Name == name
   106  	if obj.Exported() {
   107  		return true
   108  	}
   109  	// not exported, so packages must be the same (pkg == nil for
   110  	// fields in Universe scope; this can only happen for types
   111  	// introduced via Eval)
   112  	if pkg == nil || obj.pkg == nil {
   113  		return pkg == obj.pkg
   114  	}
   115  	// pkg != nil && obj.pkg != nil
   116  	return pkg.path == obj.pkg.path
   117  }
   118  
   119  // A PkgName represents an imported Go package.
   120  type PkgName struct {
   121  	object
   122  	imported *Package
   123  	used     bool // set if the package was used
   124  }
   125  
   126  func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
   127  	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0}, imported, false}
   128  }
   129  
   130  // Imported returns the package that was imported.
   131  // It is distinct from Pkg(), which is the package containing the import statement.
   132  func (obj *PkgName) Imported() *Package { return obj.imported }
   133  
   134  // A Const represents a declared constant.
   135  type Const struct {
   136  	object
   137  	val     exact.Value
   138  	visited bool // for initialization cycle detection
   139  }
   140  
   141  func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val exact.Value) *Const {
   142  	return &Const{object{nil, pos, pkg, name, typ, 0}, val, false}
   143  }
   144  
   145  func (obj *Const) Val() exact.Value { return obj.val }
   146  
   147  // A TypeName represents a declared type.
   148  type TypeName struct {
   149  	object
   150  }
   151  
   152  func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
   153  	return &TypeName{object{nil, pos, pkg, name, typ, 0}}
   154  }
   155  
   156  // A Variable represents a declared variable (including function parameters and results, and struct fields).
   157  type Var struct {
   158  	object
   159  	anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
   160  	visited   bool // for initialization cycle detection
   161  	isField   bool // var is struct field
   162  	used      bool // set if the variable was used
   163  }
   164  
   165  func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
   166  	return &Var{object: object{nil, pos, pkg, name, typ, 0}}
   167  }
   168  
   169  func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
   170  	return &Var{object: object{nil, pos, pkg, name, typ, 0}, used: true} // parameters are always 'used'
   171  }
   172  
   173  func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
   174  	return &Var{object: object{nil, pos, pkg, name, typ, 0}, anonymous: anonymous, isField: true}
   175  }
   176  
   177  func (obj *Var) Anonymous() bool { return obj.anonymous }
   178  
   179  func (obj *Var) IsField() bool { return obj.isField }
   180  
   181  // A Func represents a declared function, concrete method, or abstract
   182  // (interface) method.  Its Type() is always a *Signature.
   183  // An abstract method may belong to many interfaces due to embedding.
   184  type Func struct {
   185  	object
   186  }
   187  
   188  func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
   189  	// don't store a nil signature
   190  	var typ Type
   191  	if sig != nil {
   192  		typ = sig
   193  	}
   194  	return &Func{object{nil, pos, pkg, name, typ, 0}}
   195  }
   196  
   197  // FullName returns the package- or receiver-type-qualified name of
   198  // function or method obj.
   199  func (obj *Func) FullName() string {
   200  	var buf bytes.Buffer
   201  	writeFuncName(&buf, nil, obj)
   202  	return buf.String()
   203  }
   204  
   205  func (obj *Func) Scope() *Scope {
   206  	return obj.typ.(*Signature).scope
   207  }
   208  
   209  // A Label represents a declared label.
   210  type Label struct {
   211  	object
   212  	used bool // set if the label was used
   213  }
   214  
   215  func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
   216  	return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid]}, false}
   217  }
   218  
   219  // A Builtin represents a built-in function.
   220  // Builtins don't have a valid type.
   221  type Builtin struct {
   222  	object
   223  	id builtinId
   224  }
   225  
   226  func newBuiltin(id builtinId) *Builtin {
   227  	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
   228  }
   229  
   230  // Nil represents the predeclared value nil.
   231  type Nil struct {
   232  	object
   233  }
   234  
   235  func writeObject(buf *bytes.Buffer, this *Package, obj Object) {
   236  	typ := obj.Type()
   237  	switch obj := obj.(type) {
   238  	case *PkgName:
   239  		fmt.Fprintf(buf, "package %s", obj.Name())
   240  		if path := obj.imported.path; path != "" && path != obj.name {
   241  			fmt.Fprintf(buf, " (%q)", path)
   242  		}
   243  		return
   244  
   245  	case *Const:
   246  		buf.WriteString("const")
   247  
   248  	case *TypeName:
   249  		buf.WriteString("type")
   250  		typ = typ.Underlying()
   251  
   252  	case *Var:
   253  		if obj.isField {
   254  			buf.WriteString("field")
   255  		} else {
   256  			buf.WriteString("var")
   257  		}
   258  
   259  	case *Func:
   260  		buf.WriteString("func ")
   261  		writeFuncName(buf, this, obj)
   262  		if typ != nil {
   263  			WriteSignature(buf, this, typ.(*Signature))
   264  		}
   265  		return
   266  
   267  	case *Label:
   268  		buf.WriteString("label")
   269  		typ = nil
   270  
   271  	case *Builtin:
   272  		buf.WriteString("builtin")
   273  		typ = nil
   274  
   275  	case *Nil:
   276  		buf.WriteString("nil")
   277  		return
   278  
   279  	default:
   280  		panic(fmt.Sprintf("writeObject(%T)", obj))
   281  	}
   282  
   283  	buf.WriteByte(' ')
   284  
   285  	// For package-level objects, package-qualify the name,
   286  	// except for intra-package references (this != nil).
   287  	if pkg := obj.Pkg(); pkg != nil && this != pkg && pkg.scope.Lookup(obj.Name()) == obj {
   288  		buf.WriteString(pkg.path)
   289  		buf.WriteByte('.')
   290  	}
   291  	buf.WriteString(obj.Name())
   292  	if typ != nil {
   293  		buf.WriteByte(' ')
   294  		WriteType(buf, this, typ)
   295  	}
   296  }
   297  
   298  // ObjectString returns the string form of obj.
   299  // Object and type names are printed package-qualified
   300  // only if they do not belong to this package.
   301  //
   302  func ObjectString(this *Package, obj Object) string {
   303  	var buf bytes.Buffer
   304  	writeObject(&buf, this, obj)
   305  	return buf.String()
   306  }
   307  
   308  func (obj *PkgName) String() string  { return ObjectString(nil, obj) }
   309  func (obj *Const) String() string    { return ObjectString(nil, obj) }
   310  func (obj *TypeName) String() string { return ObjectString(nil, obj) }
   311  func (obj *Var) String() string      { return ObjectString(nil, obj) }
   312  func (obj *Func) String() string     { return ObjectString(nil, obj) }
   313  func (obj *Label) String() string    { return ObjectString(nil, obj) }
   314  func (obj *Builtin) String() string  { return ObjectString(nil, obj) }
   315  func (obj *Nil) String() string      { return ObjectString(nil, obj) }
   316  
   317  func writeFuncName(buf *bytes.Buffer, this *Package, f *Func) {
   318  	if f.typ != nil {
   319  		sig := f.typ.(*Signature)
   320  		if recv := sig.Recv(); recv != nil {
   321  			buf.WriteByte('(')
   322  			if _, ok := recv.Type().(*Interface); ok {
   323  				// gcimporter creates abstract methods of
   324  				// named interfaces using the interface type
   325  				// (not the named type) as the receiver.
   326  				// Don't print it in full.
   327  				buf.WriteString("interface")
   328  			} else {
   329  				WriteType(buf, this, recv.Type())
   330  			}
   331  			buf.WriteByte(')')
   332  			buf.WriteByte('.')
   333  		} else if f.pkg != nil && f.pkg != this {
   334  			buf.WriteString(f.pkg.path)
   335  			buf.WriteByte('.')
   336  		}
   337  	}
   338  	buf.WriteString(f.name)
   339  }