From 2e4132e53b93d8d81f7a076566396511238b89b0 Mon Sep 17 00:00:00 2001 From: Rebecca Stambler Date: Tue, 15 Jan 2019 17:04:34 -0500 Subject: [PATCH] internal/lsp: add a test for completion of builtin types and functions Change-Id: I7df2cfebbf2c44d189066a6d16770c753f7bf1d4 Reviewed-on: https://go-review.googlesource.com/c/158020 Reviewed-by: Ian Cottrell --- internal/lsp/lsp_test.go | 38 +++++++++++-------- internal/lsp/source/completion.go | 5 +-- internal/lsp/testdata/builtins/builtins.go | 44 +++++++++++++++++++++- internal/lsp/testdata/foo/foo.go | 2 +- 4 files changed, 68 insertions(+), 21 deletions(-) diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go index 65282e4e..28a2c22a 100644 --- a/internal/lsp/lsp_test.go +++ b/internal/lsp/lsp_test.go @@ -21,8 +21,8 @@ import ( "golang.org/x/tools/internal/lsp/source" ) -// TODO(rstambler): Remove this once Go 1.12 is released as we will end support -// for versions of Go <= 1.10. +// TODO(rstambler): Remove this once Go 1.12 is released as we end support for +// versions of Go <= 1.10. var goVersion111 = true func TestLSP(t *testing.T) { @@ -251,21 +251,10 @@ func (c completions) test(t *testing.T, exported *packagestest.Exported, s *serv if err != nil { t.Fatal(err) } + wantBuiltins := strings.Contains(src.Filename, "builtins") var got []protocol.CompletionItem for _, item := range list.Items { - // Skip all types with no details (builtin types). - if item.Detail == "" && item.Kind == float64(protocol.TypeParameterCompletion) { - continue - } - // Skip remaining builtin types. - trimmed := item.Label - if i := strings.Index(trimmed, "("); i >= 0 { - trimmed = trimmed[:i] - } - switch trimmed { - case "append", "cap", "close", "complex", "copy", "delete", - "error", "false", "imag", "iota", "len", "make", "new", - "nil", "panic", "print", "println", "real", "recover", "true": + if !wantBuiltins && isBuiltin(item) { continue } got = append(got, item) @@ -279,6 +268,25 @@ func (c completions) test(t *testing.T, exported *packagestest.Exported, s *serv } } +func isBuiltin(item protocol.CompletionItem) bool { + // If a type has no detail, it is a builtin type. + if item.Detail == "" && item.Kind == float64(protocol.TypeParameterCompletion) { + return true + } + // Remaining builtin constants, variables, interfaces, and functions. + trimmed := item.Label + if i := strings.Index(trimmed, "("); i >= 0 { + trimmed = trimmed[:i] + } + switch trimmed { + case "append", "cap", "close", "complex", "copy", "delete", + "error", "false", "imag", "iota", "len", "make", "new", + "nil", "panic", "print", "println", "real", "recover", "true": + return true + } + return false +} + func (c completions) collect(src token.Position, expected []token.Pos) { c[src] = expected } diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go index 576c501d..4bb2d3e3 100644 --- a/internal/lsp/source/completion.go +++ b/internal/lsp/source/completion.go @@ -144,7 +144,6 @@ func Completion(ctx context.Context, f File, pos token.Pos) (items []CompletionI // fallback to lexical completions return lexical(path, pos, pkg.Types, pkg.TypesInfo, found), "", nil } - return items, prefix, nil } @@ -691,11 +690,11 @@ var builtinDetails = map[string]itemDetails{ label: "close(c chan<- T)", }, "complex": { // complex(r, i float64) complex128 - label: "complex(real, imag float64)", + label: "complex(real float64, imag float64)", detail: "complex128", }, "copy": { // copy(dst, src []T) int - label: "copy(dst, src []T)", + label: "copy(dst []T, src []T)", detail: "int", }, "delete": { // delete(m map[T]T1, key T) diff --git a/internal/lsp/testdata/builtins/builtins.go b/internal/lsp/testdata/builtins/builtins.go index 75452504..c85a763a 100644 --- a/internal/lsp/testdata/builtins/builtins.go +++ b/internal/lsp/testdata/builtins/builtins.go @@ -1,6 +1,46 @@ package builtins func _() { - // TODO(rstambler): Add testing for completion of builtin symbols. - //@complete("") + //@complete("", append, bool, byte, cap, close, complex, complex128, complex64, copy, delete, error, _false, float32, float64, imag, int, int16, int32, int64, int8, iota, len, make, new, _nil, panic, print, println, real, recover, rune, string, _true, uint, uint16, uint32, uint64, uint8, uintptr) } + +/* Create markers for builtin types. Only for use by this test. +/* append(slice []T, elems ...T) []T */ //@item(append, "append(slice []T, elems ...T)", "[]T", "func") +/* bool */ //@item(bool, "bool", "", "type") +/* byte */ //@item(byte, "byte", "", "type") +/* cap(v []T) int */ //@item(cap, "cap(v []T)", "int", "func") +/* close(c chan<- T) */ //@item(close, "close(c chan<- T)", "", "func") +/* complex(real float64, imag float64) */ //@item(complex, "complex(real float64, imag float64)", "complex128", "func") +/* complex128 */ //@item(complex128, "complex128", "", "type") +/* complex64 */ //@item(complex64, "complex64", "", "type") +/* copy(dst []T, src []T) int */ //@item(copy, "copy(dst []T, src []T)", "int", "func") +/* delete(m map[K]V, key K) */ //@item(delete, "delete(m map[K]V, key K)", "", "func") +/* error */ //@item(error, "error", "", "interface") +/* false */ //@item(_false, "false", "", "const") +/* float32 */ //@item(float32, "float32", "", "type") +/* float64 */ //@item(float64, "float64", "", "type") +/* imag(complex128) float64 */ //@item(imag, "imag(complex128)", "float64", "func") +/* int */ //@item(int, "int", "", "type") +/* int16 */ //@item(int16, "int16", "", "type") +/* int32 */ //@item(int32, "int32", "", "type") +/* int64 */ //@item(int64, "int64", "", "type") +/* int8 */ //@item(int8, "int8", "", "type") +/* iota */ //@item(iota, "iota", "", "const") +/* len(T) int */ //@item(len, "len(T)", "int", "func") +/* make(t T, size ...int) T */ //@item(make, "make(t T, size ...int)", "T", "func") +/* new(T) *T */ //@item(new, "new(T)", "*T", "func") +/* nil */ //@item(_nil, "nil", "", "var") +/* panic(interface{}) */ //@item(panic, "panic(interface{})", "", "func") +/* print(args ...T) */ //@item(print, "print(args ...T)", "", "func") +/* println(args ...T) */ //@item(println, "println(args ...T)", "", "func") +/* real(complex128) float64 */ //@item(real, "real(complex128)", "float64", "func") +/* recover() interface{} */ //@item(recover, "recover()", "interface{}", "func") +/* rune */ //@item(rune, "rune", "", "type") +/* string */ //@item(string, "string", "", "type") +/* true */ //@item(_true, "true", "", "const") +/* uint */ //@item(uint, "uint", "", "type") +/* uint16 */ //@item(uint16, "uint16", "", "type") +/* uint32 */ //@item(uint32, "uint32", "", "type") +/* uint64 */ //@item(uint64, "uint64", "", "type") +/* uint8 */ //@item(uint8, "uint8", "", "type") +/* uintptr */ //@item(uintptr, "uintptr", "", "type") diff --git a/internal/lsp/testdata/foo/foo.go b/internal/lsp/testdata/foo/foo.go index e02099b4..cc515c2a 100644 --- a/internal/lsp/testdata/foo/foo.go +++ b/internal/lsp/testdata/foo/foo.go @@ -4,7 +4,7 @@ type StructFoo struct { //@item(StructFoo, "StructFoo", "struct{...}", "struct") Value int //@item(Value, "Value", "int", "field") } -// TODO(rstambler): Create pre-set builtins? +// Pre-set this marker, as we don't have a "source" for it in this package. /* Error() */ //@item(Error, "Error()", "string", "method") func Foo() { //@item(Foo, "Foo()", "", "func")