internal/lsp/source: prefer funcs when completing go/defer

Now we prefer functions when completing "go" and "defer" statements.
Previously we had no preference for the type of object. Further, we
will now also properly invoke functions.

    var f1 int
    var f2 func()
    go f<> // prefers "f2" and expands to "f2()"

Change-Id: I213551b74ba453c337ac89e825b5d495659e9d65
Reviewed-on: https://go-review.googlesource.com/c/tools/+/246359
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go
index e4f32bd..c0362be 100644
--- a/internal/lsp/source/completion.go
+++ b/internal/lsp/source/completion.go
@@ -1511,6 +1511,7 @@
 	kindMap
 	kindStruct
 	kindString
+	kindFunc
 )
 
 // candidateInference holds information we have inferred about a type that can be
@@ -1639,7 +1640,7 @@
 			return inf
 		case *ast.CallExpr:
 			// Only consider CallExpr args if position falls between parens.
-			if node.Lparen <= c.pos && c.pos <= node.Rparen {
+			if node.Lparen < c.pos && c.pos <= node.Rparen {
 				// For type conversions like "int64(foo)" we can only infer our
 				// desired type is convertible to int64.
 				if typ := typeConversion(node, c.pkg.GetTypesInfo()); typ != nil {
@@ -1709,8 +1710,9 @@
 						continue Nodes
 					}
 				}
+
+				return inf
 			}
-			return inf
 		case *ast.ReturnStmt:
 			if c.enclosingFunc != nil {
 				sig := c.enclosingFunc.sig
@@ -1775,6 +1777,9 @@
 			case token.ARROW:
 				inf.modifiers = append(inf.modifiers, typeModifier{mod: chanRead})
 			}
+		case *ast.DeferStmt, *ast.GoStmt:
+			inf.objKind |= kindFunc
+			return inf
 		default:
 			if breaksExpectedTypeInference(node) {
 				return inf
@@ -2137,7 +2142,12 @@
 
 			// If we have no expected type, fall back to checking the
 			// expected "kind" of object, if available.
-			return ci.kindMatches(candType)
+			if ci.kindMatches(candType) {
+				if ci.objKind == kindFunc {
+					cand.expandFuncCall = true
+				}
+				return true
+			}
 		}
 
 		for _, expType := range expTypes {
@@ -2326,6 +2336,8 @@
 		if t.Info()&types.IsString > 0 {
 			return kindString
 		}
+	case *types.Signature:
+		return kindFunc
 	}
 
 	return 0
diff --git a/internal/lsp/testdata/lsp/primarymod/badstmt/badstmt_3.go.in b/internal/lsp/testdata/lsp/primarymod/badstmt/badstmt_3.go.in
index 6617409..be774e8 100644
--- a/internal/lsp/testdata/lsp/primarymod/badstmt/badstmt_3.go.in
+++ b/internal/lsp/testdata/lsp/primarymod/badstmt/badstmt_3.go.in
@@ -5,5 +5,5 @@
 )
 
 func _() {
-	go foo. //@rank(" //", Foo)
+	go foo. //@rank(" //", Foo, IntFoo),snippet(" //", Foo, "Foo()", "Foo()")
 }
diff --git a/internal/lsp/testdata/lsp/primarymod/badstmt/badstmt_4.go.in b/internal/lsp/testdata/lsp/primarymod/badstmt/badstmt_4.go.in
index d661581..a9b46fb 100644
--- a/internal/lsp/testdata/lsp/primarymod/badstmt/badstmt_4.go.in
+++ b/internal/lsp/testdata/lsp/primarymod/badstmt/badstmt_4.go.in
@@ -6,6 +6,6 @@
 
 func _() {
 	go func() {
-		defer foo. //@rank(" //", Foo)
+		defer foo. //@rank(" //", Foo, IntFoo)
 	}
 }
diff --git a/internal/lsp/testdata/lsp/primarymod/func_rank/func_rank.go.in b/internal/lsp/testdata/lsp/primarymod/func_rank/func_rank.go.in
index 9d180ad..3706009 100644
--- a/internal/lsp/testdata/lsp/primarymod/func_rank/func_rank.go.in
+++ b/internal/lsp/testdata/lsp/primarymod/func_rank/func_rank.go.in
@@ -27,7 +27,7 @@
 
 	// no expected type
 	fnInt(func() int { s.A }) //@complete(" }", rankAA, rankAB, rankAC)
-	fnInt(s.A())              //@complete("()", rankAA, rankAB, rankAC)
+	fnInt(s.A())              //@complete("()", rankAA, rankAC, rankAB)
 	fnInt([]int{}[s.A])       //@complete("])", rankAA, rankAC, rankAB)
 	fnInt([]int{}[:s.A])      //@complete("])", rankAA, rankAC, rankAB)
 
diff --git a/internal/lsp/testdata/lsp/summary.txt.golden b/internal/lsp/testdata/lsp/summary.txt.golden
index ea87659..91b872a 100644
--- a/internal/lsp/testdata/lsp/summary.txt.golden
+++ b/internal/lsp/testdata/lsp/summary.txt.golden
@@ -1,7 +1,7 @@
 -- summary --
 CodeLensCount = 4
 CompletionsCount = 241
-CompletionSnippetCount = 80
+CompletionSnippetCount = 81
 UnimportedCompletionsCount = 6
 DeepCompletionsCount = 5
 FuzzyCompletionsCount = 8