Skip to content

Commit 97ad0ed

Browse files
muirdmstamblerre
authored andcommitted
internal/lsp: improve completion in append() calls
Add a special case for append() arguments so we infer the expected type from the append() context. For example: var foo []int foo = append(<>) We now infer the expected type at <> to be []int. We also support the variadicity of append(). Change-Id: Ie0ef0007907fcb7992f9697cb90970ce4d9a66b8 Reviewed-on: https://go-review.googlesource.com/c/tools/+/205606 Run-TryBot: Rebecca Stambler <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Rebecca Stambler <[email protected]>
1 parent 7d206e1 commit 97ad0ed

File tree

3 files changed

+56
-6
lines changed

3 files changed

+56
-6
lines changed

internal/lsp/source/completion.go

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,10 +1053,8 @@ type typeNameInference struct {
10531053

10541054
// expectedType returns information about the expected type for an expression at
10551055
// the query position.
1056-
func expectedType(c *completer) typeInference {
1057-
inf := typeInference{
1058-
typeName: expectTypeName(c),
1059-
}
1056+
func expectedType(c *completer) (inf typeInference) {
1057+
inf.typeName = expectTypeName(c)
10601058

10611059
if c.enclosingCompositeLiteral != nil {
10621060
inf.objType = c.expectedCompositeLiteralType()
@@ -1139,6 +1137,39 @@ Nodes:
11391137
break Nodes
11401138
}
11411139
}
1140+
1141+
if funIdent, ok := node.Fun.(*ast.Ident); ok {
1142+
switch c.pkg.GetTypesInfo().ObjectOf(funIdent) {
1143+
case types.Universe.Lookup("append"):
1144+
defer func() {
1145+
exprIdx := indexExprAtPos(c.pos, node.Args)
1146+
1147+
// Check if we are completing the variadic append()
1148+
// param. We defer this since we don't want to inherit
1149+
// variadicity from the next node.
1150+
inf.variadic = exprIdx == 1 && len(node.Args) <= 2
1151+
1152+
// If we are completing an individual element of the
1153+
// variadic param, "deslice" the expected type.
1154+
if !inf.variadic && exprIdx > 0 {
1155+
if slice, ok := inf.objType.(*types.Slice); ok {
1156+
inf.objType = slice.Elem()
1157+
}
1158+
}
1159+
}()
1160+
1161+
// The expected type of append() arguments is the expected
1162+
// type of the append() call itself. For example:
1163+
//
1164+
// var foo []int
1165+
// foo = append(<>)
1166+
//
1167+
// To find the expected type at <> we "skip" the append()
1168+
// node and get the expected type one level up, which is
1169+
// []int.
1170+
continue Nodes
1171+
}
1172+
}
11421173
}
11431174
return inf
11441175
case *ast.ReturnStmt:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package append
2+
3+
func foo([]string) {}
4+
func bar(...string) {}
5+
6+
func _() {
7+
var (
8+
aInt []int //@item(appendInt, "aInt", "[]int", "var")
9+
aStrings []string //@item(appendStrings, "aStrings", "[]string", "var")
10+
aString string //@item(appendString, "aString", "string", "var")
11+
)
12+
13+
foo(append()) //@rank("))", appendStrings, appendInt),rank("))", appendStrings, appendString)
14+
foo(append(nil, a)) //@rank("))", appendStrings, appendInt),rank("))", appendString, appendInt),snippet("))", appendStrings, "aStrings...", "aStrings...")
15+
foo(append(nil, "", a)) //@rank("))", appendString, appendInt),rank("))", appendString, appendStrings)
16+
17+
// Don't add "..." to append() argument.
18+
bar(append()) //@snippet("))", appendStrings, "aStrings", "aStrings")
19+
}

internal/lsp/testdata/summary.txt.golden

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
-- summary --
22
CompletionsCount = 215
3-
CompletionSnippetCount = 45
3+
CompletionSnippetCount = 47
44
UnimportedCompletionsCount = 3
55
DeepCompletionsCount = 5
66
FuzzyCompletionsCount = 7
7-
RankedCompletionsCount = 16
7+
RankedCompletionsCount = 22
88
CaseSensitiveCompletionsCount = 4
99
DiagnosticsCount = 22
1010
FoldingRangesCount = 2

0 commit comments

Comments
 (0)