From 473961ec044c1c001df816e5edb29e4a31db4c01 Mon Sep 17 00:00:00 2001 From: Muir Manders Date: Tue, 14 Jan 2020 09:13:30 -0800 Subject: [PATCH] internal/lsp/source: improve completion for "range" and "<-" Now that we understand object "kind" for builtin generic functions, we can apply it to a couple more places as well: // prefer rangeable object kinds for i := range <> { } // prefer channels <- <> Change-Id: If9cfba3a06b3abde073a9d397000bb3f3b0e9853 Reviewed-on: https://go-review.googlesource.com/c/tools/+/214678 Run-TryBot: Muir Manders TryBot-Result: Gobot Gobot Reviewed-by: Rebecca Stambler --- internal/lsp/source/completion.go | 19 ++++++----- .../lsp/testdata/builtins/builtin_args.go | 34 ++++++++++++------- internal/lsp/testdata/summary.txt.golden | 2 +- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go index 4a086550bf0..62e0f3851e4 100644 --- a/internal/lsp/source/completion.go +++ b/internal/lsp/source/completion.go @@ -1290,7 +1290,6 @@ Nodes: } if tv, ok := c.pkg.GetTypesInfo().Types[node.Lhs[i]]; ok { inf.objType = tv.Type - break Nodes } } return inf @@ -1298,7 +1297,7 @@ Nodes: if node.Type != nil && c.pos > node.Type.End() { inf.objType = c.pkg.GetTypesInfo().TypeOf(node.Type) } - break Nodes + return inf case *ast.CallExpr: // Only consider CallExpr args if position falls between parens. if node.Lparen <= c.pos && c.pos <= node.Rparen { @@ -1387,7 +1386,6 @@ Nodes: if resultIdx := indexExprAtPos(c.pos, node.Results); resultIdx < len(node.Results) { if resultIdx < sig.Results().Len() { inf.objType = sig.Results().At(resultIdx).Type() - break Nodes } } } @@ -1396,7 +1394,6 @@ Nodes: if swtch, ok := findSwitchStmt(c.path[i+1:], c.pos, node).(*ast.SwitchStmt); ok { if tv, ok := c.pkg.GetTypesInfo().Types[swtch.Tag]; ok { inf.objType = tv.Type - break Nodes } } return inf @@ -1404,7 +1401,6 @@ Nodes: // Make sure position falls within the brackets (e.g. "foo[a:<>]"). if node.Lbrack < c.pos && c.pos <= node.Rbrack { inf.objType = types.Typ[types.Int] - break Nodes } return inf case *ast.IndexExpr: @@ -1416,10 +1412,7 @@ Nodes: inf.objType = t.Key() case *types.Slice, *types.Array: inf.objType = types.Typ[types.Int] - default: - return inf } - break Nodes } } return inf @@ -1429,11 +1422,18 @@ Nodes: if tv, ok := c.pkg.GetTypesInfo().Types[node.Chan]; ok { if ch, ok := tv.Type.Underlying().(*types.Chan); ok { inf.objType = ch.Elem() - break Nodes } } } return inf + case *ast.RangeStmt: + if nodeContains(node.X, c.pos) { + inf.objKind |= kindSlice | kindArray | kindMap | kindString + if node.Value == nil { + inf.objKind |= kindChan + } + } + return inf case *ast.StarExpr: inf.modifiers = append(inf.modifiers, typeModifier{mod: star}) case *ast.UnaryExpr: @@ -1442,6 +1442,7 @@ Nodes: inf.modifiers = append(inf.modifiers, typeModifier{mod: address}) case token.ARROW: inf.modifiers = append(inf.modifiers, typeModifier{mod: chanRead}) + inf.objKind |= kindChan } default: if breaksExpectedTypeInference(node) { diff --git a/internal/lsp/testdata/builtins/builtin_args.go b/internal/lsp/testdata/builtins/builtin_args.go index 9652b0b0869..040d7e396af 100644 --- a/internal/lsp/testdata/builtins/builtin_args.go +++ b/internal/lsp/testdata/builtins/builtin_args.go @@ -2,26 +2,26 @@ package builtins func _() { var ( - slice_ []int //@item(builtinSlice, "slice_", "[]int", "var") - map_ map[string]int //@item(builtinMap, "map_", "map[string]int", "var") - string_ string //@item(builtinString, "string_", "string", "var") - array_ [0]int //@item(builtinArray, "array_", "[0]int", "var") - arrayPtr_ *[0]int //@item(builtinArrayPtr, "arrayPtr_", "*[0]int", "var") - chan_ chan int //@item(builtinChan, "chan_", "chan int", "var") - ptr_ *int //@item(builtinPtr, "ptr_", "*int", "var") - int_ int //@item(builtinInt, "int_", "int", "var") + aSlice []int //@item(builtinSlice, "aSlice", "[]int", "var") + aMap map[string]int //@item(builtinMap, "aMap", "map[string]int", "var") + aString string //@item(builtinString, "aString", "string", "var") + aArray [0]int //@item(builtinArray, "aArray", "[0]int", "var") + aArrayPtr *[0]int //@item(builtinArrayPtr, "aArrayPtr", "*[0]int", "var") + aChan chan int //@item(builtinChan, "aChan", "chan int", "var") + aPtr *int //@item(builtinPtr, "aPtr", "*int", "var") + aInt int //@item(builtinInt, "aInt", "int", "var") ) close() //@rank(")", builtinChan, builtinSlice) append() //@rank(")", builtinSlice, builtinChan) - copy() //@rank(")", builtinSlice, builtinChan) - copy(slice_, s) //@rank(")", builtinSlice, builtinString) - copy(s, slice_) //@rank(",", builtinSlice, builtinString) + copy() //@rank(")", builtinSlice, builtinChan) + copy(aSlice, aS) //@rank(")", builtinSlice, builtinString) + copy(aS, aSlice) //@rank(",", builtinSlice, builtinString) - delete() //@rank(")", builtinMap, builtinChan) - delete(map_, s) //@rank(")", builtinString, builtinSlice) + delete() //@rank(")", builtinMap, builtinChan) + delete(aMap, aS) //@rank(")", builtinString, builtinSlice) len() //@rank(")", builtinSlice, builtinInt),rank(")", builtinMap, builtinInt),rank(")", builtinString, builtinInt),rank(")", builtinArray, builtinInt),rank(")", builtinArrayPtr, builtinPtr),rank(")", builtinChan, builtinInt) @@ -34,4 +34,12 @@ func _() { type myStruct struct{} //@item(builtinStructType, "myStruct", "struct{...}", "struct") new() //@rank(")", builtinStructType, builtinInt) var _ *myStruct = new() //@rank(")", builtinStructType, int) + + for k := range a { //@rank(" {", builtinSlice, builtinInt),rank(" {", builtinString, builtinInt),rank(" {", builtinChan, builtinInt),rank(" {", builtinArray, builtinInt),rank(" {", builtinArrayPtr, builtinInt),rank(" {", builtinMap, builtinInt), + } + + for k, v := range a { //@rank(" {", builtinSlice, builtinChan) + } + + <-a //@rank(" //", builtinChan, builtinInt) } diff --git a/internal/lsp/testdata/summary.txt.golden b/internal/lsp/testdata/summary.txt.golden index 4c60c56b1c3..ee564e3b356 100644 --- a/internal/lsp/testdata/summary.txt.golden +++ b/internal/lsp/testdata/summary.txt.golden @@ -4,7 +4,7 @@ CompletionSnippetCount = 63 UnimportedCompletionsCount = 9 DeepCompletionsCount = 5 FuzzyCompletionsCount = 8 -RankedCompletionsCount = 55 +RankedCompletionsCount = 63 CaseSensitiveCompletionsCount = 4 DiagnosticsCount = 35 FoldingRangesCount = 2