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