From 990129eca5479318dfdf63957e7f4181c28cefce Mon Sep 17 00:00:00 2001 From: Muir Manders Date: Sat, 1 Aug 2020 14:18:10 -0700 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Rebecca Stambler --- internal/lsp/source/completion.go | 18 +++++++++++++++--- .../lsp/primarymod/badstmt/badstmt_3.go.in | 2 +- .../lsp/primarymod/badstmt/badstmt_4.go.in | 2 +- .../lsp/primarymod/func_rank/func_rank.go.in | 2 +- internal/lsp/testdata/lsp/summary.txt.golden | 2 +- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go index e4f32bd65d..c0362bee83 100644 --- a/internal/lsp/source/completion.go +++ b/internal/lsp/source/completion.go @@ -1511,6 +1511,7 @@ const ( kindMap kindStruct kindString + kindFunc ) // candidateInference holds information we have inferred about a type that can be @@ -1639,7 +1640,7 @@ Nodes: 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 @@ Nodes: continue Nodes } } + + return inf } - return inf case *ast.ReturnStmt: if c.enclosingFunc != nil { sig := c.enclosingFunc.sig @@ -1775,6 +1777,9 @@ Nodes: 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 @@ func (ci *candidateInference) candTypeMatches(cand *candidate) bool { // 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 @@ func candKind(candType types.Type) objKind { 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 66174095d7..be774e84b0 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 @@ import ( ) 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 d6615812d6..a9b46fb021 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 @@ import ( 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 9d180ad2c2..3706009583 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 @@ func _() { // 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 ea87659ecc..91b872a5ae 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