internal/lsp/cache: don't set context cancellation as a critical err

Fix a tricky race in gopls/internal/regtest/diagnostics.Test_Issue38211:
When reloading the workspace, we can encounter context cancellation if
the snapshot is cancelled, and can write this cancellation as a critical
error *before* the context is cloned, leading to a state where there is
a critical error that won't go away.

This should resolve test flakes reported in golang/go#44098.

For golang/go#44098

Change-Id: I41c0f49b2fe999131f4c31166e69b2cde85470b7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/419502
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
This commit is contained in:
Robert Findley 2022-07-26 17:58:48 -04:00
parent 8ea5687987
commit f560bc877f
1 changed files with 16 additions and 9 deletions

View File

@ -656,9 +656,14 @@ func (s *snapshot) loadWorkspace(ctx context.Context, firstAttempt bool) {
}
}()
// If we have multiple modules, we need to load them by paths.
var scopes []interface{}
var modDiagnostics []*source.Diagnostic
// TODO(rFindley): we should only locate template files on the first attempt,
// or guard it via a different mechanism.
s.locateTemplateFiles(ctx)
// Collect module paths to load by parsing go.mod files. If a module fails to
// parse, capture the parsing failure as a critical diagnostic.
var scopes []interface{} // scopes to load
var modDiagnostics []*source.Diagnostic // diagnostics for broken go.mod files
addError := func(uri span.URI, err error) {
modDiagnostics = append(modDiagnostics, &source.Diagnostic{
URI: uri,
@ -668,20 +673,22 @@ func (s *snapshot) loadWorkspace(ctx context.Context, firstAttempt bool) {
})
}
// TODO(rFindley): we should only locate template files on the first attempt,
// or guard it via a different mechanism.
s.locateTemplateFiles(ctx)
if len(s.workspace.getActiveModFiles()) > 0 {
for modURI := range s.workspace.getActiveModFiles() {
// Be careful not to add context cancellation errors as critical module
// errors.
fh, err := s.GetFile(ctx, modURI)
if err != nil {
addError(modURI, err)
if ctx.Err() == nil {
addError(modURI, err)
}
continue
}
parsed, err := s.ParseMod(ctx, fh)
if err != nil {
addError(modURI, err)
if ctx.Err() == nil {
addError(modURI, err)
}
continue
}
if parsed.File == nil || parsed.File.Module == nil {