internal/lsp: order struct fields completions by definition

Previously struct fields completions are ordered alphabetically.
Now it is ordered by its order in definition.

Fixes golang/go#42626

Change-Id: I8c404205b97fa9f1a5a66a95a84033b6f0f48eae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/270777
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Trust: Rebecca Stambler <rstambler@golang.org>
Trust: Robert Findley <rfindley@google.com>
diff --git a/gopls/internal/regtest/completion_test.go b/gopls/internal/regtest/completion_test.go
index 2651f59..5978f56 100644
--- a/gopls/internal/regtest/completion_test.go
+++ b/gopls/internal/regtest/completion_test.go
@@ -193,6 +193,54 @@
 	})
 }
 
+// Test the order of completion suggestions
+func TestStructLiteralCompletion(t *testing.T) {
+	const files = `
+-- go.mod --
+module mod.com
+
+-- foo.go --
+package foo
+
+type Foo struct {
+	c int
+	b int
+	a int
+}
+
+func f() {
+	foo := Foo{
+		
+	}
+}
+`
+
+	want := []string{"c", "b", "a"}
+
+	run(t, files, func(t *testing.T, env *Env) {
+		env.OpenFile("foo.go")
+		completions := env.Completion("foo.go", fake.Pos{
+			Line:   10,
+			Column: 0,
+		})
+
+		diff := compareCompletionResultsOnlyHead(want, completions.Items)
+		if diff != "" {
+			t.Fatal(diff)
+			return
+		}
+	})
+}
+
+func compareCompletionResultsOnlyHead(want []string, gotItems []protocol.CompletionItem) string {
+	for i := range want {
+		if want[i] != gotItems[i].Label {
+			return fmt.Sprintf("completion results are not the same: got %v, want %v", gotItems[i].Label, want[i])
+		}
+	}
+	return ""
+}
+
 func compareCompletionResults(want []string, gotItems []protocol.CompletionItem) string {
 	if len(gotItems) != len(want) {
 		return fmt.Sprintf("got %v completion(s), want %v", len(gotItems), len(want))
diff --git a/internal/lsp/source/completion/completion.go b/internal/lsp/source/completion/completion.go
index 78dac5b..b87154a 100644
--- a/internal/lsp/source/completion/completion.go
+++ b/internal/lsp/source/completion/completion.go
@@ -1522,6 +1522,7 @@
 		}
 	}
 
+	deltaScore := 0.0001
 	switch t := clInfo.clType.(type) {
 	case *types.Struct:
 		for i := 0; i < t.NumFields(); i++ {
@@ -1529,7 +1530,7 @@
 			if !addedFields[field] {
 				c.deepState.enqueue(candidate{
 					obj:   field,
-					score: highScore,
+					score: highScore - float64(i)*deltaScore,
 				})
 			}
 		}