internal/lsp: add additional tests for completion

New tests include cases for anonymous structs, composite literals,
ranking of results in binary expressions, and import cycles.

Change-Id: Ic02e84e09101bb9873fc1705bba2594d655bb45b
Reviewed-on: https://go-review.googlesource.com/c/153443
Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
Rebecca Stambler 2018-12-11 00:52:31 -05:00
parent 2240b23956
commit 6e267b5cc7
14 changed files with 117 additions and 36 deletions

View File

@ -14,28 +14,28 @@ import (
"golang.org/x/tools/internal/lsp/source"
)
func toProtocolCompletionItems(items []source.CompletionItem, prefix string, pos protocol.Position, snippetsSupported, signatureHelpEnabled bool) []protocol.CompletionItem {
var results []protocol.CompletionItem
sort.Slice(items, func(i, j int) bool {
return items[i].Score > items[j].Score
})
func toProtocolCompletionItems(candidates []source.CompletionItem, prefix string, pos protocol.Position, snippetsSupported, signatureHelpEnabled bool) []protocol.CompletionItem {
insertTextFormat := protocol.PlainTextFormat
if snippetsSupported {
insertTextFormat = protocol.SnippetTextFormat
}
for i, item := range items {
sort.SliceStable(candidates, func(i, j int) bool {
return candidates[i].Score > candidates[j].Score
})
var items []protocol.CompletionItem
for i, candidate := range candidates {
// Matching against the label.
if !strings.HasPrefix(item.Label, prefix) {
if !strings.HasPrefix(candidate.Label, prefix) {
continue
}
insertText, triggerSignatureHelp := labelToProtocolSnippets(item.Label, item.Kind, insertTextFormat, signatureHelpEnabled)
insertText, triggerSignatureHelp := labelToProtocolSnippets(candidate.Label, candidate.Kind, insertTextFormat, signatureHelpEnabled)
if strings.HasPrefix(insertText, prefix) {
insertText = insertText[len(prefix):]
}
i := protocol.CompletionItem{
Label: item.Label,
Detail: item.Detail,
Kind: float64(toProtocolCompletionItemKind(item.Kind)),
item := protocol.CompletionItem{
Label: candidate.Label,
Detail: candidate.Detail,
Kind: float64(toProtocolCompletionItemKind(candidate.Kind)),
InsertTextFormat: insertTextFormat,
TextEdit: &protocol.TextEdit{
NewText: insertText,
@ -53,13 +53,13 @@ func toProtocolCompletionItems(items []source.CompletionItem, prefix string, pos
}
// If we are completing a function, we should trigger signature help if possible.
if triggerSignatureHelp && signatureHelpEnabled {
i.Command = &protocol.Command{
item.Command = &protocol.Command{
Command: "editor.action.triggerParameterHints",
}
}
results = append(results, i)
items = append(items, item)
}
return results
return items
}
func toProtocolCompletionItemKind(kind source.CompletionItemKind) protocol.CompletionItemKind {

View File

@ -35,8 +35,8 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
// We hardcode the expected number of test cases to ensure that all tests
// are being executed. If a test is added, this number must be changed.
const expectedCompletionsCount = 44
const expectedDiagnosticsCount = 14
const expectedCompletionsCount = 60
const expectedDiagnosticsCount = 15
const expectedFormatCount = 3
const expectedDefinitionsCount = 16
const expectedTypeDefinitionsCount = 2

23
internal/lsp/testdata/anon/anon.go.in vendored Normal file
View File

@ -0,0 +1,23 @@
package anon
func _() {
for _, _ := range []struct {
i, j int //@item(anonI, "i", "int", "field"),item(anonJ, "j", "int", "field")
}{
{
i: 1,
//@complete("", anonJ)
},
{
//@complete("", anonI, anonJ)
},
} {
continue
}
s := struct{ f int }{ } //@item(anonF, "f", "int", "field"),item(structS, "s", "struct{...}", "var"),complete(" }", anonF)
_ = map[struct{ x int }]int{ //@item(anonX, "x", "int", "field")
struct{ x int }{ }: 1, //@complete(" }", anonX, structS)
}
}

View File

@ -1,19 +0,0 @@
package assign_rank
var (
apple int = 3 //@item(apple, "apple", "int", "var")
pear string = "hello" //@item(pear, "pear", "string", "var")
)
func _() {
orange := 1 //@item(orange, "orange", "int", "var")
grape := "hello" //@item(grape, "grape", "string", "var")
orange, grape = 2, "hello" //@complete(" \"", grape, pear, orange, apple)
}
func _() {
var pineapple int //@item(pineapple, "pineapple", "int", "var")
pineapple = //@complete(" /", pineapple, apple, pear)
y := //@complete(" /", pineapple, apple, pear)
}

View File

@ -0,0 +1,6 @@
package builtins
func _() {
// TODO(rstambler): Add testing for completion of builtin symbols.
//@complete("")
}

View File

@ -0,0 +1,26 @@
package complit
type position struct { //@item(structPosition, "position", "struct{...}", "struct")
X, Y int //@item(fieldX, "X", "int", "field"),item(fieldY, "Y", "int", "field")
}
func _() {
_ := position{
//@complete("", fieldX, fieldY, structPosition)
}
_ := position{
X: 1,
//@complete("", fieldY)
}
_ := position{
//@complete("", fieldX)
Y: 1,
}
}
func _() {
_ := position{
X: 1, //@complete("X", fieldX),complete(" 1", structPosition)
Y: , //@complete(":", fieldY),complete(" ,", structPosition)
}
}

View File

@ -0,0 +1,5 @@
package errors
func _() {
bob.Bob() //@complete(".")
}

View File

@ -0,0 +1,19 @@
package rank
var (
apple int = 3 //@item(apple, "apple", "int", "var")
pear string = "hello" //@item(pear, "pear", "string", "var")
)
func _() {
orange := 1 //@item(orange, "orange", "int", "var")
grape := "hello" //@item(grape, "grape", "string", "var")
orange, grape = 2, "hello" //@complete(" \"", grape, pear, orange, apple)
}
func _() {
var pineapple int //@item(pineapple, "pineapple", "int", "var")
pineapple = //@complete(" /", pineapple, apple, pear)
y := //@complete(" /", pineapple, apple, pear)
}

View File

@ -0,0 +1,8 @@
package rank
func _() {
_ = 5 + ; //@complete(" ;", apple, pear)
y := + 5; //@complete(" +", apple, pear)
if 6 == {} //@complete(" {", apple, pear)
}

13
internal/lsp/testdata/self/self.go.in vendored Normal file
View File

@ -0,0 +1,13 @@
// +build go1.11
package self
import (
"golang.org/x/tools/internal/lsp/self" //@diag("\"", "could not import golang.org/x/tools/internal/lsp/self (import cycle: [golang.org/x/tools/internal/lsp/self])")
)
func Hello() {}
func _() {
self.Hello()
}