1
2
3
4
5
6
7
8
9
10
11
12
13 package main
14
15 import (
16 "go/types"
17
18 "golang.org/x/tools/internal/aliases"
19 )
20
21 func (p *printer) writeType(this *types.Package, typ types.Type) {
22 p.writeTypeInternal(this, typ, make([]types.Type, 8))
23 }
24
25
26 const GcCompatibilityMode = false
27
28 func (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited []types.Type) {
29
30
31
32
33 for _, t := range visited {
34 if t == typ {
35 p.printf("○%T", typ)
36 return
37 }
38 }
39 visited = append(visited, typ)
40
41 switch t := typ.(type) {
42 case nil:
43 p.print("<nil>")
44
45 case *types.Basic:
46 if t.Kind() == types.UnsafePointer {
47 p.print("unsafe.")
48 }
49 if GcCompatibilityMode {
50
51 switch t.Kind() {
52 case types.Byte:
53 t = types.Typ[types.Uint8]
54 case types.Rune:
55 t = types.Typ[types.Int32]
56 }
57 }
58 p.print(t.Name())
59
60 case *types.Array:
61 p.printf("[%d]", t.Len())
62 p.writeTypeInternal(this, t.Elem(), visited)
63
64 case *types.Slice:
65 p.print("[]")
66 p.writeTypeInternal(this, t.Elem(), visited)
67
68 case *types.Struct:
69 n := t.NumFields()
70 if n == 0 {
71 p.print("struct{}")
72 return
73 }
74
75 p.print("struct {\n")
76 p.indent++
77 for i := 0; i < n; i++ {
78 f := t.Field(i)
79 if !f.Anonymous() {
80 p.printf("%s ", f.Name())
81 }
82 p.writeTypeInternal(this, f.Type(), visited)
83 if tag := t.Tag(i); tag != "" {
84 p.printf(" %q", tag)
85 }
86 p.print("\n")
87 }
88 p.indent--
89 p.print("}")
90
91 case *types.Pointer:
92 p.print("*")
93 p.writeTypeInternal(this, t.Elem(), visited)
94
95 case *types.Tuple:
96 p.writeTuple(this, t, false, visited)
97
98 case *types.Signature:
99 p.print("func")
100 p.writeSignatureInternal(this, t, visited)
101
102 case *types.Interface:
103
104
105
106
107
108
109
110
111
112
113
114 n := t.NumMethods()
115 if n == 0 {
116 p.print("interface{}")
117 return
118 }
119
120 p.print("interface {\n")
121 p.indent++
122 if GcCompatibilityMode {
123
124
125 for i := 0; i < n; i++ {
126 m := t.Method(i)
127 p.print(m.Name())
128 p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
129 p.print("\n")
130 }
131 } else {
132
133 for i, n := 0, t.NumExplicitMethods(); i < n; i++ {
134 m := t.ExplicitMethod(i)
135 p.print(m.Name())
136 p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
137 p.print("\n")
138 }
139 for i, n := 0, t.NumEmbeddeds(); i < n; i++ {
140 typ := t.EmbeddedType(i)
141 p.writeTypeInternal(this, typ, visited)
142 p.print("\n")
143 }
144 }
145 p.indent--
146 p.print("}")
147
148 case *types.Map:
149 p.print("map[")
150 p.writeTypeInternal(this, t.Key(), visited)
151 p.print("]")
152 p.writeTypeInternal(this, t.Elem(), visited)
153
154 case *types.Chan:
155 var s string
156 var parens bool
157 switch t.Dir() {
158 case types.SendRecv:
159 s = "chan "
160
161 if c, _ := t.Elem().(*types.Chan); c != nil && c.Dir() == types.RecvOnly {
162 parens = true
163 }
164 case types.SendOnly:
165 s = "chan<- "
166 case types.RecvOnly:
167 s = "<-chan "
168 default:
169 panic("unreachable")
170 }
171 p.print(s)
172 if parens {
173 p.print("(")
174 }
175 p.writeTypeInternal(this, t.Elem(), visited)
176 if parens {
177 p.print(")")
178 }
179
180 case *aliases.Alias:
181
182 p.writeTypeInternal(this, aliases.Unalias(t), visited)
183
184 case *types.Named:
185 s := "<Named w/o object>"
186 if obj := t.Obj(); obj != nil {
187 if pkg := obj.Pkg(); pkg != nil {
188 if pkg != this {
189 p.print(pkg.Path())
190 p.print(".")
191 }
192
193
194
195 }
196 s = obj.Name()
197 }
198 p.print(s)
199
200 default:
201
202 p.print(t.String())
203 }
204 }
205
206 func (p *printer) writeTuple(this *types.Package, tup *types.Tuple, variadic bool, visited []types.Type) {
207 p.print("(")
208 for i, n := 0, tup.Len(); i < n; i++ {
209 if i > 0 {
210 p.print(", ")
211 }
212 v := tup.At(i)
213 if name := v.Name(); name != "" {
214 p.print(name)
215 p.print(" ")
216 }
217 typ := v.Type()
218 if variadic && i == n-1 {
219 p.print("...")
220 typ = typ.(*types.Slice).Elem()
221 }
222 p.writeTypeInternal(this, typ, visited)
223 }
224 p.print(")")
225 }
226
227 func (p *printer) writeSignature(this *types.Package, sig *types.Signature) {
228 p.writeSignatureInternal(this, sig, make([]types.Type, 8))
229 }
230
231 func (p *printer) writeSignatureInternal(this *types.Package, sig *types.Signature, visited []types.Type) {
232 p.writeTuple(this, sig.Params(), sig.Variadic(), visited)
233
234 res := sig.Results()
235 n := res.Len()
236 if n == 0 {
237
238 return
239 }
240
241 p.print(" ")
242 if n == 1 && res.At(0).Name() == "" {
243
244 p.writeTypeInternal(this, res.At(0).Type(), visited)
245 return
246 }
247
248
249 p.writeTuple(this, res, false, visited)
250 }
251
View as plain text