GoPLS Viewer

Home|gopls/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
13package main
14
15import "go/types"
16
17func (p *printerwriteType(this *types.Packagetyp types.Type) {
18    p.writeTypeInternal(thistypmake([]types.Type8))
19}
20
21// From go/types - leave for now to ease back-porting this code.
22const GcCompatibilityMode = false
23
24func (p *printerwriteTypeInternal(this *types.Packagetyp types.Typevisited []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(visitedtyp)
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(thist.Elem(), visited)
59
60    case *types.Slice:
61        p.print("[]")
62        p.writeTypeInternal(thist.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 := 0i < ni++ {
74            f := t.Field(i)
75            if !f.Anonymous() {
76                p.printf("%s "f.Name())
77            }
78            p.writeTypeInternal(thisf.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(thist.Elem(), visited)
90
91    case *types.Tuple:
92        p.writeTuple(thistfalsevisited)
93
94    case *types.Signature:
95        p.print("func")
96        p.writeSignatureInternal(thistvisited)
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 := 0i < ni++ {
122                m := t.Method(i)
123                p.print(m.Name())
124                p.writeSignatureInternal(thism.Type().(*types.Signature), visited)
125                p.print("\n")
126            }
127        } else {
128            // print explicit interface methods and embedded types
129            for in := 0t.NumExplicitMethods(); i < ni++ {
130                m := t.ExplicitMethod(i)
131                p.print(m.Name())
132                p.writeSignatureInternal(thism.Type().(*types.Signature), visited)
133                p.print("\n")
134            }
135            for in := 0t.NumEmbeddeds(); i < ni++ {
136                typ := t.EmbeddedType(i)
137                p.writeTypeInternal(thistypvisited)
138                p.print("\n")
139            }
140        }
141        p.indent--
142        p.print("}")
143
144    case *types.Map:
145        p.print("map[")
146        p.writeTypeInternal(thist.Key(), visited)
147        p.print("]")
148        p.writeTypeInternal(thist.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(thist.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
198func (p *printerwriteTuple(this *types.Packagetup *types.Tuplevariadic boolvisited []types.Type) {
199    p.print("(")
200    for in := 0tup.Len(); i < ni++ {
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(thistypvisited)
215    }
216    p.print(")")
217}
218
219func (p *printerwriteSignature(this *types.Packagesig *types.Signature) {
220    p.writeSignatureInternal(thissigmake([]types.Type8))
221}
222
223func (p *printerwriteSignatureInternal(this *types.Packagesig *types.Signaturevisited []types.Type) {
224    p.writeTuple(thissig.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(thisres.At(0).Type(), visited)
237        return
238    }
239
240    // multiple or named result(s)
241    p.writeTuple(thisresfalsevisited)
242}
243
MembersX
printer.writeTuple.tup
printer.writeTuple.BlockStmt.name
printer.writeSignature
printer.writeType.this
printer.writeTypeInternal
printer.writeTypeInternal.visited
printer.writeTypeInternal.BlockStmt.n
printer.writeTypeInternal.BlockStmt.BlockStmt.i
printer.writeTypeInternal.BlockStmt.BlockStmt.BlockStmt.m
printer.writeTypeInternal.BlockStmt.obj
printer.writeSignatureInternal
printer.writeSignatureInternal.res
printer.writeSignatureInternal.n
GcCompatibilityMode
printer.writeTuple.this
printer.writeSignatureInternal.sig
printer.writeTypeInternal.p
printer.writeTypeInternal.BlockStmt.BlockStmt.tag
printer.writeTuple.variadic
printer.writeTuple.BlockStmt.v
printer.writeSignatureInternal.this
printer.writeType.typ
printer.writeTypeInternal.BlockStmt.BlockStmt.f
printer.writeTuple.n
printer.writeSignatureInternal.p
printer.writeSignatureInternal.visited
printer.writeTuple.visited
printer.writeSignature.p
printer.writeSignature.this
printer.writeType.p
printer.writeType
printer.writeTypeInternal.BlockStmt.i
printer.writeTypeInternal.BlockStmt.BlockStmt.n
printer.writeTuple.p
printer.writeTuple.BlockStmt.typ
printer.writeTypeInternal.RangeStmt_1062.t
printer.writeTypeInternal.BlockStmt.parens
printer.writeTypeInternal.BlockStmt.BlockStmt.pkg
printer.writeTuple
printer.writeTuple.i
printer.writeTypeInternal.this
printer.writeTypeInternal.typ
printer.writeTypeInternal.BlockStmt.BlockStmt.BlockStmt.typ
printer.writeTypeInternal.BlockStmt.s
printer.writeSignature.sig
Members
X