Source file
src/go/types/object.go
1
2
3
4
5 package types
6
7 import (
8 "bytes"
9 "fmt"
10 "go/ast"
11 "go/constant"
12 "go/token"
13 )
14
15
16
17
18
19 type Object interface {
20 Parent() *Scope
21 Pos() token.Pos
22 Pkg() *Package
23 Name() string
24 Type() Type
25 Exported() bool
26 Id() string
27
28
29 String() string
30
31
32
33
34
35 order() uint32
36
37
38 setOrder(uint32)
39
40
41 setParent(*Scope)
42
43
44 sameId(pkg *Package, name string) bool
45
46
47 scopePos() token.Pos
48
49
50 setScopePos(pos token.Pos)
51 }
52
53
54
55 func Id(pkg *Package, name string) string {
56 if ast.IsExported(name) {
57 return name
58 }
59
60
61
62
63
64 path := "_"
65
66
67 if pkg != nil && pkg.path != "" {
68 path = pkg.path
69 }
70 return path + "." + name
71 }
72
73
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
101
102
103
104 if name != obj.name {
105 return false
106 }
107
108 if obj.Exported() {
109 return true
110 }
111
112
113
114 if pkg == nil || obj.pkg == nil {
115 return pkg == obj.pkg
116 }
117
118 return pkg.path == obj.pkg.path
119 }
120
121
122
123 type PkgName struct {
124 object
125 imported *Package
126 used bool
127 }
128
129
130
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
136
137 func (obj *PkgName) Imported() *Package { return obj.imported }
138
139
140 type Const struct {
141 object
142 val constant.Value
143 visited bool
144 }
145
146
147
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() {}
154
155
156 type TypeName struct {
157 object
158 }
159
160
161
162
163
164
165
166
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
172 func (obj *TypeName) IsAlias() bool {
173 switch t := obj.typ.(type) {
174 case nil:
175 return false
176 case *Basic:
177
178 if obj.pkg == Unsafe {
179 return false
180 }
181
182
183
184
185
186
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
196 type Var struct {
197 object
198 anonymous bool
199 visited bool
200 isField bool
201 used bool
202 }
203
204
205
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
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}
213 }
214
215
216
217
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
223 func (obj *Var) Anonymous() bool { return obj.anonymous }
224
225
226 func (obj *Var) IsField() bool { return obj.isField }
227
228 func (*Var) isDependency() {}
229
230
231
232
233 type Func struct {
234 object
235 }
236
237
238
239 func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
240
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
249
250 func (obj *Func) FullName() string {
251 var buf bytes.Buffer
252 writeFuncName(&buf, obj, nil)
253 return buf.String()
254 }
255
256
257 func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
258
259 func (*Func) isDependency() {}
260
261
262
263 type Label struct {
264 object
265 used bool
266 }
267
268
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
274
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
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
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
353
354
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
386
387
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
410
411
412
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
View as plain text