internal/lsp: add recency check to avoid sending old diagnostics

This change uses snapshot IDs instead of file versions to determine if
diagnostics are stale.

Fixes golang/go#36601.

Change-Id: I7727a30222fecf2d7733fa013c6cee6338ffd968
Reviewed-on: https://go-review.googlesource.com/c/tools/+/215298
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
Rebecca Stambler 2020-01-17 13:12:00 -05:00
parent 351fb220e1
commit 633b092c1e
1 changed files with 19 additions and 4 deletions

View File

@ -113,20 +113,35 @@ func (s *Server) publishReports(ctx context.Context, snapshot source.Snapshot, r
withAnalysis: withAnalysis,
snapshotID: snapshot.ID(),
}
// We use the zero values if this is an unknown file.
delivered := s.delivered[fileID.URI]
// Reuse cached diagnostics and update the delivered map.
if fileID.Version >= delivered.version && equalDiagnostics(delivered.sorted, diagnostics) {
// Snapshot IDs are always increasing, so we use them instead of file
// versions to create the correct order for diagnostics.
// If we've already delivered diagnostics for a future snapshot for this file,
// do not deliver them.
if delivered.snapshotID > toSend.snapshotID {
// Do not update the delivered map since it already contains newer diagnostics.
continue
}
// Check if we should reuse the cached diagnostics.
if equalDiagnostics(delivered.sorted, diagnostics) {
// Make sure to update the delivered map.
s.delivered[fileID.URI] = toSend
continue
}
// If we've already delivered diagnostics with analyses for this file, for this snapshot,
// at this version, do not send diagnostics without analyses.
// If we've already delivered diagnostics for this file, at this
// snapshot, with analyses, do not send diagnostics without analyses.
if delivered.snapshotID == toSend.snapshotID && delivered.version == toSend.version &&
delivered.withAnalysis && !toSend.withAnalysis {
// Do not update the delivered map since it already contains better diagnostics.
continue
}
if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
Diagnostics: toProtocolDiagnostics(diagnostics),
URI: protocol.NewURI(fileID.URI),