internal/lsp/cache: add a check for snapshot invariants

Check that some invariants are met when cloning the snapshot, in an
attempt to catch golang/go#43347

For golang/go#43347

Change-Id: I7404509027a1b0b0085133cba4d21d1006a52a57
Reviewed-on: https://go-review.googlesource.com/c/tools/+/280698
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Robert Findley <rfindley@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Rob Findley 2020-12-30 09:37:05 -05:00 committed by Robert Findley
parent b8413747bb
commit ef3185ba9c
1 changed files with 26 additions and 0 deletions

View File

@ -25,6 +25,7 @@ import (
"golang.org/x/tools/go/packages"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/lsp/debug/log"
"golang.org/x/tools/internal/lsp/debug/tag"
"golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/memoize"
@ -1231,6 +1232,29 @@ func generationName(v *View, snapshotID uint64) string {
return fmt.Sprintf("v%v/%v", v.id, snapshotID)
}
// checkSnapshotLocked verifies that some invariants are preserved on the
// snapshot.
func checkSnapshotLocked(ctx context.Context, s *snapshot) {
// Check that every go file for a workspace package is identified as
// belonging to that workspace package.
for wsID := range s.workspacePackages {
if m, ok := s.metadata[wsID]; ok {
for _, uri := range m.goFiles {
found := false
for _, id := range s.ids[uri] {
if id == wsID {
found = true
break
}
}
if !found {
log.Error.Logf(ctx, "workspace package %v not associated with %v", wsID, uri)
}
}
}
}
}
func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileChange, forceReloadMetadata bool) (*snapshot, bool) {
var vendorChanged bool
newWorkspace, workspaceChanged, workspaceReload := s.workspace.invalidate(ctx, changes)
@ -1238,6 +1262,8 @@ func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]*fileC
s.mu.Lock()
defer s.mu.Unlock()
checkSnapshotLocked(ctx, s)
newGen := s.view.session.cache.store.Generation(generationName(s.view, s.id+1))
bgCtx, cancel := context.WithCancel(bgCtx)
result := &snapshot{