1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "fmt"
10 "go/constant"
11 "go/token"
12 "go/types"
13 "io"
14 "math/big"
15
16 "golang.org/x/tools/internal/aliases"
17 )
18
19
20
21 func print(w io.Writer, pkg *types.Package, filter func(types.Object) bool) {
22 var p printer
23 p.pkg = pkg
24 p.printPackage(pkg, filter)
25 p.printGccgoExtra(pkg)
26 io.Copy(w, &p.buf)
27 }
28
29 type printer struct {
30 pkg *types.Package
31 buf bytes.Buffer
32 indent int
33 last byte
34 }
35
36 func (p *printer) print(s string) {
37
38
39
40 for i := 0; i < len(s); i++ {
41 ch := s[i]
42 if ch != '\n' && p.last == '\n' {
43
44
45
46 p.buf.WriteString("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"[:p.indent])
47 }
48 p.buf.WriteByte(ch)
49 p.last = ch
50 }
51 }
52
53 func (p *printer) printf(format string, args ...interface{}) {
54 p.print(fmt.Sprintf(format, args...))
55 }
56
57
58
59
60 func methodsFor(obj *types.TypeName) (*types.Named, []*types.Selection) {
61 named, _ := aliases.Unalias(obj.Type()).(*types.Named)
62 if named == nil {
63
64
65 return nil, nil
66 }
67 if _, ok := named.Underlying().(*types.Interface); ok {
68
69 return nil, nil
70 }
71 methods := combinedMethodSet(named)
72 if len(methods) == 0 {
73 return nil, nil
74 }
75 return named, methods
76 }
77
78 func (p *printer) printPackage(pkg *types.Package, filter func(types.Object) bool) {
79
80 var (
81 consts []*types.Const
82 typem []*types.Named
83 typez []*types.TypeName
84 vars []*types.Var
85 funcs []*types.Func
86 builtins []*types.Builtin
87 methods = make(map[*types.Named][]*types.Selection)
88 )
89 scope := pkg.Scope()
90 for _, name := range scope.Names() {
91 obj := scope.Lookup(name)
92 if obj.Exported() {
93
94 if filter == nil || filter(obj) {
95 switch obj := obj.(type) {
96 case *types.Const:
97 consts = append(consts, obj)
98 case *types.TypeName:
99
100 if named, m := methodsFor(obj); named != nil {
101 typem = append(typem, named)
102 methods[named] = m
103 } else {
104 typez = append(typez, obj)
105 }
106 case *types.Var:
107 vars = append(vars, obj)
108 case *types.Func:
109 funcs = append(funcs, obj)
110 case *types.Builtin:
111
112 builtins = append(builtins, obj)
113 }
114 }
115 } else if filter == nil {
116
117 if obj, _ := obj.(*types.TypeName); obj != nil {
118
119 if named, m := methodsFor(obj); named != nil {
120 typem = append(typem, named)
121 methods[named] = m
122 }
123 }
124 }
125 }
126
127 p.printf("package %s // %q\n", pkg.Name(), pkg.Path())
128
129 p.printDecl("const", len(consts), func() {
130 for _, obj := range consts {
131 p.printObj(obj)
132 p.print("\n")
133 }
134 })
135
136 p.printDecl("var", len(vars), func() {
137 for _, obj := range vars {
138 p.printObj(obj)
139 p.print("\n")
140 }
141 })
142
143 p.printDecl("type", len(typez), func() {
144 for _, obj := range typez {
145 p.printf("%s ", obj.Name())
146 typ := obj.Type()
147 if isAlias(obj) {
148 p.print("= ")
149 p.writeType(p.pkg, typ)
150 } else {
151 p.writeType(p.pkg, typ.Underlying())
152 }
153 p.print("\n")
154 }
155 })
156
157
158 for _, named := range typem {
159 first := true
160 if obj := named.Obj(); obj.Exported() {
161 if first {
162 p.print("\n")
163 first = false
164 }
165 p.printf("type %s ", obj.Name())
166 p.writeType(p.pkg, named.Underlying())
167 p.print("\n")
168 }
169 for _, m := range methods[named] {
170 if obj := m.Obj(); obj.Exported() {
171 if first {
172 p.print("\n")
173 first = false
174 }
175 p.printFunc(m.Recv(), obj.(*types.Func))
176 p.print("\n")
177 }
178 }
179 }
180
181 if len(funcs) > 0 {
182 p.print("\n")
183 for _, obj := range funcs {
184 p.printFunc(nil, obj)
185 p.print("\n")
186 }
187 }
188
189
190 if len(builtins) > 0 {
191 p.print("\n")
192 for _, obj := range builtins {
193 p.printf("func %s() // builtin\n", obj.Name())
194 }
195 }
196
197 p.print("\n")
198 }
199
200 func (p *printer) printDecl(keyword string, n int, printGroup func()) {
201 switch n {
202 case 0:
203
204 case 1:
205 p.printf("\n%s ", keyword)
206 printGroup()
207 default:
208 p.printf("\n%s (\n", keyword)
209 p.indent++
210 printGroup()
211 p.indent--
212 p.print(")\n")
213 }
214 }
215
216
217
218 func absInt(v constant.Value) *big.Int {
219
220 b := constant.Bytes(v)
221 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
222 b[i], b[j] = b[j], b[i]
223 }
224 return new(big.Int).SetBytes(b)
225 }
226
227 var (
228 one = big.NewRat(1, 1)
229 ten = big.NewRat(10, 1)
230 )
231
232
233
234 func floatString(v constant.Value) string {
235 if constant.Sign(v) == 0 {
236 return "0.0"
237 }
238
239
240
241 x := new(big.Rat).SetFrac(absInt(constant.Num(v)), absInt(constant.Denom(v)))
242
243
244
245 var e int
246 for x.Cmp(ten) >= 0 {
247 x.Quo(x, ten)
248 e++
249 }
250 for x.Cmp(one) < 0 {
251 x.Mul(x, ten)
252 e--
253 }
254
255
256
257
258
259 s := x.FloatString(100)
260
261
262 i := len(s)
263 for i > 0 && s[i-1] == '0' {
264 i--
265 }
266 s = s[:i]
267
268
269 if len(s) > 0 && s[len(s)-1] == '.' {
270 s += "0"
271 }
272
273
274 if e != 0 {
275 s += fmt.Sprintf("e%+d", e)
276 }
277 if constant.Sign(v) < 0 {
278 s = "-" + s
279 }
280
281
282
283
284
285 return s
286 }
287
288
289
290
291
292 func valString(v constant.Value, floatFmt bool) string {
293 switch v.Kind() {
294 case constant.Int:
295 if floatFmt {
296 return floatString(v)
297 }
298 case constant.Float:
299 return floatString(v)
300 case constant.Complex:
301 re := constant.Real(v)
302 im := constant.Imag(v)
303 var s string
304 if constant.Sign(re) != 0 {
305 s = floatString(re)
306 if constant.Sign(im) >= 0 {
307 s += " + "
308 } else {
309 s += " - "
310 im = constant.UnaryOp(token.SUB, im, 0)
311 }
312 }
313
314 return s + floatString(im) + "i"
315 }
316 return v.String()
317 }
318
319 func (p *printer) printObj(obj types.Object) {
320 p.print(obj.Name())
321
322 typ, basic := obj.Type().Underlying().(*types.Basic)
323 if basic && typ.Info()&types.IsUntyped != 0 {
324
325 } else {
326 p.print(" ")
327 p.writeType(p.pkg, obj.Type())
328 }
329
330 if obj, ok := obj.(*types.Const); ok {
331 floatFmt := basic && typ.Info()&(types.IsFloat|types.IsComplex) != 0
332 p.print(" = ")
333 p.print(valString(obj.Val(), floatFmt))
334 }
335 }
336
337 func (p *printer) printFunc(recvType types.Type, obj *types.Func) {
338 p.print("func ")
339 sig := obj.Type().(*types.Signature)
340 if recvType != nil {
341 p.print("(")
342 p.writeType(p.pkg, recvType)
343 p.print(") ")
344 }
345 p.print(obj.Name())
346 p.writeSignature(p.pkg, sig)
347 }
348
349
350
351
352
353
354
355
356
357 func combinedMethodSet(T *types.Named) []*types.Selection {
358
359 mset := types.NewMethodSet(T)
360 var res []*types.Selection
361 for i, n := 0, mset.Len(); i < n; i++ {
362 res = append(res, mset.At(i))
363 }
364
365
366 pmset := types.NewMethodSet(types.NewPointer(T))
367 for i, n := 0, pmset.Len(); i < n; i++ {
368 pm := pmset.At(i)
369 if obj := pm.Obj(); mset.Lookup(obj.Pkg(), obj.Name()) == nil {
370 res = append(res, pm)
371 }
372 }
373
374 return res
375 }
376
View as plain text