Update .bashrc
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.0 / go / pointer / labels.go
1 // Copyright 2013 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 package pointer
6
7 import (
8         "fmt"
9         "go/token"
10         "go/types"
11         "strings"
12
13         "golang.org/x/tools/go/ssa"
14 )
15
16 // A Label is an entity that may be pointed to by a pointer, map,
17 // channel, 'func', slice or interface.
18 //
19 // Labels include:
20 //      - functions
21 //      - globals
22 //      - tagged objects, representing interfaces and reflect.Values
23 //      - arrays created by conversions (e.g. []byte("foo"), []byte(s))
24 //      - stack- and heap-allocated variables (including composite literals)
25 //      - channels, maps and arrays created by make()
26 //      - intrinsic or reflective operations that allocate (e.g. append, reflect.New)
27 //      - intrinsic objects, e.g. the initial array behind os.Args.
28 //      - and their subelements, e.g. "alloc.y[*].z"
29 //
30 // Labels are so varied that they defy good generalizations;
31 // some have no value, no callgraph node, or no position.
32 // Many objects have types that are inexpressible in Go:
33 // maps, channels, functions, tagged objects.
34 //
35 // At most one of Value() or ReflectType() may return non-nil.
36 //
37 type Label struct {
38         obj        *object    // the addressable memory location containing this label
39         subelement *fieldInfo // subelement path within obj, e.g. ".a.b[*].c"
40 }
41
42 // Value returns the ssa.Value that allocated this label's object, if any.
43 func (l Label) Value() ssa.Value {
44         val, _ := l.obj.data.(ssa.Value)
45         return val
46 }
47
48 // ReflectType returns the type represented by this label if it is an
49 // reflect.rtype instance object or *reflect.rtype-tagged object.
50 //
51 func (l Label) ReflectType() types.Type {
52         rtype, _ := l.obj.data.(types.Type)
53         return rtype
54 }
55
56 // Path returns the path to the subelement of the object containing
57 // this label.  For example, ".x[*].y".
58 //
59 func (l Label) Path() string {
60         return l.subelement.path()
61 }
62
63 // Pos returns the position of this label, if known, zero otherwise.
64 func (l Label) Pos() token.Pos {
65         switch data := l.obj.data.(type) {
66         case ssa.Value:
67                 return data.Pos()
68         case types.Type:
69                 if nt, ok := deref(data).(*types.Named); ok {
70                         return nt.Obj().Pos()
71                 }
72         }
73         if cgn := l.obj.cgn; cgn != nil {
74                 return cgn.fn.Pos()
75         }
76         return token.NoPos
77 }
78
79 // String returns the printed form of this label.
80 //
81 // Examples:                                    Object type:
82 //      x                                       (a variable)
83 //      (sync.Mutex).Lock                       (a function)
84 //      convert                                 (array created by conversion)
85 //      makemap                                 (map allocated via make)
86 //      makechan                                (channel allocated via make)
87 //      makeinterface                           (tagged object allocated by makeinterface)
88 //      <alloc in reflect.Zero>                 (allocation in instrinsic)
89 //      sync.Mutex                              (a reflect.rtype instance)
90 //      <command-line arguments>                (an intrinsic object)
91 //
92 // Labels within compound objects have subelement paths:
93 //      x.y[*].z                                (a struct variable, x)
94 //      append.y[*].z                           (array allocated by append)
95 //      makeslice.y[*].z                        (array allocated via make)
96 //
97 // TODO(adonovan): expose func LabelString(*types.Package, Label).
98 //
99 func (l Label) String() string {
100         var s string
101         switch v := l.obj.data.(type) {
102         case types.Type:
103                 return v.String()
104
105         case string:
106                 s = v // an intrinsic object (e.g. os.Args[*])
107
108         case nil:
109                 if l.obj.cgn != nil {
110                         // allocation by intrinsic or reflective operation
111                         s = fmt.Sprintf("<alloc in %s>", l.obj.cgn.fn)
112                 } else {
113                         s = "<unknown>" // should be unreachable
114                 }
115
116         case *ssa.Function:
117                 s = v.String()
118
119         case *ssa.Global:
120                 s = v.String()
121
122         case *ssa.Const:
123                 s = v.Name()
124
125         case *ssa.Alloc:
126                 s = v.Comment
127                 if s == "" {
128                         s = "alloc"
129                 }
130
131         case *ssa.Call:
132                 // Currently only calls to append can allocate objects.
133                 if v.Call.Value.(*ssa.Builtin).Object().Name() != "append" {
134                         panic("unhandled *ssa.Call label: " + v.Name())
135                 }
136                 s = "append"
137
138         case *ssa.MakeMap, *ssa.MakeChan, *ssa.MakeSlice, *ssa.Convert:
139                 s = strings.ToLower(strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa."))
140
141         case *ssa.MakeInterface:
142                 // MakeInterface is usually implicit in Go source (so
143                 // Pos()==0), and tagged objects may be allocated
144                 // synthetically (so no *MakeInterface data).
145                 s = "makeinterface:" + v.X.Type().String()
146
147         default:
148                 panic(fmt.Sprintf("unhandled object data type: %T", v))
149         }
150
151         return s + l.subelement.path()
152 }