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 / completion / completion_builtin.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 completion
6
7 import (
8         "context"
9         "go/ast"
10         "go/types"
11 )
12
13 // builtinArgKind determines the expected object kind for a builtin
14 // argument. It attempts to use the AST hints from builtin.go where
15 // possible.
16 func (c *completer) builtinArgKind(ctx context.Context, obj types.Object, call *ast.CallExpr) objKind {
17         builtin, err := c.snapshot.BuiltinPackage(ctx)
18         if err != nil {
19                 return 0
20         }
21         exprIdx := exprAtPos(c.pos, call.Args)
22
23         builtinObj := builtin.Package.Scope.Lookup(obj.Name())
24         if builtinObj == nil {
25                 return 0
26         }
27         decl, ok := builtinObj.Decl.(*ast.FuncDecl)
28         if !ok || exprIdx >= len(decl.Type.Params.List) {
29                 return 0
30         }
31
32         switch ptyp := decl.Type.Params.List[exprIdx].Type.(type) {
33         case *ast.ChanType:
34                 return kindChan
35         case *ast.ArrayType:
36                 return kindSlice
37         case *ast.MapType:
38                 return kindMap
39         case *ast.Ident:
40                 switch ptyp.Name {
41                 case "Type":
42                         switch obj.Name() {
43                         case "make":
44                                 return kindChan | kindSlice | kindMap
45                         case "len":
46                                 return kindSlice | kindMap | kindArray | kindString | kindChan
47                         case "cap":
48                                 return kindSlice | kindArray | kindChan
49                         }
50                 }
51         }
52
53         return 0
54 }
55
56 // builtinArgType infers the type of an argument to a builtin
57 // function. parentInf is the inferred type info for the builtin
58 // call's parent node.
59 func (c *completer) builtinArgType(obj types.Object, call *ast.CallExpr, parentInf candidateInference) candidateInference {
60         var (
61                 exprIdx = exprAtPos(c.pos, call.Args)
62
63                 // Propagate certain properties from our parent's inference.
64                 inf = candidateInference{
65                         typeName:  parentInf.typeName,
66                         modifiers: parentInf.modifiers,
67                 }
68         )
69
70         switch obj.Name() {
71         case "append":
72                 if parentInf.objType == nil {
73                         break
74                 }
75
76                 inf.objType = parentInf.objType
77
78                 if exprIdx <= 0 {
79                         break
80                 }
81
82                 inf.objType = deslice(inf.objType)
83
84                 // Check if we are completing the variadic append() param.
85                 inf.variadic = exprIdx == 1 && len(call.Args) <= 2
86
87                 // Penalize the first append() argument as a candidate. You
88                 // don't normally append a slice to itself.
89                 if sliceChain := objChain(c.pkg.GetTypesInfo(), call.Args[0]); len(sliceChain) > 0 {
90                         inf.penalized = append(inf.penalized, penalizedObj{objChain: sliceChain, penalty: 0.9})
91                 }
92         case "delete":
93                 if exprIdx > 0 && len(call.Args) > 0 {
94                         // Try to fill in expected type of map key.
95                         firstArgType := c.pkg.GetTypesInfo().TypeOf(call.Args[0])
96                         if firstArgType != nil {
97                                 if mt, ok := firstArgType.Underlying().(*types.Map); ok {
98                                         inf.objType = mt.Key()
99                                 }
100                         }
101                 }
102         case "copy":
103                 var t1, t2 types.Type
104                 if len(call.Args) > 0 {
105                         t1 = c.pkg.GetTypesInfo().TypeOf(call.Args[0])
106                         if len(call.Args) > 1 {
107                                 t2 = c.pkg.GetTypesInfo().TypeOf(call.Args[1])
108                         }
109                 }
110
111                 // Fill in expected type of either arg if the other is already present.
112                 if exprIdx == 1 && t1 != nil {
113                         inf.objType = t1
114                 } else if exprIdx == 0 && t2 != nil {
115                         inf.objType = t2
116                 }
117         case "new":
118                 inf.typeName.wantTypeName = true
119                 if parentInf.objType != nil {
120                         // Expected type for "new" is the de-pointered parent type.
121                         if ptr, ok := parentInf.objType.Underlying().(*types.Pointer); ok {
122                                 inf.objType = ptr.Elem()
123                         }
124                 }
125         case "make":
126                 if exprIdx == 0 {
127                         inf.typeName.wantTypeName = true
128                         inf.objType = parentInf.objType
129                 } else {
130                         inf.objType = types.Typ[types.Int]
131                 }
132         }
133
134         return inf
135 }