internal/lsp/cache: build the workspace module deterministically

Iterating through the map means that the ordering changes, which may
result in us creating different workspace module files for the same
workspace. We should be careful to always create the same file.

Change-Id: I4ccd3f9ebbbe81bb062285fe9c3ad675bdf2e53a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/291493
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/internal/lsp/cache/snapshot.go b/internal/lsp/cache/snapshot.go
index 3bc9be3..7ecb1b8 100644
--- a/internal/lsp/cache/snapshot.go
+++ b/internal/lsp/cache/snapshot.go
@@ -1758,7 +1758,14 @@
 	goVersion := "1.12"
 
 	paths := make(map[string]span.URI)
-	for modURI := range modFiles {
+	var sortedModURIs []span.URI
+	for uri := range modFiles {
+		sortedModURIs = append(sortedModURIs, uri)
+	}
+	sort.Slice(sortedModURIs, func(i, j int) bool {
+		return sortedModURIs[i] < sortedModURIs[j]
+	})
+	for _, modURI := range sortedModURIs {
 		fh, err := fs.GetFile(ctx, modURI)
 		if err != nil {
 			return nil, err
@@ -1799,7 +1806,7 @@
 	}
 	// Go back through all of the modules to handle any of their replace
 	// statements.
-	for modURI := range modFiles {
+	for _, modURI := range sortedModURIs {
 		fh, err := fs.GetFile(ctx, modURI)
 		if err != nil {
 			return nil, err