...
Run Format

Source file src/go/types/object.go

     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/constant"
    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; nil for methods and struct fields
    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		// scopePos returns the start position of the scope of this Object
    49		scopePos() token.Pos
    50	
    51		// setScopePos sets the start position of the scope for this Object.
    52		setScopePos(pos token.Pos)
    53	}
    54	
    55	// Id returns name if it is exported, otherwise it
    56	// returns the name qualified with the package path.
    57	func Id(pkg *Package, name string) string {
    58		if ast.IsExported(name) {
    59			return name
    60		}
    61		// unexported names need the package path for differentiation
    62		// (if there's no package, make sure we don't start with '.'
    63		// as that may change the order of methods between a setup
    64		// inside a package and outside a package - which breaks some
    65		// tests)
    66		path := "_"
    67		// TODO(gri): shouldn't !ast.IsExported(name) => pkg != nil be an precondition?
    68		// if pkg == nil {
    69		// 	panic("nil package in lookup of unexported name")
    70		// }
    71		if pkg != nil {
    72			path = pkg.path
    73			if path == "" {
    74				path = "_"
    75			}
    76		}
    77		return path + "." + name
    78	}
    79	
    80	// An object implements the common parts of an Object.
    81	type object struct {
    82		parent    *Scope
    83		pos       token.Pos
    84		pkg       *Package
    85		name      string
    86		typ       Type
    87		order_    uint32
    88		scopePos_ token.Pos
    89	}
    90	
    91	func (obj *object) Parent() *Scope      { return obj.parent }
    92	func (obj *object) Pos() token.Pos      { return obj.pos }
    93	func (obj *object) Pkg() *Package       { return obj.pkg }
    94	func (obj *object) Name() string        { return obj.name }
    95	func (obj *object) Type() Type          { return obj.typ }
    96	func (obj *object) Exported() bool      { return ast.IsExported(obj.name) }
    97	func (obj *object) Id() string          { return Id(obj.pkg, obj.name) }
    98	func (obj *object) String() string      { panic("abstract") }
    99	func (obj *object) order() uint32       { return obj.order_ }
   100	func (obj *object) scopePos() token.Pos { return obj.scopePos_ }
   101	
   102	func (obj *object) setParent(parent *Scope)   { obj.parent = parent }
   103	func (obj *object) setOrder(order uint32)     { assert(order > 0); obj.order_ = order }
   104	func (obj *object) setScopePos(pos token.Pos) { obj.scopePos_ = pos }
   105	
   106	func (obj *object) sameId(pkg *Package, name string) bool {
   107		// spec:
   108		// "Two identifiers are different if they are spelled differently,
   109		// or if they appear in different packages and are not exported.
   110		// Otherwise, they are the same."
   111		if name != obj.name {
   112			return false
   113		}
   114		// obj.Name == name
   115		if obj.Exported() {
   116			return true
   117		}
   118		// not exported, so packages must be the same (pkg == nil for
   119		// fields in Universe scope; this can only happen for types
   120		// introduced via Eval)
   121		if pkg == nil || obj.pkg == nil {
   122			return pkg == obj.pkg
   123		}
   124		// pkg != nil && obj.pkg != nil
   125		return pkg.path == obj.pkg.path
   126	}
   127	
   128	// A PkgName represents an imported Go package.
   129	type PkgName struct {
   130		object
   131		imported *Package
   132		used     bool // set if the package was used
   133	}
   134	
   135	func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
   136		return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, token.NoPos}, imported, false}
   137	}
   138	
   139	// Imported returns the package that was imported.
   140	// It is distinct from Pkg(), which is the package containing the import statement.
   141	func (obj *PkgName) Imported() *Package { return obj.imported }
   142	
   143	// A Const represents a declared constant.
   144	type Const struct {
   145		object
   146		val     constant.Value
   147		visited bool // for initialization cycle detection
   148	}
   149	
   150	func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const {
   151		return &Const{object{nil, pos, pkg, name, typ, 0, token.NoPos}, val, false}
   152	}
   153	
   154	func (obj *Const) Val() constant.Value { return obj.val }
   155	func (*Const) isDependency()           {} // a constant may be a dependency of an initialization expression
   156	
   157	// A TypeName represents a declared type.
   158	type TypeName struct {
   159		object
   160	}
   161	
   162	func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
   163		return &TypeName{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
   164	}
   165	
   166	// A Variable represents a declared variable (including function parameters and results, and struct fields).
   167	type Var struct {
   168		object
   169		anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
   170		visited   bool // for initialization cycle detection
   171		isField   bool // var is struct field
   172		used      bool // set if the variable was used
   173	}
   174	
   175	func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
   176		return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}}
   177	}
   178	
   179	func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
   180		return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, used: true} // parameters are always 'used'
   181	}
   182	
   183	func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
   184		return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, anonymous: anonymous, isField: true}
   185	}
   186	
   187	func (obj *Var) Anonymous() bool { return obj.anonymous }
   188	func (obj *Var) IsField() bool   { return obj.isField }
   189	func (*Var) isDependency()       {} // a variable may be a dependency of an initialization expression
   190	
   191	// A Func represents a declared function, concrete method, or abstract
   192	// (interface) method. Its Type() is always a *Signature.
   193	// An abstract method may belong to many interfaces due to embedding.
   194	type Func struct {
   195		object
   196	}
   197	
   198	func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
   199		// don't store a nil signature
   200		var typ Type
   201		if sig != nil {
   202			typ = sig
   203		}
   204		return &Func{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
   205	}
   206	
   207	// FullName returns the package- or receiver-type-qualified name of
   208	// function or method obj.
   209	func (obj *Func) FullName() string {
   210		var buf bytes.Buffer
   211		writeFuncName(&buf, obj, nil)
   212		return buf.String()
   213	}
   214	
   215	func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
   216	func (*Func) isDependency()     {} // a function may be a dependency of an initialization expression
   217	
   218	// An Alias represents a declared alias.
   219	type disabledAlias struct {
   220		object
   221		orig Object      // aliased constant, type, variable, or function; never an alias
   222		kind token.Token // token.CONST, token.TYPE, token.VAR, or token.FUNC (only needed during resolve phase)
   223	}
   224	
   225	func disabledNewAlias(pos token.Pos, pkg *Package, name string, orig Object) *disabledAlias {
   226		var typ Type = Typ[Invalid]
   227		if orig != nil {
   228			typ = orig.Type()
   229		}
   230		// No need to set a valid Alias.kind - that field is only used during identifier
   231		// resolution (1st type-checker pass). We could store the field outside but it's
   232		// easier to keep it here.
   233		return &disabledAlias{object{nil, pos, pkg, name, typ, 0, token.NoPos}, orig, token.ILLEGAL}
   234	}
   235	
   236	// Orig returns the aliased object, or nil if there was an error.
   237	// The returned object is never an Alias.
   238	func (obj *disabledAlias) disabledOrig() Object { return obj.orig }
   239	
   240	// A Label represents a declared label.
   241	type Label struct {
   242		object
   243		used bool // set if the label was used
   244	}
   245	
   246	func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
   247		return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid]}, false}
   248	}
   249	
   250	// A Builtin represents a built-in function.
   251	// Builtins don't have a valid type.
   252	type Builtin struct {
   253		object
   254		id builtinId
   255	}
   256	
   257	func newBuiltin(id builtinId) *Builtin {
   258		return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
   259	}
   260	
   261	// Nil represents the predeclared value nil.
   262	type Nil struct {
   263		object
   264	}
   265	
   266	func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
   267		typ := obj.Type()
   268		switch obj := obj.(type) {
   269		case *PkgName:
   270			fmt.Fprintf(buf, "package %s", obj.Name())
   271			if path := obj.imported.path; path != "" && path != obj.name {
   272				fmt.Fprintf(buf, " (%q)", path)
   273			}
   274			return
   275	
   276		case *Const:
   277			buf.WriteString("const")
   278	
   279		case *TypeName:
   280			buf.WriteString("type")
   281			typ = typ.Underlying()
   282	
   283		case *Var:
   284			if obj.isField {
   285				buf.WriteString("field")
   286			} else {
   287				buf.WriteString("var")
   288			}
   289	
   290		case *Func:
   291			buf.WriteString("func ")
   292			writeFuncName(buf, obj, qf)
   293			if typ != nil {
   294				WriteSignature(buf, typ.(*Signature), qf)
   295			}
   296			return
   297	
   298		// Alias-related code. Keep for now.
   299		// case *Alias:
   300		// 	buf.WriteString("alias")
   301	
   302		case *Label:
   303			buf.WriteString("label")
   304			typ = nil
   305	
   306		case *Builtin:
   307			buf.WriteString("builtin")
   308			typ = nil
   309	
   310		case *Nil:
   311			buf.WriteString("nil")
   312			return
   313	
   314		default:
   315			panic(fmt.Sprintf("writeObject(%T)", obj))
   316		}
   317	
   318		buf.WriteByte(' ')
   319	
   320		// For package-level objects, qualify the name.
   321		if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj {
   322			writePackage(buf, obj.Pkg(), qf)
   323		}
   324		buf.WriteString(obj.Name())
   325		if typ != nil {
   326			buf.WriteByte(' ')
   327			WriteType(buf, typ, qf)
   328		}
   329	}
   330	
   331	func writePackage(buf *bytes.Buffer, pkg *Package, qf Qualifier) {
   332		if pkg == nil {
   333			return
   334		}
   335		var s string
   336		if qf != nil {
   337			s = qf(pkg)
   338		} else {
   339			s = pkg.Path()
   340		}
   341		if s != "" {
   342			buf.WriteString(s)
   343			buf.WriteByte('.')
   344		}
   345	}
   346	
   347	// ObjectString returns the string form of obj.
   348	// The Qualifier controls the printing of
   349	// package-level objects, and may be nil.
   350	func ObjectString(obj Object, qf Qualifier) string {
   351		var buf bytes.Buffer
   352		writeObject(&buf, obj, qf)
   353		return buf.String()
   354	}
   355	
   356	func (obj *PkgName) String() string       { return ObjectString(obj, nil) }
   357	func (obj *Const) String() string         { return ObjectString(obj, nil) }
   358	func (obj *TypeName) String() string      { return ObjectString(obj, nil) }
   359	func (obj *Var) String() string           { return ObjectString(obj, nil) }
   360	func (obj *Func) String() string          { return ObjectString(obj, nil) }
   361	func (obj *disabledAlias) String() string { return ObjectString(obj, nil) }
   362	func (obj *Label) String() string         { return ObjectString(obj, nil) }
   363	func (obj *Builtin) String() string       { return ObjectString(obj, nil) }
   364	func (obj *Nil) String() string           { return ObjectString(obj, nil) }
   365	
   366	func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
   367		if f.typ != nil {
   368			sig := f.typ.(*Signature)
   369			if recv := sig.Recv(); recv != nil {
   370				buf.WriteByte('(')
   371				if _, ok := recv.Type().(*Interface); ok {
   372					// gcimporter creates abstract methods of
   373					// named interfaces using the interface type
   374					// (not the named type) as the receiver.
   375					// Don't print it in full.
   376					buf.WriteString("interface")
   377				} else {
   378					WriteType(buf, recv.Type(), qf)
   379				}
   380				buf.WriteByte(')')
   381				buf.WriteByte('.')
   382			} else if f.pkg != nil {
   383				writePackage(buf, f.pkg, qf)
   384			}
   385		}
   386		buf.WriteString(f.name)
   387	}
   388	

View as plain text