internal/lsp/source: sort references and implementations results

We should make sure to return deterministic results for these requests.

Fixes golang/go#40904

Change-Id: If10489e3eca0e1b6a5e449de851d332f2d91ceb4
Reviewed-on: https://go-review.googlesource.com/c/tools/+/250737
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/internal/lsp/source/implementation.go b/internal/lsp/source/implementation.go
index 76a27a0..bd5af1f 100644
--- a/internal/lsp/source/implementation.go
+++ b/internal/lsp/source/implementation.go
@@ -11,6 +11,7 @@
 	"go/ast"
 	"go/token"
 	"go/types"
+	"sort"
 
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/lsp/protocol"
@@ -42,6 +43,13 @@
 			Range: pr,
 		})
 	}
+	sort.Slice(locations, func(i, j int) bool {
+		li, lj := locations[i], locations[j]
+		if li.URI == lj.URI {
+			return protocol.CompareRange(li.Range, lj.Range) < 0
+		}
+		return li.URI < lj.URI
+	})
 	return locations, nil
 }
 
@@ -195,8 +203,10 @@
 	sourcePkg Package
 }
 
-var errBuiltin = errors.New("builtin object")
-var errNoObjectFound = errors.New("no object found")
+var (
+	errBuiltin       = errors.New("builtin object")
+	errNoObjectFound = errors.New("no object found")
+)
 
 // qualifiedObjsAtProtocolPos returns info for all the type.Objects
 // referenced at the given position. An object will be returned for
diff --git a/internal/lsp/source/references.go b/internal/lsp/source/references.go
index 1eb8308..204e185 100644
--- a/internal/lsp/source/references.go
+++ b/internal/lsp/source/references.go
@@ -9,6 +9,7 @@
 	"go/ast"
 	"go/token"
 	"go/types"
+	"sort"
 
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/lsp/protocol"
@@ -40,7 +41,22 @@
 	if err != nil {
 		return nil, err
 	}
-	return references(ctx, s, qualifiedObjs, includeDeclaration)
+	refs, err := references(ctx, s, qualifiedObjs, includeDeclaration)
+	if err != nil {
+		return nil, err
+	}
+	toSort := refs
+	if includeDeclaration {
+		toSort = refs[1:]
+	}
+	sort.Slice(toSort, func(i, j int) bool {
+		x := span.CompareURI(toSort[i].URI(), toSort[j].URI())
+		if x == 0 {
+			return toSort[i].ident.Pos() < toSort[j].ident.Pos()
+		}
+		return x < 0
+	})
+	return refs, nil
 }
 
 // references is a helper function to avoid recomputing qualifiedObjsAtProtocolPos.