Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / internal / lsp / source / completion / builtin.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/internal/lsp/source/completion/builtin.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/internal/lsp/source/completion/builtin.go
new file mode 100644 (file)
index 0000000..f4137b3
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package completion
+
+import (
+       "context"
+       "go/ast"
+       "go/types"
+)
+
+// builtinArgKind determines the expected object kind for a builtin
+// argument. It attempts to use the AST hints from builtin.go where
+// possible.
+func (c *completer) builtinArgKind(ctx context.Context, obj types.Object, call *ast.CallExpr) objKind {
+       builtin, err := c.snapshot.BuiltinPackage(ctx)
+       if err != nil {
+               return 0
+       }
+       exprIdx := exprAtPos(c.pos, call.Args)
+
+       builtinObj := builtin.Package.Scope.Lookup(obj.Name())
+       if builtinObj == nil {
+               return 0
+       }
+       decl, ok := builtinObj.Decl.(*ast.FuncDecl)
+       if !ok || exprIdx >= len(decl.Type.Params.List) {
+               return 0
+       }
+
+       switch ptyp := decl.Type.Params.List[exprIdx].Type.(type) {
+       case *ast.ChanType:
+               return kindChan
+       case *ast.ArrayType:
+               return kindSlice
+       case *ast.MapType:
+               return kindMap
+       case *ast.Ident:
+               switch ptyp.Name {
+               case "Type":
+                       switch obj.Name() {
+                       case "make":
+                               return kindChan | kindSlice | kindMap
+                       case "len":
+                               return kindSlice | kindMap | kindArray | kindString | kindChan
+                       case "cap":
+                               return kindSlice | kindArray | kindChan
+                       }
+               }
+       }
+
+       return 0
+}
+
+// builtinArgType infers the type of an argument to a builtin
+// function. parentInf is the inferred type info for the builtin
+// call's parent node.
+func (c *completer) builtinArgType(obj types.Object, call *ast.CallExpr, parentInf candidateInference) candidateInference {
+       var (
+               exprIdx = exprAtPos(c.pos, call.Args)
+
+               // Propagate certain properties from our parent's inference.
+               inf = candidateInference{
+                       typeName:  parentInf.typeName,
+                       modifiers: parentInf.modifiers,
+               }
+       )
+
+       switch obj.Name() {
+       case "append":
+               if parentInf.objType == nil {
+                       break
+               }
+
+               inf.objType = parentInf.objType
+
+               if exprIdx <= 0 {
+                       break
+               }
+
+               inf.objType = deslice(inf.objType)
+
+               // Check if we are completing the variadic append() param.
+               inf.variadic = exprIdx == 1 && len(call.Args) <= 2
+
+               // Penalize the first append() argument as a candidate. You
+               // don't normally append a slice to itself.
+               if sliceChain := objChain(c.pkg.GetTypesInfo(), call.Args[0]); len(sliceChain) > 0 {
+                       inf.penalized = append(inf.penalized, penalizedObj{objChain: sliceChain, penalty: 0.9})
+               }
+       case "delete":
+               if exprIdx > 0 && len(call.Args) > 0 {
+                       // Try to fill in expected type of map key.
+                       firstArgType := c.pkg.GetTypesInfo().TypeOf(call.Args[0])
+                       if firstArgType != nil {
+                               if mt, ok := firstArgType.Underlying().(*types.Map); ok {
+                                       inf.objType = mt.Key()
+                               }
+                       }
+               }
+       case "copy":
+               var t1, t2 types.Type
+               if len(call.Args) > 0 {
+                       t1 = c.pkg.GetTypesInfo().TypeOf(call.Args[0])
+                       if len(call.Args) > 1 {
+                               t2 = c.pkg.GetTypesInfo().TypeOf(call.Args[1])
+                       }
+               }
+
+               // Fill in expected type of either arg if the other is already present.
+               if exprIdx == 1 && t1 != nil {
+                       inf.objType = t1
+               } else if exprIdx == 0 && t2 != nil {
+                       inf.objType = t2
+               }
+       case "new":
+               inf.typeName.wantTypeName = true
+               if parentInf.objType != nil {
+                       // Expected type for "new" is the de-pointered parent type.
+                       if ptr, ok := parentInf.objType.Underlying().(*types.Pointer); ok {
+                               inf.objType = ptr.Elem()
+                       }
+               }
+       case "make":
+               if exprIdx == 0 {
+                       inf.typeName.wantTypeName = true
+                       inf.objType = parentInf.objType
+               } else {
+                       inf.objType = types.Typ[types.Int]
+               }
+       }
+
+       return inf
+}