internal/lsp: invalidate all packages on go.mod file changes

Previously, we were only invalidating workspace packages when the go.mod
changed, but we really need to be invalidating all known packages.

Fixes golang/go#40456

Change-Id: I9ad353a26ab40c74c7760ed7a1c5de517640cfab
Reviewed-on: https://go-review.googlesource.com/c/tools/+/245779
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/internal/lsp/cache/snapshot.go b/internal/lsp/cache/snapshot.go
index 6ea8e4f..fd5bcdc 100644
--- a/internal/lsp/cache/snapshot.go
+++ b/internal/lsp/cache/snapshot.go
@@ -803,11 +803,11 @@
 			result.modWhyHandle = nil
 		}
 		if currentFH.Kind() == source.Mod {
-			// If the view's go.mod file's contents have changed, invalidate the metadata
-			// for all of the packages in the workspace.
+			// If the view's go.mod file's contents have changed, invalidate the
+			// metadata for every known package in the snapshot.
 			if invalidateMetadata {
-				for id := range s.workspacePackages {
-					directIDs[id] = struct{}{}
+				for k := range s.packages {
+					directIDs[k.id] = struct{}{}
 				}
 			}
 			delete(result.parseModHandles, withoutURI)
diff --git a/internal/lsp/regtest/watch_test.go b/internal/lsp/regtest/watch_test.go
index 2dd7a09..75cac13 100644
--- a/internal/lsp/regtest/watch_test.go
+++ b/internal/lsp/regtest/watch_test.go
@@ -496,3 +496,80 @@
 		)
 	})
 }
+
+// Reproduce golang/go#40456.
+func TestChangeVersion(t *testing.T) {
+	const proxy = `
+-- example.com@v1.2.3/go.mod --
+module example.com
+
+go 1.12
+-- example.com@v1.2.3/blah/blah.go --
+package blah
+
+const Name = "Blah"
+
+func X(x int) {}
+-- example.com@v1.2.2/go.mod --
+module example.com
+
+go 1.12
+-- example.com@v1.2.2/blah/blah.go --
+package blah
+
+const Name = "Blah"
+
+func X() {}
+-- random.org@v1.2.3/go.mod --
+module random.org
+
+go 1.12
+-- random.org@v1.2.3/blah/blah.go --
+package hello
+
+const Name = "Hello"
+`
+	const mod = `
+-- go.mod --
+module mod.com
+
+go 1.12
+
+require example.com v1.2.2
+-- main.go --
+package main
+
+import "example.com/blah"
+
+func main() {
+	blah.X()
+}
+`
+	withOptions(WithProxyFiles(proxy)).run(t, mod, func(t *testing.T, env *Env) {
+		env.Await(
+			CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromInitialWorkspaceLoad), 1),
+		)
+		env.WriteWorkspaceFiles(map[string]string{
+			"go.mod": `module mod.com
+
+go 1.12
+
+require example.com v1.2.3
+`,
+			"main.go": `package main
+
+import (
+	"example.com/blah"
+)
+
+func main() {
+	blah.X(1)
+}
+`,
+		})
+		env.Await(
+			CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), 1),
+			NoDiagnostics("main.go"),
+		)
+	})
+}