internal/lsp: don't reload invalid build configurations unconditionally Previously, we would always reload views with invalid build configurations on every call to reloadWorkspace, even if the metadata had no reason to be treated as invalid. Fixes golang/go#42813 Change-Id: I9e0e493228916262908b81bc1b1ab1eb4e4eca9e Reviewed-on: https://go-review.googlesource.com/c/tools/+/274443 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> (cherry picked from commit 2ecf2a5d1b8adb93a4ca116a53f629f33a26f4e8) Reviewed-on: https://go-review.googlesource.com/c/tools/+/275436 Run-TryBot: Robert Findley <rfindley@google.com>
diff --git a/gopls/go.mod b/gopls/go.mod index 0977538..60253b2 100644 --- a/gopls/go.mod +++ b/gopls/go.mod
@@ -10,3 +10,5 @@ mvdan.cc/gofumpt v0.0.0-20200927160801-5bfeb2e70dd6 mvdan.cc/xurls/v2 v2.2.0 ) + +replace golang.org/x/tools => ../
diff --git a/gopls/internal/regtest/diagnostics_test.go b/gopls/internal/regtest/diagnostics_test.go index 90d0938..aef5ee8 100644 --- a/gopls/internal/regtest/diagnostics_test.go +++ b/gopls/internal/regtest/diagnostics_test.go
@@ -1515,3 +1515,22 @@ ) }) } + +func TestAdHocPackagesReloading(t *testing.T) { + const nomod = ` +-- main.go -- +package main + +func main() {} +` + run(t, nomod, func(t *testing.T, env *Env) { + env.OpenFile("main.go") + env.RegexpReplace("main.go", "{}", "{ var x int; }") // simulate typing + env.Await( + OnceMet( + CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1), + NoLogMatching(protocol.Info, "packages=1"), + ), + ) + }) +}
diff --git a/internal/lsp/cache/snapshot.go b/internal/lsp/cache/snapshot.go index 0faaacd..022c338 100644 --- a/internal/lsp/cache/snapshot.go +++ b/internal/lsp/cache/snapshot.go
@@ -937,29 +937,34 @@ // reloadWorkspace reloads the metadata for all invalidated workspace packages. func (s *snapshot) reloadWorkspace(ctx context.Context) error { - // If the view's build configuration is invalid, we cannot reload by - // package path. Just reload the directory instead. - if !s.ValidBuildConfiguration() { - return s.load(ctx, viewLoadScope("LOAD_INVALID_VIEW")) - } - // See which of the workspace packages are missing metadata. s.mu.Lock() + missingMetadata := len(s.workspacePackages) == 0 || len(s.metadata) == 0 pkgPathSet := map[packagePath]struct{}{} for id, pkgPath := range s.workspacePackages { + if s.metadata[id] != nil { + continue + } + missingMetadata = true + // Don't try to reload "command-line-arguments" directly. if pkgPath == "command-line-arguments" { continue } - if s.metadata[id] == nil { - pkgPathSet[pkgPath] = struct{}{} - } + pkgPathSet[pkgPath] = struct{}{} } s.mu.Unlock() + // If the view's build configuration is invalid, we cannot reload by + // package path. Just reload the directory instead. + if missingMetadata && !s.ValidBuildConfiguration() { + return s.load(ctx, viewLoadScope("LOAD_INVALID_VIEW")) + } + if len(pkgPathSet) == 0 { return nil } + var pkgPaths []interface{} for pkgPath := range pkgPathSet { pkgPaths = append(pkgPaths, pkgPath)