Source file
src/go/types/object.go
1
2
3
4
5
6
7
8 package types
9
10 import (
11 "bytes"
12 "fmt"
13 "go/constant"
14 "go/token"
15 "strings"
16 "unicode"
17 "unicode/utf8"
18 )
19
20
21
22
23
24
25
26
27
28
29 type Object interface {
30 Parent() *Scope
31 Pos() token.Pos
32 Pkg() *Package
33 Name() string
34 Type() Type
35 Exported() bool
36 Id() string
37
38
39
40 String() string
41
42
43
44
45
46 order() uint32
47
48
49 color() color
50
51
52 setType(Type)
53
54
55 setOrder(uint32)
56
57
58 setColor(color color)
59
60
61 setParent(*Scope)
62
63
64
65
66 sameId(pkg *Package, name string, foldCase bool) bool
67
68
69 scopePos() token.Pos
70
71
72 setScopePos(pos token.Pos)
73 }
74
75 func isExported(name string) bool {
76 ch, _ := utf8.DecodeRuneInString(name)
77 return unicode.IsUpper(ch)
78 }
79
80
81
82 func Id(pkg *Package, name string) string {
83 if isExported(name) {
84 return name
85 }
86
87
88
89
90
91 path := "_"
92
93
94 if pkg != nil && pkg.path != "" {
95 path = pkg.path
96 }
97 return path + "." + name
98 }
99
100
101 type object struct {
102 parent *Scope
103 pos token.Pos
104 pkg *Package
105 name string
106 typ Type
107 order_ uint32
108 color_ color
109 scopePos_ token.Pos
110 }
111
112
113 type color uint32
114
115
116
117 const (
118 white color = iota
119 black
120 grey
121 )
122
123 func (c color) String() string {
124 switch c {
125 case white:
126 return "white"
127 case black:
128 return "black"
129 default:
130 return "grey"
131 }
132 }
133
134
135
136 func colorFor(t Type) color {
137 if t != nil {
138 return black
139 }
140 return white
141 }
142
143
144
145 func (obj *object) Parent() *Scope { return obj.parent }
146
147
148 func (obj *object) Pos() token.Pos { return obj.pos }
149
150
151
152 func (obj *object) Pkg() *Package { return obj.pkg }
153
154
155 func (obj *object) Name() string { return obj.name }
156
157
158 func (obj *object) Type() Type { return obj.typ }
159
160
161
162
163 func (obj *object) Exported() bool { return isExported(obj.name) }
164
165
166 func (obj *object) Id() string { return Id(obj.pkg, obj.name) }
167
168 func (obj *object) String() string { panic("abstract") }
169 func (obj *object) order() uint32 { return obj.order_ }
170 func (obj *object) color() color { return obj.color_ }
171 func (obj *object) scopePos() token.Pos { return obj.scopePos_ }
172
173 func (obj *object) setParent(parent *Scope) { obj.parent = parent }
174 func (obj *object) setType(typ Type) { obj.typ = typ }
175 func (obj *object) setOrder(order uint32) { assert(order > 0); obj.order_ = order }
176 func (obj *object) setColor(color color) { assert(color != white); obj.color_ = color }
177 func (obj *object) setScopePos(pos token.Pos) { obj.scopePos_ = pos }
178
179 func (obj *object) sameId(pkg *Package, name string, foldCase bool) bool {
180
181 if foldCase && strings.EqualFold(obj.name, name) {
182 return true
183 }
184
185
186
187
188 if obj.name != name {
189 return false
190 }
191
192 if obj.Exported() {
193 return true
194 }
195
196 return samePkg(obj.pkg, pkg)
197 }
198
199
200
201
202
203
204
205
206
207
208
209 func (a *object) cmp(b *object) int {
210 if a == b {
211 return 0
212 }
213
214
215 if a == nil {
216 return -1
217 }
218 if b == nil {
219 return +1
220 }
221
222
223 ea := isExported(a.name)
224 eb := isExported(b.name)
225 if ea != eb {
226 if ea {
227 return -1
228 }
229 return +1
230 }
231
232
233 if a.name != b.name {
234 return strings.Compare(a.name, b.name)
235 }
236 if !ea {
237 return strings.Compare(a.pkg.path, b.pkg.path)
238 }
239
240 return 0
241 }
242
243
244
245 type PkgName struct {
246 object
247 imported *Package
248 }
249
250
251
252 func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
253 return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, nopos}, imported}
254 }
255
256
257
258 func (obj *PkgName) Imported() *Package { return obj.imported }
259
260
261 type Const struct {
262 object
263 val constant.Value
264 }
265
266
267
268 func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const {
269 return &Const{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, val}
270 }
271
272
273 func (obj *Const) Val() constant.Value { return obj.val }
274
275 func (*Const) isDependency() {}
276
277
278
279
280
281
282 type TypeName struct {
283 object
284 }
285
286
287
288
289
290
291
292
293 func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
294 return &TypeName{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}}
295 }
296
297
298
299 func _NewTypeNameLazy(pos token.Pos, pkg *Package, name string, load func(named *Named) (tparams []*TypeParam, underlying Type, methods []*Func)) *TypeName {
300 obj := NewTypeName(pos, pkg, name, nil)
301 NewNamed(obj, nil, nil).loader = load
302 return obj
303 }
304
305
306 func (obj *TypeName) IsAlias() bool {
307 switch t := obj.typ.(type) {
308 case nil:
309 return false
310
311
312 case *Basic:
313
314 if obj.pkg == Unsafe {
315 return false
316 }
317
318
319
320
321
322
323 return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune
324 case *Named:
325 return obj != t.obj
326 case *TypeParam:
327 return obj != t.obj
328 default:
329 return true
330 }
331 }
332
333
334 type Var struct {
335 object
336 origin *Var
337 kind VarKind
338 embedded bool
339 }
340
341
342 type VarKind uint8
343
344 const (
345 _ VarKind = iota
346 PackageVar
347 LocalVar
348 RecvVar
349 ParamVar
350 ResultVar
351 FieldVar
352 )
353
354 var varKindNames = [...]string{
355 0: "VarKind(0)",
356 PackageVar: "PackageVar",
357 LocalVar: "LocalVar",
358 RecvVar: "RecvVar",
359 ParamVar: "ParamVar",
360 ResultVar: "ResultVar",
361 FieldVar: "FieldVar",
362 }
363
364 func (kind VarKind) String() string {
365 if 0 <= kind && int(kind) < len(varKindNames) {
366 return varKindNames[kind]
367 }
368 return fmt.Sprintf("VarKind(%d)", kind)
369 }
370
371
372 func (v *Var) Kind() VarKind { return v.kind }
373
374
375
376 func (v *Var) SetKind(kind VarKind) { v.kind = kind }
377
378
379
380
381
382
383 func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
384 return newVar(PackageVar, pos, pkg, name, typ)
385 }
386
387
388
389
390
391 func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
392 return newVar(ParamVar, pos, pkg, name, typ)
393 }
394
395
396
397
398 func NewField(pos token.Pos, pkg *Package, name string, typ Type, embedded bool) *Var {
399 v := newVar(FieldVar, pos, pkg, name, typ)
400 v.embedded = embedded
401 return v
402 }
403
404
405
406 func newVar(kind VarKind, pos token.Pos, pkg *Package, name string, typ Type) *Var {
407 return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, kind: kind}
408 }
409
410
411
412 func (obj *Var) Anonymous() bool { return obj.embedded }
413
414
415 func (obj *Var) Embedded() bool { return obj.embedded }
416
417
418 func (obj *Var) IsField() bool { return obj.kind == FieldVar }
419
420
421
422
423
424
425
426
427 func (obj *Var) Origin() *Var {
428 if obj.origin != nil {
429 return obj.origin
430 }
431 return obj
432 }
433
434 func (*Var) isDependency() {}
435
436
437
438
439 type Func struct {
440 object
441 hasPtrRecv_ bool
442 origin *Func
443 }
444
445
446
447 func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
448 var typ Type
449 if sig != nil {
450 typ = sig
451 } else {
452
453
454
455
456 }
457 return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, false, nil}
458 }
459
460
461 func (obj *Func) Signature() *Signature {
462 if obj.typ != nil {
463 return obj.typ.(*Signature)
464 }
465
466
467
468
469
470
471
472
473 return new(Signature)
474 }
475
476
477
478 func (obj *Func) FullName() string {
479 var buf bytes.Buffer
480 writeFuncName(&buf, obj, nil)
481 return buf.String()
482 }
483
484
485
486
487 func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
488
489
490
491
492
493
494
495
496 func (obj *Func) Origin() *Func {
497 if obj.origin != nil {
498 return obj.origin
499 }
500 return obj
501 }
502
503
504
505
506
507 func (obj *Func) Pkg() *Package { return obj.object.Pkg() }
508
509
510 func (obj *Func) hasPtrRecv() bool {
511
512
513
514
515 if sig, _ := obj.typ.(*Signature); sig != nil && sig.recv != nil {
516 _, isPtr := deref(sig.recv.typ)
517 return isPtr
518 }
519
520
521
522
523
524
525 return obj.hasPtrRecv_
526 }
527
528 func (*Func) isDependency() {}
529
530
531
532 type Label struct {
533 object
534 used bool
535 }
536
537
538 func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
539 return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid], color_: black}, false}
540 }
541
542
543
544 type Builtin struct {
545 object
546 id builtinId
547 }
548
549 func newBuiltin(id builtinId) *Builtin {
550 return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid], color_: black}, id}
551 }
552
553
554 type Nil struct {
555 object
556 }
557
558 func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
559 var tname *TypeName
560 typ := obj.Type()
561
562 switch obj := obj.(type) {
563 case *PkgName:
564 fmt.Fprintf(buf, "package %s", obj.Name())
565 if path := obj.imported.path; path != "" && path != obj.name {
566 fmt.Fprintf(buf, " (%q)", path)
567 }
568 return
569
570 case *Const:
571 buf.WriteString("const")
572
573 case *TypeName:
574 tname = obj
575 buf.WriteString("type")
576 if isTypeParam(typ) {
577 buf.WriteString(" parameter")
578 }
579
580 case *Var:
581 if obj.IsField() {
582 buf.WriteString("field")
583 } else {
584 buf.WriteString("var")
585 }
586
587 case *Func:
588 buf.WriteString("func ")
589 writeFuncName(buf, obj, qf)
590 if typ != nil {
591 WriteSignature(buf, typ.(*Signature), qf)
592 }
593 return
594
595 case *Label:
596 buf.WriteString("label")
597 typ = nil
598
599 case *Builtin:
600 buf.WriteString("builtin")
601 typ = nil
602
603 case *Nil:
604 buf.WriteString("nil")
605 return
606
607 default:
608 panic(fmt.Sprintf("writeObject(%T)", obj))
609 }
610
611 buf.WriteByte(' ')
612
613
614 if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj {
615 buf.WriteString(packagePrefix(obj.Pkg(), qf))
616 }
617 buf.WriteString(obj.Name())
618
619 if typ == nil {
620 return
621 }
622
623 if tname != nil {
624 switch t := typ.(type) {
625 case *Basic:
626
627
628 return
629 case genericType:
630 if t.TypeParams().Len() > 0 {
631 newTypeWriter(buf, qf).tParamList(t.TypeParams().list())
632 }
633 }
634 if tname.IsAlias() {
635 buf.WriteString(" =")
636 if alias, ok := typ.(*Alias); ok {
637 typ = alias.fromRHS
638 }
639 } else if t, _ := typ.(*TypeParam); t != nil {
640 typ = t.bound
641 } else {
642
643
644 typ = under(typ)
645 }
646 }
647
648
649
650
651 if obj.Name() == "any" && obj.Parent() == Universe {
652 assert(Identical(typ, &emptyInterface))
653 typ = &emptyInterface
654 }
655
656 buf.WriteByte(' ')
657 WriteType(buf, typ, qf)
658 }
659
660 func packagePrefix(pkg *Package, qf Qualifier) string {
661 if pkg == nil {
662 return ""
663 }
664 var s string
665 if qf != nil {
666 s = qf(pkg)
667 } else {
668 s = pkg.Path()
669 }
670 if s != "" {
671 s += "."
672 }
673 return s
674 }
675
676
677
678
679 func ObjectString(obj Object, qf Qualifier) string {
680 var buf bytes.Buffer
681 writeObject(&buf, obj, qf)
682 return buf.String()
683 }
684
685 func (obj *PkgName) String() string { return ObjectString(obj, nil) }
686 func (obj *Const) String() string { return ObjectString(obj, nil) }
687 func (obj *TypeName) String() string { return ObjectString(obj, nil) }
688 func (obj *Var) String() string { return ObjectString(obj, nil) }
689 func (obj *Func) String() string { return ObjectString(obj, nil) }
690 func (obj *Label) String() string { return ObjectString(obj, nil) }
691 func (obj *Builtin) String() string { return ObjectString(obj, nil) }
692 func (obj *Nil) String() string { return ObjectString(obj, nil) }
693
694 func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
695 if f.typ != nil {
696 sig := f.typ.(*Signature)
697 if recv := sig.Recv(); recv != nil {
698 buf.WriteByte('(')
699 if _, ok := recv.Type().(*Interface); ok {
700
701
702
703
704 buf.WriteString("interface")
705 } else {
706 WriteType(buf, recv.Type(), qf)
707 }
708 buf.WriteByte(')')
709 buf.WriteByte('.')
710 } else if f.pkg != nil {
711 buf.WriteString(packagePrefix(f.pkg, qf))
712 }
713 }
714 buf.WriteString(f.name)
715 }
716
View as plain text