internal/lsp: move function signature into detail instead of label

Fixes golang/go#32414

Change-Id: If08e655d7a0e29b0865c13d8377e98be01cf24c5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/184777
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/lsp/source/completion_format.go b/internal/lsp/source/completion_format.go
index abad1f9..b9718f7 100644
--- a/internal/lsp/source/completion_format.go
+++ b/internal/lsp/source/completion_format.go
@@ -40,7 +40,7 @@
 		params := formatParams(sig.Params(), sig.Variadic(), c.qf)
 		plainSnippet, placeholderSnippet = c.functionCallSnippets(label, params)
 		results, writeParens := formatResults(sig.Results(), c.qf)
-		label, detail = formatFunction(label, params, results, writeParens)
+		detail = "func" + formatFunction(params, results, writeParens)
 	}
 
 	switch obj := obj.(type) {
@@ -112,7 +112,6 @@
 
 func (c *completer) formatBuiltin(cand candidate) CompletionItem {
 	obj := cand.obj
-
 	item := CompletionItem{
 		Label:      obj.Name(),
 		InsertText: obj.Name(),
@@ -129,7 +128,8 @@
 		}
 		params, _ := formatFieldList(c.ctx, c.view, decl.Type.Params)
 		results, writeResultParens := formatFieldList(c.ctx, c.view, decl.Type.Results)
-		item.Label, item.Detail = formatFunction(obj.Name(), params, results, writeResultParens)
+		item.Label = obj.Name()
+		item.Detail = "func" + formatFunction(params, results, writeResultParens)
 		item.plainSnippet, item.placeholderSnippet = c.functionCallSnippets(obj.Name(), params)
 	case *types.TypeName:
 		if types.IsInterface(obj.Type()) {
diff --git a/internal/lsp/source/signature_help.go b/internal/lsp/source/signature_help.go
index 7a657b6..c17b8f5 100644
--- a/internal/lsp/source/signature_help.go
+++ b/internal/lsp/source/signature_help.go
@@ -152,11 +152,7 @@
 	for _, p := range params {
 		paramInfo = append(paramInfo, ParameterInformation{Label: p})
 	}
-	label, detail := formatFunction(name, params, results, writeResultParens)
-	// Show return values of the function in the label.
-	if detail != "" {
-		label += " " + detail
-	}
+	label := name + formatFunction(params, results, writeResultParens)
 	return &SignatureInformation{
 		Label: label,
 		// TODO: Should we have the HoverKind apply to signature information as well?
diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go
index 8fe0498..cfacb46 100644
--- a/internal/lsp/source/util.go
+++ b/internal/lsp/source/util.go
@@ -219,17 +219,22 @@
 	return detail, kind
 }
 
-func formatFunction(name string, params []string, results []string, writeResultParens bool) (string, string) {
-	var label, detail strings.Builder
-	label.WriteString(name)
-	label.WriteByte('(')
+func formatFunction(params []string, results []string, writeResultParens bool) string {
+	var detail strings.Builder
+
+	detail.WriteByte('(')
 	for i, p := range params {
 		if i > 0 {
-			label.WriteString(", ")
+			detail.WriteString(", ")
 		}
-		label.WriteString(p)
+		detail.WriteString(p)
 	}
-	label.WriteByte(')')
+	detail.WriteByte(')')
+
+	// Add space between parameters and results.
+	if len(results) > 0 {
+		detail.WriteByte(' ')
+	}
 
 	if writeResultParens {
 		detail.WriteByte('(')
@@ -244,5 +249,5 @@
 		detail.WriteByte(')')
 	}
 
-	return label.String(), detail.String()
+	return detail.String()
 }
diff --git a/internal/lsp/testdata/bad/bad0.go b/internal/lsp/testdata/bad/bad0.go
index e6df4c1..b178252 100644
--- a/internal/lsp/testdata/bad/bad0.go
+++ b/internal/lsp/testdata/bad/bad0.go
@@ -2,7 +2,7 @@
 
 package bad
 
-func stuff() { //@item(stuff, "stuff()", "", "func")
+func stuff() { //@item(stuff, "stuff", "func()", "func")
 	x := "heeeeyyyy"
 	random2(x) //@diag("x", "LSP", "cannot use x (variable of type string) as int value in argument to random2")
 	random2(1) //@complete("dom", random, random2, random3)
diff --git a/internal/lsp/testdata/bad/bad1.go b/internal/lsp/testdata/bad/bad1.go
index b9664cb..c71d555 100644
--- a/internal/lsp/testdata/bad/bad1.go
+++ b/internal/lsp/testdata/bad/bad1.go
@@ -8,12 +8,12 @@
 
 var a unknown //@item(global_a, "a", "unknown", "var"),diag("unknown", "LSP", "undeclared name: unknown")
 
-func random() int { //@item(random, "random()", "int", "func")
+func random() int { //@item(random, "random", "func() int", "func")
 	//@complete("", global_a, bob, random, random2, random3, stuff)
 	return 0
 }
 
-func random2(y int) int { //@item(random2, "random2(y int)", "int", "func"),item(bad_y_param, "y", "int", "parameter")
+func random2(y int) int { //@item(random2, "random2", "func(y int) int", "func"),item(bad_y_param, "y", "int", "parameter")
 	x := 6     //@item(x, "x", "int", "var"),diag("x", "LSP", "x declared but not used")
 	var q blah //@item(q, "q", "blah", "var"),diag("q", "LSP", "q declared but not used"),diag("blah", "LSP", "undeclared name: blah")
 	var t blob //@item(t, "t", "blob", "var"),diag("t", "LSP", "t declared but not used"),diag("blob", "LSP", "undeclared name: blob")
@@ -22,6 +22,6 @@
 	return y
 }
 
-func random3(y ...int) { //@item(random3, "random3(y ...int)", "", "func"),item(y_variadic_param, "y", "[]int", "parameter")
+func random3(y ...int) { //@item(random3, "random3", "func(y ...int)", "func"),item(y_variadic_param, "y", "[]int", "parameter")
 	//@complete("", y_variadic_param, global_a, bob, random, random2, random3, stuff)
 }
diff --git a/internal/lsp/testdata/bar/bar.go.in b/internal/lsp/testdata/bar/bar.go.in
index 94d8254..c53facf 100644
--- a/internal/lsp/testdata/bar/bar.go.in
+++ b/internal/lsp/testdata/bar/bar.go.in
@@ -6,14 +6,14 @@
 	"golang.org/x/tools/internal/lsp/foo" //@item(foo, "foo", "\"golang.org/x/tools/internal/lsp/foo\"", "package")
 )
 
-func helper(i foo.IntFoo) {} //@item(helper, "helper(i foo.IntFoo)", "", "func")
+func helper(i foo.IntFoo) {} //@item(helper, "helper", "func(i foo.IntFoo)", "func")
 
 func _() {
 	help //@complete("l", helper)
 	_ = foo.StructFoo{} //@complete("S", Foo, IntFoo, StructFoo)
 }
 
-func Bar() { //@item(Bar, "Bar()", "", "func")
+func Bar() { //@item(Bar, "Bar", "func()", "func")
 	foo.Foo()        //@complete("F", Foo, IntFoo, StructFoo)
 	var _ foo.IntFoo //@complete("I", Foo, IntFoo, StructFoo)
 	foo.()           //@complete("(", Foo, IntFoo, StructFoo)
diff --git a/internal/lsp/testdata/builtins/builtins.go b/internal/lsp/testdata/builtins/builtins.go
index ae7280e..14fd144 100644
--- a/internal/lsp/testdata/builtins/builtins.go
+++ b/internal/lsp/testdata/builtins/builtins.go
@@ -5,36 +5,36 @@
 }
 
 /* Create markers for builtin types. Only for use by this test.
-/* append(slice []Type, elems ...Type) []Type */ //@item(append, "append(slice []Type, elems ...Type)", "[]Type", "func")
+/* append(slice []Type, elems ...Type) []Type */ //@item(append, "append", "func(slice []Type, elems ...Type) []Type", "func")
 /* bool */ //@item(bool, "bool", "", "type")
 /* byte */ //@item(byte, "byte", "", "type")
-/* cap(v Type) int */ //@item(cap, "cap(v Type)", "int", "func")
-/* close(c chan<- Type) */ //@item(close, "close(c chan<- Type)", "", "func")
-/* complex(r float64, i float64) */ //@item(complex, "complex(r float64, i float64)", "complex128", "func")
+/* cap(v Type) int */ //@item(cap, "cap", "func(v Type) int", "func")
+/* close(c chan<- Type) */ //@item(close, "close", "func(c chan<- Type)", "func")
+/* complex(r float64, i float64) */ //@item(complex, "complex", "func(r float64, i float64) complex128", "func")
 /* complex128 */ //@item(complex128, "complex128", "", "type")
 /* complex64 */ //@item(complex64, "complex64", "", "type")
-/* copy(dst []Type, src []Type) int */ //@item(copy, "copy(dst []Type, src []Type)", "int", "func")
-/* delete(m map[Type]Type1, key Type) */ //@item(delete, "delete(m map[Type]Type1, key Type)", "", "func")
+/* copy(dst []Type, src []Type) int */ //@item(copy, "copy", "func(dst []Type, src []Type) int", "func")
+/* delete(m map[Type]Type1, key Type) */ //@item(delete, "delete", "func(m map[Type]Type1, key Type)", "func")
 /* error */ //@item(error, "error", "", "interface")
 /* false */ //@item(_false, "false", "", "const")
 /* float32 */ //@item(float32, "float32", "", "type")
 /* float64 */ //@item(float64, "float64", "", "type")
-/* imag(c complex128) float64 */ //@item(imag, "imag(c complex128)", "float64", "func")
+/* imag(c complex128) float64 */ //@item(imag, "imag", "func(c 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(v Type) int */ //@item(len, "len(v Type)", "int", "func")
-/* make(t Type, size ...int) Type */ //@item(make, "make(t Type, size ...int)", "Type", "func")
-/* new(Type) *Type */ //@item(new, "new(Type)", "*Type", "func")
+/* len(v Type) int */ //@item(len, "len", "func(v Type) int", "func")
+/* make(t Type, size ...int) Type */ //@item(make, "make", "func(t Type, size ...int) Type", "func")
+/* new(Type) *Type */ //@item(new, "new", "func(Type) *Type", "func")
 /* nil */ //@item(_nil, "nil", "", "var")
-/* panic(v interface{}) */ //@item(panic, "panic(v interface{})", "", "func")
-/* print(args ...Type) */ //@item(print, "print(args ...Type)", "", "func")
-/* println(args ...Type) */ //@item(println, "println(args ...Type)", "", "func")
-/* real(c complex128) float64 */ //@item(real, "real(c complex128)", "float64", "func")
-/* recover() interface{} */ //@item(recover, "recover()", "interface{}", "func")
+/* panic(v interface{}) */ //@item(panic, "panic", "func(v interface{})", "func")
+/* print(args ...Type) */ //@item(print, "print", "func(args ...Type)", "func")
+/* println(args ...Type) */ //@item(println, "println", "func(args ...Type)", "func")
+/* real(c complex128) float64 */ //@item(real, "real", "func(c complex128) float64", "func")
+/* recover() interface{} */ //@item(recover, "recover", "func() interface{}", "func")
 /* rune */ //@item(rune, "rune", "", "type")
 /* string */ //@item(string, "string", "", "type")
 /* true */ //@item(_true, "true", "", "const")
diff --git a/internal/lsp/testdata/deepcomplete/deep_complete.go b/internal/lsp/testdata/deepcomplete/deep_complete.go
index 1a56fba..970ec65 100644
--- a/internal/lsp/testdata/deepcomplete/deep_complete.go
+++ b/internal/lsp/testdata/deepcomplete/deep_complete.go
@@ -26,9 +26,9 @@
 func wantsContext(context.Context) {}
 
 func _() {
-	context.Background() //@item(ctxBackground, "context.Background()", "context.Context", "func")
-	context.TODO()       //@item(ctxTODO, "context.TODO()", "context.Context", "func")
-	/* context.WithValue(parent context.Context, key interface{}, val interface{}) */ //@item(ctxWithValue, "context.WithValue(parent context.Context, key interface{}, val interface{})", "context.Context", "func")
+	context.Background() //@item(ctxBackground, "context.Background", "func() context.Context", "func")
+	context.TODO()       //@item(ctxTODO, "context.TODO", "func() context.Context", "func")
+	/* context.WithValue(parent context.Context, key interface{}, val interface{}) */ //@item(ctxWithValue, "context.WithValue", "func(parent context.Context, key interface{}, val interface{}) context.Context", "func")
 
 	wantsContext(c) //@complete(")", ctxBackground, ctxTODO, ctxWithValue, ctxPackage)
 }
diff --git a/internal/lsp/testdata/foo/foo.go b/internal/lsp/testdata/foo/foo.go
index 094623e..444f07f 100644
--- a/internal/lsp/testdata/foo/foo.go
+++ b/internal/lsp/testdata/foo/foo.go
@@ -5,9 +5,9 @@
 }
 
 // Pre-set this marker, as we don't have a "source" for it in this package.
-/* Error() */ //@item(Error, "Error()", "string", "method")
+/* Error() */ //@item(Error, "Error", "func() string", "method")
 
-func Foo() { //@item(Foo, "Foo()", "", "func")
+func Foo() { //@item(Foo, "Foo", "func()", "func")
 	var err error
 	err.Error() //@complete("E", Error)
 }
diff --git a/internal/lsp/testdata/func_rank/func_rank.go.in b/internal/lsp/testdata/func_rank/func_rank.go.in
index ca98324..0d0feeb 100644
--- a/internal/lsp/testdata/func_rank/func_rank.go.in
+++ b/internal/lsp/testdata/func_rank/func_rank.go.in
@@ -1,7 +1,7 @@
 package func_rank
 
 var stringAVar = "var"    //@item(stringAVar, "stringAVar", "string", "var")
-func stringBFunc() string { return "str" } //@item(stringBFunc, "stringBFunc()", "string", "func")
+func stringBFunc() string { return "str" } //@item(stringBFunc, "stringBFunc", "func() string", "func")
 type stringer struct{}    //@item(stringer, "stringer", "struct{...}", "struct")
 
 func _() stringer //@complete("tr", stringer, stringAVar, stringBFunc)
diff --git a/internal/lsp/testdata/funcvalue/func_value.go b/internal/lsp/testdata/funcvalue/func_value.go
index a36a4a2..913fcbc 100644
--- a/internal/lsp/testdata/funcvalue/func_value.go
+++ b/internal/lsp/testdata/funcvalue/func_value.go
@@ -4,19 +4,19 @@
 	return 0
 }
 
-var _ = fooFunc() //@item(fvFooFuncCall, "fooFunc()", "int", "func")
+var _ = fooFunc() //@item(fvFooFuncCall, "fooFunc", "func() int", "func")
 
 var fooVar = func() int { //@item(fvFooVar, "fooVar", "func() int", "var")
 	return 0
 }
 
-var _ = fooVar() //@item(fvFooVarCall, "fooVar()", "int", "var")
+var _ = fooVar() //@item(fvFooVarCall, "fooVar", "func() int", "var")
 
 type myFunc func() int
 
 var fooType myFunc = fooVar //@item(fvFooType, "fooType", "myFunc", "var")
 
-var _ = fooType() //@item(fvFooTypeCall, "fooType()", "int", "var")
+var _ = fooType() //@item(fvFooTypeCall, "fooType", "func() int", "var")
 
 func _() {
 	var f func() int
diff --git a/internal/lsp/testdata/good/good0.go b/internal/lsp/testdata/good/good0.go
index 4e204e3..ceb26c5 100644
--- a/internal/lsp/testdata/good/good0.go
+++ b/internal/lsp/testdata/good/good0.go
@@ -1,6 +1,6 @@
 package good //@diag("package", "", "")
 
-func stuff() { //@item(good_stuff, "stuff()", "", "func")
+func stuff() { //@item(good_stuff, "stuff", "func()", "func")
 	x := 5
 	random2(x)
 }
diff --git a/internal/lsp/testdata/good/good1.go b/internal/lsp/testdata/good/good1.go
index b595950..95a9250 100644
--- a/internal/lsp/testdata/good/good1.go
+++ b/internal/lsp/testdata/good/good1.go
@@ -4,12 +4,12 @@
 	"golang.org/x/tools/internal/lsp/types" //@item(types_import, "types", "\"golang.org/x/tools/internal/lsp/types\"", "package")
 )
 
-func random() int { //@item(good_random, "random()", "int", "func")
+func random() int { //@item(good_random, "random", "func() int", "func")
 	y := 6 + 7
 	return y
 }
 
-func random2(y int) int { //@item(good_random2, "random2(y int)", "int", "func"),item(good_y_param, "y", "int", "parameter")
+func random2(y int) int { //@item(good_random2, "random2", "func(y int) int", "func"),item(good_y_param, "y", "int", "parameter")
 	//@complete("", good_y_param, types_import, good_random, good_random2, good_stuff)
 	var b types.Bob = &types.X{}
 	if _, ok := b.(*types.X); ok { //@complete("X", X_struct, Y_struct, Bob_interface)
diff --git a/internal/lsp/testdata/selector/selector.go.in b/internal/lsp/testdata/selector/selector.go.in
index 10c3912..77df003 100644
--- a/internal/lsp/testdata/selector/selector.go.in
+++ b/internal/lsp/testdata/selector/selector.go.in
@@ -19,9 +19,9 @@
 type jack struct { c int } //@item(c, "c", "int", "field")
 type jill struct { d int }
 
-func (b *bob) george() *george {} //@item(george, "george()", "*george", "method")
+func (b *bob) george() *george {} //@item(george, "george", "func() *george", "method")
 func (g *george) jack() *jack {}
-func (j *jack) jill() *jill {} //@item(jill, "jill()", "*jill", "method")
+func (j *jack) jill() *jill {} //@item(jill, "jill", "func() *jill", "method")
 
 func _() {
 	b := &bob{}
diff --git a/internal/lsp/testdata/snippets/snippets.go b/internal/lsp/testdata/snippets/snippets.go
index 0cf9232..ee56eb3 100644
--- a/internal/lsp/testdata/snippets/snippets.go
+++ b/internal/lsp/testdata/snippets/snippets.go
@@ -1,14 +1,14 @@
 package snippets
 
-func foo(i int, b bool) {} //@item(snipFoo, "foo(i int, b bool)", "", "func")
-func bar(fn func()) func()    {} //@item(snipBar, "bar(fn func())", "", "func")
+func foo(i int, b bool) {} //@item(snipFoo, "foo", "func(i int, b bool)", "func")
+func bar(fn func()) func()    {} //@item(snipBar, "bar", "func(fn func())", "func")
 
 type Foo struct {
 	Bar int //@item(snipFieldBar, "Bar", "int", "field")
 }
 
-func (Foo) Baz() func() {} //@item(snipMethodBaz, "Baz()", "func()", "method")
-func (Foo) BazBar() func() {} //@item(snipMethodBazBar, "BazBar()", "func()", "method")
+func (Foo) Baz() func() {} //@item(snipMethodBaz, "Baz", "func() func()", "method")
+func (Foo) BazBar() func() {} //@item(snipMethodBazBar, "BazBar", "func() func()", "method")
 
 func _() {
 	f //@snippet(" //", snipFoo, "foo(${1})", "foo(${1:i int}, ${2:b bool})")
diff --git a/internal/lsp/testdata/testy/testy.go b/internal/lsp/testdata/testy/testy.go
index ba1205e..1a738d7 100644
--- a/internal/lsp/testdata/testy/testy.go
+++ b/internal/lsp/testdata/testy/testy.go
@@ -1,5 +1,5 @@
 package testy
 
-func a() { //@mark(identA, "a"),item(funcA, "a()", "", "func"),refs("a", identA, testyA)
+func a() { //@mark(identA, "a"),item(funcA, "a", "func()", "func"),refs("a", identA, testyA)
 	//@complete("", funcA)
 }