Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / cmd / godex / writetype.go
1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // This file implements writing of types. The functionality is lifted
6 // directly from go/types, but now contains various modifications for
7 // nicer output.
8 //
9 // TODO(gri) back-port once we have a fixed interface and once the
10 // go/types API is not frozen anymore for the 1.3 release; and remove
11 // this implementation if possible.
12
13 package main
14
15 import "go/types"
16
17 func (p *printer) writeType(this *types.Package, typ types.Type) {
18         p.writeTypeInternal(this, typ, make([]types.Type, 8))
19 }
20
21 // From go/types - leave for now to ease back-porting this code.
22 const GcCompatibilityMode = false
23
24 func (p *printer) writeTypeInternal(this *types.Package, typ types.Type, visited []types.Type) {
25         // Theoretically, this is a quadratic lookup algorithm, but in
26         // practice deeply nested composite types with unnamed component
27         // types are uncommon. This code is likely more efficient than
28         // using a map.
29         for _, t := range visited {
30                 if t == typ {
31                         p.printf("○%T", typ) // cycle to typ
32                         return
33                 }
34         }
35         visited = append(visited, typ)
36
37         switch t := typ.(type) {
38         case nil:
39                 p.print("<nil>")
40
41         case *types.Basic:
42                 if t.Kind() == types.UnsafePointer {
43                         p.print("unsafe.")
44                 }
45                 if GcCompatibilityMode {
46                         // forget the alias names
47                         switch t.Kind() {
48                         case types.Byte:
49                                 t = types.Typ[types.Uint8]
50                         case types.Rune:
51                                 t = types.Typ[types.Int32]
52                         }
53                 }
54                 p.print(t.Name())
55
56         case *types.Array:
57                 p.printf("[%d]", t.Len())
58                 p.writeTypeInternal(this, t.Elem(), visited)
59
60         case *types.Slice:
61                 p.print("[]")
62                 p.writeTypeInternal(this, t.Elem(), visited)
63
64         case *types.Struct:
65                 n := t.NumFields()
66                 if n == 0 {
67                         p.print("struct{}")
68                         return
69                 }
70
71                 p.print("struct {\n")
72                 p.indent++
73                 for i := 0; i < n; i++ {
74                         f := t.Field(i)
75                         if !f.Anonymous() {
76                                 p.printf("%s ", f.Name())
77                         }
78                         p.writeTypeInternal(this, f.Type(), visited)
79                         if tag := t.Tag(i); tag != "" {
80                                 p.printf(" %q", tag)
81                         }
82                         p.print("\n")
83                 }
84                 p.indent--
85                 p.print("}")
86
87         case *types.Pointer:
88                 p.print("*")
89                 p.writeTypeInternal(this, t.Elem(), visited)
90
91         case *types.Tuple:
92                 p.writeTuple(this, t, false, visited)
93
94         case *types.Signature:
95                 p.print("func")
96                 p.writeSignatureInternal(this, t, visited)
97
98         case *types.Interface:
99                 // We write the source-level methods and embedded types rather
100                 // than the actual method set since resolved method signatures
101                 // may have non-printable cycles if parameters have anonymous
102                 // interface types that (directly or indirectly) embed the
103                 // current interface. For instance, consider the result type
104                 // of m:
105                 //
106                 //     type T interface{
107                 //         m() interface{ T }
108                 //     }
109                 //
110                 n := t.NumMethods()
111                 if n == 0 {
112                         p.print("interface{}")
113                         return
114                 }
115
116                 p.print("interface {\n")
117                 p.indent++
118                 if GcCompatibilityMode {
119                         // print flattened interface
120                         // (useful to compare against gc-generated interfaces)
121                         for i := 0; i < n; i++ {
122                                 m := t.Method(i)
123                                 p.print(m.Name())
124                                 p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
125                                 p.print("\n")
126                         }
127                 } else {
128                         // print explicit interface methods and embedded types
129                         for i, n := 0, t.NumExplicitMethods(); i < n; i++ {
130                                 m := t.ExplicitMethod(i)
131                                 p.print(m.Name())
132                                 p.writeSignatureInternal(this, m.Type().(*types.Signature), visited)
133                                 p.print("\n")
134                         }
135                         for i, n := 0, t.NumEmbeddeds(); i < n; i++ {
136                                 typ := t.EmbeddedType(i)
137                                 p.writeTypeInternal(this, typ, visited)
138                                 p.print("\n")
139                         }
140                 }
141                 p.indent--
142                 p.print("}")
143
144         case *types.Map:
145                 p.print("map[")
146                 p.writeTypeInternal(this, t.Key(), visited)
147                 p.print("]")
148                 p.writeTypeInternal(this, t.Elem(), visited)
149
150         case *types.Chan:
151                 var s string
152                 var parens bool
153                 switch t.Dir() {
154                 case types.SendRecv:
155                         s = "chan "
156                         // chan (<-chan T) requires parentheses
157                         if c, _ := t.Elem().(*types.Chan); c != nil && c.Dir() == types.RecvOnly {
158                                 parens = true
159                         }
160                 case types.SendOnly:
161                         s = "chan<- "
162                 case types.RecvOnly:
163                         s = "<-chan "
164                 default:
165                         panic("unreachable")
166                 }
167                 p.print(s)
168                 if parens {
169                         p.print("(")
170                 }
171                 p.writeTypeInternal(this, t.Elem(), visited)
172                 if parens {
173                         p.print(")")
174                 }
175
176         case *types.Named:
177                 s := "<Named w/o object>"
178                 if obj := t.Obj(); obj != nil {
179                         if pkg := obj.Pkg(); pkg != nil {
180                                 if pkg != this {
181                                         p.print(pkg.Path())
182                                         p.print(".")
183                                 }
184                                 // TODO(gri): function-local named types should be displayed
185                                 // differently from named types at package level to avoid
186                                 // ambiguity.
187                         }
188                         s = obj.Name()
189                 }
190                 p.print(s)
191
192         default:
193                 // For externally defined implementations of Type.
194                 p.print(t.String())
195         }
196 }
197
198 func (p *printer) writeTuple(this *types.Package, tup *types.Tuple, variadic bool, visited []types.Type) {
199         p.print("(")
200         for i, n := 0, tup.Len(); i < n; i++ {
201                 if i > 0 {
202                         p.print(", ")
203                 }
204                 v := tup.At(i)
205                 if name := v.Name(); name != "" {
206                         p.print(name)
207                         p.print(" ")
208                 }
209                 typ := v.Type()
210                 if variadic && i == n-1 {
211                         p.print("...")
212                         typ = typ.(*types.Slice).Elem()
213                 }
214                 p.writeTypeInternal(this, typ, visited)
215         }
216         p.print(")")
217 }
218
219 func (p *printer) writeSignature(this *types.Package, sig *types.Signature) {
220         p.writeSignatureInternal(this, sig, make([]types.Type, 8))
221 }
222
223 func (p *printer) writeSignatureInternal(this *types.Package, sig *types.Signature, visited []types.Type) {
224         p.writeTuple(this, sig.Params(), sig.Variadic(), visited)
225
226         res := sig.Results()
227         n := res.Len()
228         if n == 0 {
229                 // no result
230                 return
231         }
232
233         p.print(" ")
234         if n == 1 && res.At(0).Name() == "" {
235                 // single unnamed result
236                 p.writeTypeInternal(this, res.At(0).Type(), visited)
237                 return
238         }
239
240         // multiple or named result(s)
241         p.writeTuple(this, res, false, visited)
242 }