Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / source / symbols.go
1 // Copyright 2019 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 source
6
7 import (
8         "context"
9         "fmt"
10         "go/ast"
11         "go/types"
12
13         "golang.org/x/tools/internal/event"
14         "golang.org/x/tools/internal/lsp/protocol"
15         errors "golang.org/x/xerrors"
16 )
17
18 func DocumentSymbols(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.DocumentSymbol, error) {
19         ctx, done := event.Start(ctx, "source.DocumentSymbols")
20         defer done()
21
22         pkg, pgf, err := GetParsedFile(ctx, snapshot, fh, NarrowestPackage)
23         if err != nil {
24                 return nil, errors.Errorf("getting file for DocumentSymbols: %w", err)
25         }
26
27         info := pkg.GetTypesInfo()
28         q := Qualifier(pgf.File, pkg.GetTypes(), info)
29
30         symbolsToReceiver := make(map[types.Type]int)
31         var symbols []protocol.DocumentSymbol
32         for _, decl := range pgf.File.Decls {
33                 switch decl := decl.(type) {
34                 case *ast.FuncDecl:
35                         if decl.Name.Name == "_" {
36                                 continue
37                         }
38                         if obj := info.ObjectOf(decl.Name); obj != nil {
39                                 fs, err := funcSymbol(snapshot, pkg, decl, obj, q)
40                                 if err != nil {
41                                         return nil, err
42                                 }
43                                 // If function is a method, prepend the type of the method.
44                                 if fs.Kind == protocol.Method {
45                                         rtype := obj.Type().(*types.Signature).Recv().Type()
46                                         fs.Name = fmt.Sprintf("(%s).%s", types.TypeString(rtype, q), fs.Name)
47                                 }
48                                 symbols = append(symbols, fs)
49                         }
50                 case *ast.GenDecl:
51                         for _, spec := range decl.Specs {
52                                 switch spec := spec.(type) {
53                                 case *ast.TypeSpec:
54                                         if spec.Name.Name == "_" {
55                                                 continue
56                                         }
57                                         if obj := info.ObjectOf(spec.Name); obj != nil {
58                                                 ts, err := typeSymbol(snapshot, pkg, info, spec, obj, q)
59                                                 if err != nil {
60                                                         return nil, err
61                                                 }
62                                                 symbols = append(symbols, ts)
63                                                 symbolsToReceiver[obj.Type()] = len(symbols) - 1
64                                         }
65                                 case *ast.ValueSpec:
66                                         for _, name := range spec.Names {
67                                                 if name.Name == "_" {
68                                                         continue
69                                                 }
70                                                 if obj := info.ObjectOf(name); obj != nil {
71                                                         vs, err := varSymbol(snapshot, pkg, decl, name, obj, q)
72                                                         if err != nil {
73                                                                 return nil, err
74                                                         }
75                                                         symbols = append(symbols, vs)
76                                                 }
77                                         }
78                                 }
79                         }
80                 }
81         }
82         return symbols, nil
83 }
84
85 func funcSymbol(snapshot Snapshot, pkg Package, decl *ast.FuncDecl, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
86         s := protocol.DocumentSymbol{
87                 Name: obj.Name(),
88                 Kind: protocol.Function,
89         }
90         var err error
91         s.Range, err = nodeToProtocolRange(snapshot, pkg, decl)
92         if err != nil {
93                 return protocol.DocumentSymbol{}, err
94         }
95         s.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, decl.Name)
96         if err != nil {
97                 return protocol.DocumentSymbol{}, err
98         }
99         sig, _ := obj.Type().(*types.Signature)
100         if sig != nil {
101                 if sig.Recv() != nil {
102                         s.Kind = protocol.Method
103                 }
104                 s.Detail += "("
105                 for i := 0; i < sig.Params().Len(); i++ {
106                         if i > 0 {
107                                 s.Detail += ", "
108                         }
109                         param := sig.Params().At(i)
110                         label := types.TypeString(param.Type(), q)
111                         if param.Name() != "" {
112                                 label = fmt.Sprintf("%s %s", param.Name(), label)
113                         }
114                         s.Detail += label
115                 }
116                 s.Detail += ")"
117         }
118         return s, nil
119 }
120
121 func typeSymbol(snapshot Snapshot, pkg Package, info *types.Info, spec *ast.TypeSpec, obj types.Object, qf types.Qualifier) (protocol.DocumentSymbol, error) {
122         s := protocol.DocumentSymbol{
123                 Name: obj.Name(),
124         }
125         s.Detail, _ = FormatType(obj.Type(), qf)
126         s.Kind = typeToKind(obj.Type())
127
128         var err error
129         s.Range, err = nodeToProtocolRange(snapshot, pkg, spec)
130         if err != nil {
131                 return protocol.DocumentSymbol{}, err
132         }
133         s.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, spec.Name)
134         if err != nil {
135                 return protocol.DocumentSymbol{}, err
136         }
137         t, objIsStruct := obj.Type().Underlying().(*types.Struct)
138         st, specIsStruct := spec.Type.(*ast.StructType)
139         if objIsStruct && specIsStruct {
140                 for i := 0; i < t.NumFields(); i++ {
141                         f := t.Field(i)
142                         child := protocol.DocumentSymbol{
143                                 Name: f.Name(),
144                                 Kind: protocol.Field,
145                         }
146                         child.Detail, _ = FormatType(f.Type(), qf)
147
148                         spanNode, selectionNode := nodesForStructField(i, st)
149                         if span, err := nodeToProtocolRange(snapshot, pkg, spanNode); err == nil {
150                                 child.Range = span
151                         }
152                         if span, err := nodeToProtocolRange(snapshot, pkg, selectionNode); err == nil {
153                                 child.SelectionRange = span
154                         }
155                         s.Children = append(s.Children, child)
156                 }
157         }
158
159         ti, objIsInterface := obj.Type().Underlying().(*types.Interface)
160         ai, specIsInterface := spec.Type.(*ast.InterfaceType)
161         if objIsInterface && specIsInterface {
162                 for i := 0; i < ti.NumExplicitMethods(); i++ {
163                         method := ti.ExplicitMethod(i)
164                         child := protocol.DocumentSymbol{
165                                 Name: method.Name(),
166                                 Kind: protocol.Method,
167                         }
168
169                         var spanNode, selectionNode ast.Node
170                 Methods:
171                         for _, f := range ai.Methods.List {
172                                 for _, id := range f.Names {
173                                         if id.Name == method.Name() {
174                                                 spanNode, selectionNode = f, id
175                                                 break Methods
176                                         }
177                                 }
178                         }
179                         child.Range, err = nodeToProtocolRange(snapshot, pkg, spanNode)
180                         if err != nil {
181                                 return protocol.DocumentSymbol{}, err
182                         }
183                         child.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, selectionNode)
184                         if err != nil {
185                                 return protocol.DocumentSymbol{}, err
186                         }
187                         s.Children = append(s.Children, child)
188                 }
189
190                 for i := 0; i < ti.NumEmbeddeds(); i++ {
191                         embedded := ti.EmbeddedType(i)
192                         nt, isNamed := embedded.(*types.Named)
193                         if !isNamed {
194                                 continue
195                         }
196
197                         child := protocol.DocumentSymbol{
198                                 Name: types.TypeString(embedded, qf),
199                         }
200                         child.Kind = typeToKind(embedded)
201                         var spanNode, selectionNode ast.Node
202                 Embeddeds:
203                         for _, f := range ai.Methods.List {
204                                 if len(f.Names) > 0 {
205                                         continue
206                                 }
207
208                                 if t := info.TypeOf(f.Type); types.Identical(nt, t) {
209                                         spanNode, selectionNode = f, f.Type
210                                         break Embeddeds
211                                 }
212                         }
213                         child.Range, err = nodeToProtocolRange(snapshot, pkg, spanNode)
214                         if err != nil {
215                                 return protocol.DocumentSymbol{}, err
216                         }
217                         child.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, selectionNode)
218                         if err != nil {
219                                 return protocol.DocumentSymbol{}, err
220                         }
221                         s.Children = append(s.Children, child)
222                 }
223         }
224         return s, nil
225 }
226
227 func nodesForStructField(i int, st *ast.StructType) (span, selection ast.Node) {
228         j := 0
229         for _, field := range st.Fields.List {
230                 if len(field.Names) == 0 {
231                         if i == j {
232                                 return field, field.Type
233                         }
234                         j++
235                         continue
236                 }
237                 for _, name := range field.Names {
238                         if i == j {
239                                 return field, name
240                         }
241                         j++
242                 }
243         }
244         return nil, nil
245 }
246
247 func varSymbol(snapshot Snapshot, pkg Package, decl ast.Node, name *ast.Ident, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) {
248         s := protocol.DocumentSymbol{
249                 Name: obj.Name(),
250                 Kind: protocol.Variable,
251         }
252         if _, ok := obj.(*types.Const); ok {
253                 s.Kind = protocol.Constant
254         }
255         var err error
256         s.Range, err = nodeToProtocolRange(snapshot, pkg, decl)
257         if err != nil {
258                 return protocol.DocumentSymbol{}, err
259         }
260         s.SelectionRange, err = nodeToProtocolRange(snapshot, pkg, name)
261         if err != nil {
262                 return protocol.DocumentSymbol{}, err
263         }
264         s.Detail = types.TypeString(obj.Type(), q)
265         return s, nil
266 }