internal/lsp: improve completion ordering workaround

Instead of making all completion candidates look like perfect matches
to VSCode, we now make all candidates match exactly like the first
candidate. This still causes VSCode to maintain the ordering from
gopls, but it fixes the absolute match score of gopls's top
candidates. This fixes interplay with other sources of VSCode
completions, such as user defined snippets.

Fixes golang/go#35782.

Change-Id: Ie7e489b76a02fb1353b63fa3c6fa42afee2e1441
Reviewed-on: https://go-review.googlesource.com/c/tools/+/208439
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go
index 9d1fb72..cc6aa87 100644
--- a/internal/lsp/completion.go
+++ b/internal/lsp/completion.go
@@ -54,16 +54,16 @@
 
 	items := toProtocolCompletionItems(candidates, rng, options)
 
-	if incompleteResults {
-		prefix := surrounding.Prefix()
-		for i := range items {
-			// We send the prefix as the filterText to trick VSCode into not
-			// reordering our candidates. All the candidates will appear to
-			// be a perfect match, so VSCode's fuzzy matching/ranking just
-			// maintains the natural "sortText" ordering. We can only do
-			// this in tandem with "incompleteResults" since otherwise
-			// client side filtering is important.
-			items[i].FilterText = prefix
+	if incompleteResults && len(items) > 1 {
+		for i := range items[1:] {
+			// Give all the candidaites the same filterText to trick VSCode
+			// into not reordering our candidates. All the candidates will
+			// appear to be equally good matches, so VSCode's fuzzy
+			// matching/ranking just maintains the natural "sortText"
+			// ordering. We can only do this in tandem with
+			// "incompleteResults" since otherwise client side filtering is
+			// important.
+			items[i].FilterText = items[0].FilterText
 		}
 	}