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.
13 // builtinArgKind determines the expected object kind for a builtin
14 // argument. It attempts to use the AST hints from builtin.go where
16 func (c *completer) builtinArgKind(ctx context.Context, obj types.Object, call *ast.CallExpr) objKind {
17 builtin, err := c.snapshot.BuiltinPackage(ctx)
21 exprIdx := exprAtPos(c.pos, call.Args)
23 builtinObj := builtin.Package.Scope.Lookup(obj.Name())
24 if builtinObj == nil {
27 decl, ok := builtinObj.Decl.(*ast.FuncDecl)
28 if !ok || exprIdx >= len(decl.Type.Params.List) {
32 switch ptyp := decl.Type.Params.List[exprIdx].Type.(type) {
44 return kindChan | kindSlice | kindMap
46 return kindSlice | kindMap | kindArray | kindString | kindChan
48 return kindSlice | kindArray | kindChan
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 {
61 exprIdx = exprAtPos(c.pos, call.Args)
63 // Propagate certain properties from our parent's inference.
64 inf = candidateInference{
65 typeName: parentInf.typeName,
66 modifiers: parentInf.modifiers,
72 if parentInf.objType == nil {
76 inf.objType = parentInf.objType
82 inf.objType = deslice(inf.objType)
84 // Check if we are completing the variadic append() param.
85 inf.variadic = exprIdx == 1 && len(call.Args) <= 2
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})
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()
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])
111 // Fill in expected type of either arg if the other is already present.
112 if exprIdx == 1 && t1 != nil {
114 } else if exprIdx == 0 && t2 != nil {
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()
127 inf.typeName.wantTypeName = true
128 inf.objType = parentInf.objType
130 inf.objType = types.Typ[types.Int]