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 / types_format.go
1 // Copyright 2020 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         "bytes"
9         "context"
10         "fmt"
11         "go/ast"
12         "go/printer"
13         "go/token"
14         "go/types"
15         "strings"
16
17         "golang.org/x/tools/internal/event"
18         "golang.org/x/tools/internal/lsp/debug/tag"
19         "golang.org/x/tools/internal/lsp/protocol"
20 )
21
22 // FormatType returns the detail and kind for a types.Type.
23 func FormatType(typ types.Type, qf types.Qualifier) (detail string, kind protocol.CompletionItemKind) {
24         if types.IsInterface(typ) {
25                 detail = "interface{...}"
26                 kind = protocol.InterfaceCompletion
27         } else if _, ok := typ.(*types.Struct); ok {
28                 detail = "struct{...}"
29                 kind = protocol.StructCompletion
30         } else if typ != typ.Underlying() {
31                 detail, kind = FormatType(typ.Underlying(), qf)
32         } else {
33                 detail = types.TypeString(typ, qf)
34                 kind = protocol.ClassCompletion
35         }
36         return detail, kind
37 }
38
39 type signature struct {
40         name, doc        string
41         params, results  []string
42         variadic         bool
43         needResultParens bool
44 }
45
46 func (s *signature) Format() string {
47         var b strings.Builder
48         b.WriteByte('(')
49         for i, p := range s.params {
50                 if i > 0 {
51                         b.WriteString(", ")
52                 }
53                 b.WriteString(p)
54         }
55         b.WriteByte(')')
56
57         // Add space between parameters and results.
58         if len(s.results) > 0 {
59                 b.WriteByte(' ')
60         }
61         if s.needResultParens {
62                 b.WriteByte('(')
63         }
64         for i, r := range s.results {
65                 if i > 0 {
66                         b.WriteString(", ")
67                 }
68                 b.WriteString(r)
69         }
70         if s.needResultParens {
71                 b.WriteByte(')')
72         }
73         return b.String()
74 }
75
76 func (s *signature) Params() []string {
77         return s.params
78 }
79
80 // NewBuiltinSignature returns signature for the builtin object with a given
81 // name, if a builtin object with the name exists.
82 func NewBuiltinSignature(ctx context.Context, snapshot Snapshot, name string) (*signature, error) {
83         builtin, err := snapshot.BuiltinPackage(ctx)
84         if err != nil {
85                 return nil, err
86         }
87         obj := builtin.Package.Scope.Lookup(name)
88         if obj == nil {
89                 return nil, fmt.Errorf("no builtin object for %s", name)
90         }
91         decl, ok := obj.Decl.(*ast.FuncDecl)
92         if !ok {
93                 return nil, fmt.Errorf("no function declaration for builtin: %s", name)
94         }
95         if decl.Type == nil {
96                 return nil, fmt.Errorf("no type for builtin decl %s", decl.Name)
97         }
98         var variadic bool
99         if decl.Type.Params.List != nil {
100                 numParams := len(decl.Type.Params.List)
101                 lastParam := decl.Type.Params.List[numParams-1]
102                 if _, ok := lastParam.Type.(*ast.Ellipsis); ok {
103                         variadic = true
104                 }
105         }
106         params, _ := formatFieldList(ctx, snapshot, decl.Type.Params, variadic)
107         results, needResultParens := formatFieldList(ctx, snapshot, decl.Type.Results, false)
108         return &signature{
109                 doc:              decl.Doc.Text(),
110                 name:             name,
111                 needResultParens: needResultParens,
112                 params:           params,
113                 results:          results,
114                 variadic:         variadic,
115         }, nil
116 }
117
118 var replacer = strings.NewReplacer(
119         `ComplexType`, `complex128`,
120         `FloatType`, `float64`,
121         `IntegerType`, `int`,
122 )
123
124 func formatFieldList(ctx context.Context, snapshot Snapshot, list *ast.FieldList, variadic bool) ([]string, bool) {
125         if list == nil {
126                 return nil, false
127         }
128         var writeResultParens bool
129         var result []string
130         for i := 0; i < len(list.List); i++ {
131                 if i >= 1 {
132                         writeResultParens = true
133                 }
134                 p := list.List[i]
135                 cfg := printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 4}
136                 b := &bytes.Buffer{}
137                 if err := cfg.Fprint(b, snapshot.FileSet(), p.Type); err != nil {
138                         event.Error(ctx, "unable to print type", nil, tag.Type.Of(p.Type))
139                         continue
140                 }
141                 typ := replacer.Replace(b.String())
142                 if len(p.Names) == 0 {
143                         result = append(result, typ)
144                 }
145                 for _, name := range p.Names {
146                         if name.Name != "" {
147                                 if i == 0 {
148                                         writeResultParens = true
149                                 }
150                                 result = append(result, fmt.Sprintf("%s %s", name.Name, typ))
151                         } else {
152                                 result = append(result, typ)
153                         }
154                 }
155         }
156         if variadic {
157                 result[len(result)-1] = strings.Replace(result[len(result)-1], "[]", "...", 1)
158         }
159         return result, writeResultParens
160 }
161
162 // NewSignature returns formatted signature for a types.Signature struct.
163 func NewSignature(ctx context.Context, s Snapshot, pkg Package, sig *types.Signature, comment *ast.CommentGroup, qf types.Qualifier) *signature {
164         params := make([]string, 0, sig.Params().Len())
165         for i := 0; i < sig.Params().Len(); i++ {
166                 el := sig.Params().At(i)
167                 typ := FormatVarType(ctx, s, pkg, el, qf)
168                 p := typ
169                 if el.Name() != "" {
170                         p = el.Name() + " " + typ
171                 }
172                 params = append(params, p)
173         }
174         var needResultParens bool
175         results := make([]string, 0, sig.Results().Len())
176         for i := 0; i < sig.Results().Len(); i++ {
177                 if i >= 1 {
178                         needResultParens = true
179                 }
180                 el := sig.Results().At(i)
181                 typ := FormatVarType(ctx, s, pkg, el, qf)
182                 if el.Name() == "" {
183                         results = append(results, typ)
184                 } else {
185                         if i == 0 {
186                                 needResultParens = true
187                         }
188                         results = append(results, el.Name()+" "+typ)
189                 }
190         }
191         var doc string
192         if comment != nil {
193                 doc = comment.Text()
194         }
195         return &signature{
196                 doc:              doc,
197                 params:           params,
198                 results:          results,
199                 variadic:         sig.Variadic(),
200                 needResultParens: needResultParens,
201         }
202 }
203
204 // FormatVarType formats a *types.Var, accounting for type aliases.
205 // To do this, it looks in the AST of the file in which the object is declared.
206 // On any errors, it always fallbacks back to types.TypeString.
207 func FormatVarType(ctx context.Context, snapshot Snapshot, srcpkg Package, obj *types.Var, qf types.Qualifier) string {
208         pgf, pkg, err := FindPosInPackage(snapshot, srcpkg, obj.Pos())
209         if err != nil {
210                 return types.TypeString(obj.Type(), qf)
211         }
212
213         expr, err := varType(ctx, snapshot, pgf, obj)
214         if err != nil {
215                 return types.TypeString(obj.Type(), qf)
216         }
217
218         // The type names in the AST may not be correctly qualified.
219         // Determine the package name to use based on the package that originated
220         // the query and the package in which the type is declared.
221         // We then qualify the value by cloning the AST node and editing it.
222         clonedInfo := make(map[token.Pos]*types.PkgName)
223         qualified := cloneExpr(expr, pkg.GetTypesInfo(), clonedInfo)
224
225         // If the request came from a different package than the one in which the
226         // types are defined, we may need to modify the qualifiers.
227         qualified = qualifyExpr(qualified, srcpkg, pkg, clonedInfo, qf)
228         fmted := FormatNode(snapshot.FileSet(), qualified)
229         return fmted
230 }
231
232 // varType returns the type expression for a *types.Var.
233 func varType(ctx context.Context, snapshot Snapshot, pgf *ParsedGoFile, obj *types.Var) (ast.Expr, error) {
234         posToField, err := snapshot.PosToField(ctx, pgf)
235         if err != nil {
236                 return nil, err
237         }
238         field := posToField[obj.Pos()]
239         if field == nil {
240                 return nil, fmt.Errorf("no declaration for object %s", obj.Name())
241         }
242         typ, ok := field.Type.(ast.Expr)
243         if !ok {
244                 return nil, fmt.Errorf("unexpected type for node (%T)", field.Type)
245         }
246         return typ, nil
247 }
248
249 // qualifyExpr applies the "pkgName." prefix to any *ast.Ident in the expr.
250 func qualifyExpr(expr ast.Expr, srcpkg, pkg Package, clonedInfo map[token.Pos]*types.PkgName, qf types.Qualifier) ast.Expr {
251         ast.Inspect(expr, func(n ast.Node) bool {
252                 switch n := n.(type) {
253                 case *ast.ArrayType, *ast.ChanType, *ast.Ellipsis,
254                         *ast.FuncType, *ast.MapType, *ast.ParenExpr,
255                         *ast.StarExpr, *ast.StructType:
256                         // These are the only types that are cloned by cloneExpr below,
257                         // so these are the only types that we can traverse and potentially
258                         // modify. This is not an ideal approach, but it works for now.
259                         return true
260                 case *ast.SelectorExpr:
261                         // We may need to change any selectors in which the X is a package
262                         // name and the Sel is exported.
263                         x, ok := n.X.(*ast.Ident)
264                         if !ok {
265                                 return false
266                         }
267                         obj, ok := clonedInfo[x.Pos()]
268                         if !ok {
269                                 return false
270                         }
271                         pkgName := qf(obj.Imported())
272                         if pkgName != "" {
273                                 x.Name = pkgName
274                         }
275                         return false
276                 case *ast.Ident:
277                         if srcpkg == pkg {
278                                 return false
279                         }
280                         // Only add the qualifier if the identifier is exported.
281                         if ast.IsExported(n.Name) {
282                                 pkgName := qf(pkg.GetTypes())
283                                 n.Name = pkgName + "." + n.Name
284                         }
285                 }
286                 return false
287         })
288         return expr
289 }
290
291 // cloneExpr only clones expressions that appear in the parameters or return
292 // values of a function declaration. The original expression may be returned
293 // to the caller in 2 cases:
294 //    (1) The expression has no pointer fields.
295 //    (2) The expression cannot appear in an *ast.FuncType, making it
296 //        unnecessary to clone.
297 // This function also keeps track of selector expressions in which the X is a
298 // package name and marks them in a map along with their type information, so
299 // that this information can be used when rewriting the expression.
300 //
301 // NOTE: This function is tailored to the use case of qualifyExpr, and should
302 // be used with caution.
303 func cloneExpr(expr ast.Expr, info *types.Info, clonedInfo map[token.Pos]*types.PkgName) ast.Expr {
304         switch expr := expr.(type) {
305         case *ast.ArrayType:
306                 return &ast.ArrayType{
307                         Lbrack: expr.Lbrack,
308                         Elt:    cloneExpr(expr.Elt, info, clonedInfo),
309                         Len:    expr.Len,
310                 }
311         case *ast.ChanType:
312                 return &ast.ChanType{
313                         Arrow: expr.Arrow,
314                         Begin: expr.Begin,
315                         Dir:   expr.Dir,
316                         Value: cloneExpr(expr.Value, info, clonedInfo),
317                 }
318         case *ast.Ellipsis:
319                 return &ast.Ellipsis{
320                         Ellipsis: expr.Ellipsis,
321                         Elt:      cloneExpr(expr.Elt, info, clonedInfo),
322                 }
323         case *ast.FuncType:
324                 return &ast.FuncType{
325                         Func:    expr.Func,
326                         Params:  cloneFieldList(expr.Params, info, clonedInfo),
327                         Results: cloneFieldList(expr.Results, info, clonedInfo),
328                 }
329         case *ast.Ident:
330                 return cloneIdent(expr)
331         case *ast.MapType:
332                 return &ast.MapType{
333                         Map:   expr.Map,
334                         Key:   cloneExpr(expr.Key, info, clonedInfo),
335                         Value: cloneExpr(expr.Value, info, clonedInfo),
336                 }
337         case *ast.ParenExpr:
338                 return &ast.ParenExpr{
339                         Lparen: expr.Lparen,
340                         Rparen: expr.Rparen,
341                         X:      cloneExpr(expr.X, info, clonedInfo),
342                 }
343         case *ast.SelectorExpr:
344                 s := &ast.SelectorExpr{
345                         Sel: cloneIdent(expr.Sel),
346                         X:   cloneExpr(expr.X, info, clonedInfo),
347                 }
348                 if x, ok := expr.X.(*ast.Ident); ok && ast.IsExported(expr.Sel.Name) {
349                         if obj, ok := info.ObjectOf(x).(*types.PkgName); ok {
350                                 clonedInfo[s.X.Pos()] = obj
351                         }
352                 }
353                 return s
354         case *ast.StarExpr:
355                 return &ast.StarExpr{
356                         Star: expr.Star,
357                         X:    cloneExpr(expr.X, info, clonedInfo),
358                 }
359         case *ast.StructType:
360                 return &ast.StructType{
361                         Struct:     expr.Struct,
362                         Fields:     cloneFieldList(expr.Fields, info, clonedInfo),
363                         Incomplete: expr.Incomplete,
364                 }
365         default:
366                 return expr
367         }
368 }
369
370 func cloneFieldList(fl *ast.FieldList, info *types.Info, clonedInfo map[token.Pos]*types.PkgName) *ast.FieldList {
371         if fl == nil {
372                 return nil
373         }
374         if fl.List == nil {
375                 return &ast.FieldList{
376                         Closing: fl.Closing,
377                         Opening: fl.Opening,
378                 }
379         }
380         list := make([]*ast.Field, 0, len(fl.List))
381         for _, f := range fl.List {
382                 var names []*ast.Ident
383                 for _, n := range f.Names {
384                         names = append(names, cloneIdent(n))
385                 }
386                 list = append(list, &ast.Field{
387                         Comment: f.Comment,
388                         Doc:     f.Doc,
389                         Names:   names,
390                         Tag:     f.Tag,
391                         Type:    cloneExpr(f.Type, info, clonedInfo),
392                 })
393         }
394         return &ast.FieldList{
395                 Closing: fl.Closing,
396                 Opening: fl.Opening,
397                 List:    list,
398         }
399 }
400
401 func cloneIdent(ident *ast.Ident) *ast.Ident {
402         return &ast.Ident{
403                 NamePos: ident.NamePos,
404                 Name:    ident.Name,
405                 Obj:     ident.Obj,
406         }
407 }