github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/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/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 }