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 }