Source file
src/go/types/object.go
1
2
3
4
5 package types
6
7 import (
8 "bytes"
9 "fmt"
10 "go/constant"
11 "go/token"
12 )
13
14
15
16
17 type Object interface {
18 Parent() *Scope
19 Pos() token.Pos
20 Pkg() *Package
21 Name() string
22 Type() Type
23 Exported() bool
24 Id() string
25
26
27 String() string
28
29
30
31
32
33 order() uint32
34
35
36 color() color
37
38
39 setType(Type)
40
41
42 setOrder(uint32)
43
44
45 setColor(color color)
46
47
48 setParent(*Scope)
49
50
51 sameId(pkg *Package, name string) bool
52
53
54 scopePos() token.Pos
55
56
57 setScopePos(pos token.Pos)
58 }
59
60
61
62 func Id(pkg *Package, name string) string {
63 if token.IsExported(name) {
64 return name
65 }
66
67
68
69
70
71 path := "_"
72
73
74 if pkg != nil && pkg.path != "" {
75 path = pkg.path
76 }
77 return path + "." + name
78 }
79
80
81 type object struct {
82 parent *Scope
83 pos token.Pos
84 pkg *Package
85 name string
86 typ Type
87 order_ uint32
88 color_ color
89 scopePos_ token.Pos
90 }
91
92
93 type color uint32
94
95
96
97 const (
98 white color = iota
99 black
100 grey
101 )
102
103 func (c color) String() string {
104 switch c {
105 case white:
106 return "white"
107 case black:
108 return "black"
109 default:
110 return "grey"
111 }
112 }
113
114
115
116 func colorFor(t Type) color {
117 if t != nil {
118 return black
119 }
120 return white
121 }
122
123
124
125 func (obj *object) Parent() *Scope { return obj.parent }
126
127
128 func (obj *object) Pos() token.Pos { return obj.pos }
129
130
131
132 func (obj *object) Pkg() *Package { return obj.pkg }
133
134
135 func (obj *object) Name() string { return obj.name }
136
137
138 func (obj *object) Type() Type { return obj.typ }
139
140
141
142
143 func (obj *object) Exported() bool { return token.IsExported(obj.name) }
144
145
146 func (obj *object) Id() string { return Id(obj.pkg, obj.name) }
147
148 func (obj *object) String() string { panic("abstract") }
149 func (obj *object) order() uint32 { return obj.order_ }
150 func (obj *object) color() color { return obj.color_ }
151 func (obj *object) scopePos() token.Pos { return obj.scopePos_ }
152
153 func (obj *object) setParent(parent *Scope) { obj.parent = parent }
154 func (obj *object) setType(typ Type) { obj.typ = typ }
155 func (obj *object) setOrder(order uint32) { assert(order > 0); obj.order_ = order }
156 func (obj *object) setColor(color color) { assert(color != white); obj.color_ = color }
157 func (obj *object) setScopePos(pos token.Pos) { obj.scopePos_ = pos }
158
159 func (obj *object) sameId(pkg *Package, name string) bool {
160
161
162
163
164 if name != obj.name {
165 return false
166 }
167
168 if obj.Exported() {
169 return true
170 }
171
172
173
174 if pkg == nil || obj.pkg == nil {
175 return pkg == obj.pkg
176 }
177
178 return pkg.path == obj.pkg.path
179 }
180
181
182
183 type PkgName struct {
184 object
185 imported *Package
186 used bool
187 }
188
189
190
191 func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
192 return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, token.NoPos}, imported, false}
193 }
194
195
196
197 func (obj *PkgName) Imported() *Package { return obj.imported }
198
199
200 type Const struct {
201 object
202 val constant.Value
203 }
204
205
206
207 func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const {
208 return &Const{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, val}
209 }
210
211
212 func (obj *Const) Val() constant.Value { return obj.val }
213
214 func (*Const) isDependency() {}
215
216
217 type TypeName struct {
218 object
219 }
220
221
222
223
224
225
226
227
228 func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
229 return &TypeName{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}}
230 }
231
232
233
234 func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName {
235 obj := NewTypeName(pos, pkg, name, nil)
236 NewNamed(obj, nil, nil).loader = load
237 return obj
238 }
239
240
241 func (obj *TypeName) IsAlias() bool {
242 switch t := obj.typ.(type) {
243 case nil:
244 return false
245 case *Basic:
246
247 if obj.pkg == Unsafe {
248 return false
249 }
250
251
252
253
254
255
256 return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune
257 case *Named:
258 return obj != t.obj
259 case *TypeParam:
260 return obj != t.obj
261 default:
262 return true
263 }
264 }
265
266
267 type Var struct {
268 object
269 embedded bool
270 isField bool
271 used bool
272 origin *Var
273 }
274
275
276
277 func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
278 return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}}
279 }
280
281
282 func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
283 return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, used: true}
284 }
285
286
287
288
289 func NewField(pos token.Pos, pkg *Package, name string, typ Type, embedded bool) *Var {
290 return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, embedded: embedded, isField: true}
291 }
292
293
294
295 func (obj *Var) Anonymous() bool { return obj.embedded }
296
297
298 func (obj *Var) Embedded() bool { return obj.embedded }
299
300
301 func (obj *Var) IsField() bool { return obj.isField }
302
303
304
305
306
307
308
309
310 func (obj *Var) Origin() *Var {
311 if obj.origin != nil {
312 return obj.origin
313 }
314 return obj
315 }
316
317 func (*Var) isDependency() {}
318
319
320
321
322 type Func struct {
323 object
324 hasPtrRecv_ bool
325 origin *Func
326 }
327
328
329
330 func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
331
332 var typ Type
333 if sig != nil {
334 typ = sig
335 }
336 return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, false, nil}
337 }
338
339
340
341 func (obj *Func) FullName() string {
342 var buf bytes.Buffer
343 writeFuncName(&buf, obj, nil)
344 return buf.String()
345 }
346
347
348
349
350 func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
351
352
353
354
355
356
357
358
359 func (obj *Func) Origin() *Func {
360 if obj.origin != nil {
361 return obj.origin
362 }
363 return obj
364 }
365
366
367 func (obj *Func) hasPtrRecv() bool {
368
369
370
371
372 if sig, _ := obj.typ.(*Signature); sig != nil && sig.recv != nil {
373 _, isPtr := deref(sig.recv.typ)
374 return isPtr
375 }
376
377
378
379
380
381
382 return obj.hasPtrRecv_
383 }
384
385 func (*Func) isDependency() {}
386
387
388
389 type Label struct {
390 object
391 used bool
392 }
393
394
395 func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
396 return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid], color_: black}, false}
397 }
398
399
400
401 type Builtin struct {
402 object
403 id builtinId
404 }
405
406 func newBuiltin(id builtinId) *Builtin {
407 return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid], color_: black}, id}
408 }
409
410
411 type Nil struct {
412 object
413 }
414
415 func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
416 var tname *TypeName
417 typ := obj.Type()
418
419 switch obj := obj.(type) {
420 case *PkgName:
421 fmt.Fprintf(buf, "package %s", obj.Name())
422 if path := obj.imported.path; path != "" && path != obj.name {
423 fmt.Fprintf(buf, " (%q)", path)
424 }
425 return
426
427 case *Const:
428 buf.WriteString("const")
429
430 case *TypeName:
431 tname = obj
432 buf.WriteString("type")
433 if isTypeParam(typ) {
434 buf.WriteString(" parameter")
435 }
436
437 case *Var:
438 if obj.isField {
439 buf.WriteString("field")
440 } else {
441 buf.WriteString("var")
442 }
443
444 case *Func:
445 buf.WriteString("func ")
446 writeFuncName(buf, obj, qf)
447 if typ != nil {
448 WriteSignature(buf, typ.(*Signature), qf)
449 }
450 return
451
452 case *Label:
453 buf.WriteString("label")
454 typ = nil
455
456 case *Builtin:
457 buf.WriteString("builtin")
458 typ = nil
459
460 case *Nil:
461 buf.WriteString("nil")
462 return
463
464 default:
465 panic(fmt.Sprintf("writeObject(%T)", obj))
466 }
467
468 buf.WriteByte(' ')
469
470
471 if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj {
472 writePackage(buf, obj.Pkg(), qf)
473 }
474 buf.WriteString(obj.Name())
475
476 if typ == nil {
477 return
478 }
479
480 if tname != nil {
481 switch t := typ.(type) {
482 case *Basic:
483
484
485 return
486 case *Named:
487 if t.TypeParams().Len() > 0 {
488 newTypeWriter(buf, qf).tParamList(t.TypeParams().list())
489 }
490 }
491 if tname.IsAlias() {
492 buf.WriteString(" =")
493 } else if t, _ := typ.(*TypeParam); t != nil {
494 typ = t.bound
495 } else {
496
497 typ = under(typ)
498 }
499 }
500
501
502
503
504 if obj == universeAny {
505 assert(Identical(typ, &emptyInterface))
506 typ = &emptyInterface
507 }
508
509 buf.WriteByte(' ')
510 WriteType(buf, typ, qf)
511 }
512
513 func writePackage(buf *bytes.Buffer, pkg *Package, qf Qualifier) {
514 if pkg == nil {
515 return
516 }
517 var s string
518 if qf != nil {
519 s = qf(pkg)
520 } else {
521 s = pkg.Path()
522 }
523 if s != "" {
524 buf.WriteString(s)
525 buf.WriteByte('.')
526 }
527 }
528
529
530
531
532 func ObjectString(obj Object, qf Qualifier) string {
533 var buf bytes.Buffer
534 writeObject(&buf, obj, qf)
535 return buf.String()
536 }
537
538 func (obj *PkgName) String() string { return ObjectString(obj, nil) }
539 func (obj *Const) String() string { return ObjectString(obj, nil) }
540 func (obj *TypeName) String() string { return ObjectString(obj, nil) }
541 func (obj *Var) String() string { return ObjectString(obj, nil) }
542 func (obj *Func) String() string { return ObjectString(obj, nil) }
543 func (obj *Label) String() string { return ObjectString(obj, nil) }
544 func (obj *Builtin) String() string { return ObjectString(obj, nil) }
545 func (obj *Nil) String() string { return ObjectString(obj, nil) }
546
547 func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
548 if f.typ != nil {
549 sig := f.typ.(*Signature)
550 if recv := sig.Recv(); recv != nil {
551 buf.WriteByte('(')
552 if _, ok := recv.Type().(*Interface); ok {
553
554
555
556
557 buf.WriteString("interface")
558 } else {
559 WriteType(buf, recv.Type(), qf)
560 }
561 buf.WriteByte(')')
562 buf.WriteByte('.')
563 } else if f.pkg != nil {
564 writePackage(buf, f.pkg, qf)
565 }
566 }
567 buf.WriteString(f.name)
568 }
569
View as plain text