...

Source file src/go/types/object.go

Documentation: go/types

		 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/constant"
		11  	"go/token"
		12  )
		13  
		14  // An Object describes a named language entity such as a package,
		15  // constant, type, variable, function (incl. methods), or label.
		16  // All objects implement the Object interface.
		17  //
		18  type Object interface {
		19  	Parent() *Scope // scope in which this object is declared; nil for methods and struct fields
		20  	Pos() token.Pos // position of object identifier in declaration
		21  	Pkg() *Package	// package to which this object belongs; nil for labels and objects in the Universe scope
		22  	Name() string	 // package local object name
		23  	Type() Type		 // object type
		24  	Exported() bool // reports whether the name starts with a capital letter
		25  	Id() string		 // object name if exported, qualified name if not exported (see func Id)
		26  
		27  	// String returns a human-readable string of the object.
		28  	String() string
		29  
		30  	// order reflects a package-level object's source order: if object
		31  	// a is before object b in the source, then a.order() < b.order().
		32  	// order returns a value > 0 for package-level objects; it returns
		33  	// 0 for all other objects (including objects in file scopes).
		34  	order() uint32
		35  
		36  	// color returns the object's color.
		37  	color() color
		38  
		39  	// setType sets the type of the object.
		40  	setType(Type)
		41  
		42  	// setOrder sets the order number of the object. It must be > 0.
		43  	setOrder(uint32)
		44  
		45  	// setColor sets the object's color. It must not be white.
		46  	setColor(color color)
		47  
		48  	// setParent sets the parent scope of the object.
		49  	setParent(*Scope)
		50  
		51  	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
		52  	sameId(pkg *Package, name string) bool
		53  
		54  	// scopePos returns the start position of the scope of this Object
		55  	scopePos() token.Pos
		56  
		57  	// setScopePos sets the start position of the scope for this Object.
		58  	setScopePos(pos token.Pos)
		59  }
		60  
		61  // Id returns name if it is exported, otherwise it
		62  // returns the name qualified with the package path.
		63  func Id(pkg *Package, name string) string {
		64  	if token.IsExported(name) {
		65  		return name
		66  	}
		67  	// unexported names need the package path for differentiation
		68  	// (if there's no package, make sure we don't start with '.'
		69  	// as that may change the order of methods between a setup
		70  	// inside a package and outside a package - which breaks some
		71  	// tests)
		72  	path := "_"
		73  	// pkg is nil for objects in Universe scope and possibly types
		74  	// introduced via Eval (see also comment in object.sameId)
		75  	if pkg != nil && pkg.path != "" {
		76  		path = pkg.path
		77  	}
		78  	return path + "." + name
		79  }
		80  
		81  // An object implements the common parts of an Object.
		82  type object struct {
		83  	parent		*Scope
		84  	pos			 token.Pos
		85  	pkg			 *Package
		86  	name			string
		87  	typ			 Type
		88  	order_		uint32
		89  	color_		color
		90  	scopePos_ token.Pos
		91  }
		92  
		93  // color encodes the color of an object (see Checker.objDecl for details).
		94  type color uint32
		95  
		96  // An object may be painted in one of three colors.
		97  // Color values other than white or black are considered grey.
		98  const (
		99  	white color = iota
	 100  	black
	 101  	grey // must be > white and black
	 102  )
	 103  
	 104  func (c color) String() string {
	 105  	switch c {
	 106  	case white:
	 107  		return "white"
	 108  	case black:
	 109  		return "black"
	 110  	default:
	 111  		return "grey"
	 112  	}
	 113  }
	 114  
	 115  // colorFor returns the (initial) color for an object depending on
	 116  // whether its type t is known or not.
	 117  func colorFor(t Type) color {
	 118  	if t != nil {
	 119  		return black
	 120  	}
	 121  	return white
	 122  }
	 123  
	 124  // Parent returns the scope in which the object is declared.
	 125  // The result is nil for methods and struct fields.
	 126  func (obj *object) Parent() *Scope { return obj.parent }
	 127  
	 128  // Pos returns the declaration position of the object's identifier.
	 129  func (obj *object) Pos() token.Pos { return obj.pos }
	 130  
	 131  // Pkg returns the package to which the object belongs.
	 132  // The result is nil for labels and objects in the Universe scope.
	 133  func (obj *object) Pkg() *Package { return obj.pkg }
	 134  
	 135  // Name returns the object's (package-local, unqualified) name.
	 136  func (obj *object) Name() string { return obj.name }
	 137  
	 138  // Type returns the object's type.
	 139  func (obj *object) Type() Type { return obj.typ }
	 140  
	 141  // Exported reports whether the object is exported (starts with a capital letter).
	 142  // It doesn't take into account whether the object is in a local (function) scope
	 143  // or not.
	 144  func (obj *object) Exported() bool { return token.IsExported(obj.name) }
	 145  
	 146  // Id is a wrapper for Id(obj.Pkg(), obj.Name()).
	 147  func (obj *object) Id() string { return Id(obj.pkg, obj.name) }
	 148  
	 149  func (obj *object) String() string			{ panic("abstract") }
	 150  func (obj *object) order() uint32			 { return obj.order_ }
	 151  func (obj *object) color() color				{ return obj.color_ }
	 152  func (obj *object) scopePos() token.Pos { return obj.scopePos_ }
	 153  
	 154  func (obj *object) setParent(parent *Scope)	 { obj.parent = parent }
	 155  func (obj *object) setType(typ Type)					{ obj.typ = typ }
	 156  func (obj *object) setOrder(order uint32)		 { assert(order > 0); obj.order_ = order }
	 157  func (obj *object) setColor(color color)			{ assert(color != white); obj.color_ = color }
	 158  func (obj *object) setScopePos(pos token.Pos) { obj.scopePos_ = pos }
	 159  
	 160  func (obj *object) sameId(pkg *Package, name string) bool {
	 161  	// spec:
	 162  	// "Two identifiers are different if they are spelled differently,
	 163  	// or if they appear in different packages and are not exported.
	 164  	// Otherwise, they are the same."
	 165  	if name != obj.name {
	 166  		return false
	 167  	}
	 168  	// obj.Name == name
	 169  	if obj.Exported() {
	 170  		return true
	 171  	}
	 172  	// not exported, so packages must be the same (pkg == nil for
	 173  	// fields in Universe scope; this can only happen for types
	 174  	// introduced via Eval)
	 175  	if pkg == nil || obj.pkg == nil {
	 176  		return pkg == obj.pkg
	 177  	}
	 178  	// pkg != nil && obj.pkg != nil
	 179  	return pkg.path == obj.pkg.path
	 180  }
	 181  
	 182  // A PkgName represents an imported Go package.
	 183  // PkgNames don't have a type.
	 184  type PkgName struct {
	 185  	object
	 186  	imported *Package
	 187  	used		 bool // set if the package was used
	 188  }
	 189  
	 190  // NewPkgName returns a new PkgName object representing an imported package.
	 191  // The remaining arguments set the attributes found with all Objects.
	 192  func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
	 193  	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, token.NoPos}, imported, false}
	 194  }
	 195  
	 196  // Imported returns the package that was imported.
	 197  // It is distinct from Pkg(), which is the package containing the import statement.
	 198  func (obj *PkgName) Imported() *Package { return obj.imported }
	 199  
	 200  // A Const represents a declared constant.
	 201  type Const struct {
	 202  	object
	 203  	val constant.Value
	 204  }
	 205  
	 206  // NewConst returns a new constant with value val.
	 207  // The remaining arguments set the attributes found with all Objects.
	 208  func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const {
	 209  	return &Const{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, val}
	 210  }
	 211  
	 212  // Val returns the constant's value.
	 213  func (obj *Const) Val() constant.Value { return obj.val }
	 214  
	 215  func (*Const) isDependency() {} // a constant may be a dependency of an initialization expression
	 216  
	 217  // A TypeName represents a name for a (defined or alias) type.
	 218  type TypeName struct {
	 219  	object
	 220  }
	 221  
	 222  // NewTypeName returns a new type name denoting the given typ.
	 223  // The remaining arguments set the attributes found with all Objects.
	 224  //
	 225  // The typ argument may be a defined (Named) type or an alias type.
	 226  // It may also be nil such that the returned TypeName can be used as
	 227  // argument for NewNamed, which will set the TypeName's type as a side-
	 228  // effect.
	 229  func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
	 230  	return &TypeName{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}}
	 231  }
	 232  
	 233  // IsAlias reports whether obj is an alias name for a type.
	 234  func (obj *TypeName) IsAlias() bool {
	 235  	switch t := obj.typ.(type) {
	 236  	case nil:
	 237  		return false
	 238  	case *Basic:
	 239  		// unsafe.Pointer is not an alias.
	 240  		if obj.pkg == Unsafe {
	 241  			return false
	 242  		}
	 243  		// Any user-defined type name for a basic type is an alias for a
	 244  		// basic type (because basic types are pre-declared in the Universe
	 245  		// scope, outside any package scope), and so is any type name with
	 246  		// a different name than the name of the basic type it refers to.
	 247  		// Additionally, we need to look for "byte" and "rune" because they
	 248  		// are aliases but have the same names (for better error messages).
	 249  		return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune
	 250  	case *Named:
	 251  		return obj != t.obj
	 252  	default:
	 253  		return true
	 254  	}
	 255  }
	 256  
	 257  // A Variable represents a declared variable (including function parameters and results, and struct fields).
	 258  type Var struct {
	 259  	object
	 260  	embedded bool // if set, the variable is an embedded struct field, and name is the type name
	 261  	isField	bool // var is struct field
	 262  	used		 bool // set if the variable was used
	 263  }
	 264  
	 265  // NewVar returns a new variable.
	 266  // The arguments set the attributes found with all Objects.
	 267  func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	 268  	return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}}
	 269  }
	 270  
	 271  // NewParam returns a new variable representing a function parameter.
	 272  func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
	 273  	return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, used: true} // parameters are always 'used'
	 274  }
	 275  
	 276  // NewField returns a new variable representing a struct field.
	 277  // For embedded fields, the name is the unqualified type name
	 278  /// under which the field is accessible.
	 279  func NewField(pos token.Pos, pkg *Package, name string, typ Type, embedded bool) *Var {
	 280  	return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, embedded: embedded, isField: true}
	 281  }
	 282  
	 283  // Anonymous reports whether the variable is an embedded field.
	 284  // Same as Embedded; only present for backward-compatibility.
	 285  func (obj *Var) Anonymous() bool { return obj.embedded }
	 286  
	 287  // Embedded reports whether the variable is an embedded field.
	 288  func (obj *Var) Embedded() bool { return obj.embedded }
	 289  
	 290  // IsField reports whether the variable is a struct field.
	 291  func (obj *Var) IsField() bool { return obj.isField }
	 292  
	 293  func (*Var) isDependency() {} // a variable may be a dependency of an initialization expression
	 294  
	 295  // A Func represents a declared function, concrete method, or abstract
	 296  // (interface) method. Its Type() is always a *Signature.
	 297  // An abstract method may belong to many interfaces due to embedding.
	 298  type Func struct {
	 299  	object
	 300  	hasPtrRecv bool // only valid for methods that don't have a type yet
	 301  }
	 302  
	 303  // NewFunc returns a new function with the given signature, representing
	 304  // the function's type.
	 305  func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
	 306  	// don't store a (typed) nil signature
	 307  	var typ Type
	 308  	if sig != nil {
	 309  		typ = sig
	 310  	}
	 311  	return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, false}
	 312  }
	 313  
	 314  // FullName returns the package- or receiver-type-qualified name of
	 315  // function or method obj.
	 316  func (obj *Func) FullName() string {
	 317  	var buf bytes.Buffer
	 318  	writeFuncName(&buf, obj, nil)
	 319  	return buf.String()
	 320  }
	 321  
	 322  // Scope returns the scope of the function's body block.
	 323  func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
	 324  
	 325  func (*Func) isDependency() {} // a function may be a dependency of an initialization expression
	 326  
	 327  // A Label represents a declared label.
	 328  // Labels don't have a type.
	 329  type Label struct {
	 330  	object
	 331  	used bool // set if the label was used
	 332  }
	 333  
	 334  // NewLabel returns a new label.
	 335  func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
	 336  	return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid], color_: black}, false}
	 337  }
	 338  
	 339  // A Builtin represents a built-in function.
	 340  // Builtins don't have a valid type.
	 341  type Builtin struct {
	 342  	object
	 343  	id builtinId
	 344  }
	 345  
	 346  func newBuiltin(id builtinId) *Builtin {
	 347  	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid], color_: black}, id}
	 348  }
	 349  
	 350  // Nil represents the predeclared value nil.
	 351  type Nil struct {
	 352  	object
	 353  }
	 354  
	 355  func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
	 356  	var tname *TypeName
	 357  	typ := obj.Type()
	 358  
	 359  	switch obj := obj.(type) {
	 360  	case *PkgName:
	 361  		fmt.Fprintf(buf, "package %s", obj.Name())
	 362  		if path := obj.imported.path; path != "" && path != obj.name {
	 363  			fmt.Fprintf(buf, " (%q)", path)
	 364  		}
	 365  		return
	 366  
	 367  	case *Const:
	 368  		buf.WriteString("const")
	 369  
	 370  	case *TypeName:
	 371  		tname = obj
	 372  		buf.WriteString("type")
	 373  
	 374  	case *Var:
	 375  		if obj.isField {
	 376  			buf.WriteString("field")
	 377  		} else {
	 378  			buf.WriteString("var")
	 379  		}
	 380  
	 381  	case *Func:
	 382  		buf.WriteString("func ")
	 383  		writeFuncName(buf, obj, qf)
	 384  		if typ != nil {
	 385  			WriteSignature(buf, typ.(*Signature), qf)
	 386  		}
	 387  		return
	 388  
	 389  	case *Label:
	 390  		buf.WriteString("label")
	 391  		typ = nil
	 392  
	 393  	case *Builtin:
	 394  		buf.WriteString("builtin")
	 395  		typ = nil
	 396  
	 397  	case *Nil:
	 398  		buf.WriteString("nil")
	 399  		return
	 400  
	 401  	default:
	 402  		panic(fmt.Sprintf("writeObject(%T)", obj))
	 403  	}
	 404  
	 405  	buf.WriteByte(' ')
	 406  
	 407  	// For package-level objects, qualify the name.
	 408  	if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj {
	 409  		writePackage(buf, obj.Pkg(), qf)
	 410  	}
	 411  	buf.WriteString(obj.Name())
	 412  
	 413  	if typ == nil {
	 414  		return
	 415  	}
	 416  
	 417  	if tname != nil {
	 418  		// We have a type object: Don't print anything more for
	 419  		// basic types since there's no more information (names
	 420  		// are the same; see also comment in TypeName.IsAlias).
	 421  		if _, ok := typ.(*Basic); ok {
	 422  			return
	 423  		}
	 424  		if tname.IsAlias() {
	 425  			buf.WriteString(" =")
	 426  		} else {
	 427  			typ = under(typ)
	 428  		}
	 429  	}
	 430  
	 431  	buf.WriteByte(' ')
	 432  	WriteType(buf, typ, qf)
	 433  }
	 434  
	 435  func writePackage(buf *bytes.Buffer, pkg *Package, qf Qualifier) {
	 436  	if pkg == nil {
	 437  		return
	 438  	}
	 439  	var s string
	 440  	if qf != nil {
	 441  		s = qf(pkg)
	 442  	} else {
	 443  		s = pkg.Path()
	 444  	}
	 445  	if s != "" {
	 446  		buf.WriteString(s)
	 447  		buf.WriteByte('.')
	 448  	}
	 449  }
	 450  
	 451  // ObjectString returns the string form of obj.
	 452  // The Qualifier controls the printing of
	 453  // package-level objects, and may be nil.
	 454  func ObjectString(obj Object, qf Qualifier) string {
	 455  	var buf bytes.Buffer
	 456  	writeObject(&buf, obj, qf)
	 457  	return buf.String()
	 458  }
	 459  
	 460  func (obj *PkgName) String() string	{ return ObjectString(obj, nil) }
	 461  func (obj *Const) String() string		{ return ObjectString(obj, nil) }
	 462  func (obj *TypeName) String() string { return ObjectString(obj, nil) }
	 463  func (obj *Var) String() string			{ return ObjectString(obj, nil) }
	 464  func (obj *Func) String() string		 { return ObjectString(obj, nil) }
	 465  func (obj *Label) String() string		{ return ObjectString(obj, nil) }
	 466  func (obj *Builtin) String() string	{ return ObjectString(obj, nil) }
	 467  func (obj *Nil) String() string			{ return ObjectString(obj, nil) }
	 468  
	 469  func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
	 470  	if f.typ != nil {
	 471  		sig := f.typ.(*Signature)
	 472  		if recv := sig.Recv(); recv != nil {
	 473  			buf.WriteByte('(')
	 474  			if _, ok := recv.Type().(*Interface); ok {
	 475  				// gcimporter creates abstract methods of
	 476  				// named interfaces using the interface type
	 477  				// (not the named type) as the receiver.
	 478  				// Don't print it in full.
	 479  				buf.WriteString("interface")
	 480  			} else {
	 481  				WriteType(buf, recv.Type(), qf)
	 482  			}
	 483  			buf.WriteByte(')')
	 484  			buf.WriteByte('.')
	 485  		} else if f.pkg != nil {
	 486  			writePackage(buf, f.pkg, qf)
	 487  		}
	 488  	}
	 489  	buf.WriteString(f.name)
	 490  }
	 491  

View as plain text