gopls/internal/completion: fix issue 80268

When completing the argument to func foo(_ *[10]int), the existing
code can produce syntactically invalid code because it discards
a conversion to slice.

More precisely: in
func foo(p *[10]int) {}
func bar() {
	var array [10]int
	foo(arr<cursor>)
}
the completion at 'arr' was (*[10]int)(array), but the code should
have produced (*[10]int)(array[:]). [Even better would have been
&array, but that's not how the completion logic is organized.]

Fixes: golang/go#80268
Change-Id: Ief2ccc963d30cd275d8383b110fbd3b40661534f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/799560
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Madeline Kalil <mkalil@google.com>
diff --git a/gopls/internal/golang/completion/format.go b/gopls/internal/golang/completion/format.go
index ba50c4a..583cfe6 100644
--- a/gopls/internal/golang/completion/format.go
+++ b/gopls/internal/golang/completion/format.go
@@ -198,10 +198,15 @@
 		}
 	}
 
+	// replacing suffix with conv.suffix was wrong (Issue 80268)
+	// That produced `(*[10]int)(array)` for passing an
+	// array to a function expecting an array pointer. But
+	// `(*[10]int)(array[:])` is what is wanted.
+	// (conv.suffix is always ")" or empty)
 	if cand.convertTo != nil {
 		conv := c.formatConversion(cand.convertTo)
 		prefix = conv.prefix + prefix
-		suffix = conv.suffix
+		suffix = suffix + conv.suffix
 	}
 
 	if prefix != "" {
diff --git a/gopls/internal/test/integration/completion/completion_test.go b/gopls/internal/test/integration/completion/completion_test.go
index 9a2e591..cedb5f2 100644
--- a/gopls/internal/test/integration/completion/completion_test.go
+++ b/gopls/internal/test/integration/completion/completion_test.go
@@ -1638,3 +1638,46 @@
 		}
 	})
 }
+
+// ensure that completion converts the array to a slice
+func TestIssue80268(t *testing.T) {
+	const src = `
+-- go.mod --
+module mod.com
+go 1.22
+-- main.go --
+package example
+
+func foo(p *[10]int) {}
+
+func Bar() {
+	var array [10]int
+	foo(arr)
+}
+`
+	Run(t, src, func(t *testing.T, env *Env) {
+		env.OpenFile("main.go")
+		env.Await(env.DoneWithOpen())
+		loc := env.RegexpSearch("main.go", `foo\(arr()\)`)
+		completions := env.Completion(loc)
+		if len(completions.Items) == 0 {
+			t.Fatal("no completions found")
+		}
+		env.AcceptCompletion(loc, completions.Items[0])
+		env.Await(env.DoneWithChange())
+
+		fmt.Printf("New main.go content:\n%s\n", env.BufferText("main.go"))
+
+		var diags protocol.PublishDiagnosticsParams
+		env.Await(ReadDiagnostics("main.go", &diags))
+		if len(diags.Diagnostics) != 0 {
+			t.Errorf("unexpected diagnostics:\n")
+			for _, d := range diags.Diagnostics {
+				t.Errorf("Diagnostic: %d:%d: %s\n", d.Range.Start.Line, d.Range.Start.Character, d.Message)
+			}
+			for _, item := range completions.Items {
+				t.Errorf("Completion: %s (Kind: %v, Detail: %q)\n", item.Label, item.Kind, item.Detail)
+			}
+		}
+	})
+}