From 4e31bdea7810f35a2654fd9a81602f35d437d00f Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Thu, 6 Jan 2022 12:16:50 -0500 Subject: [PATCH] internal/lsp/cache: avoid panic in mod diags with redundant requires modfile.File.SetRequire panics on duplicate requires with conflicting versions. Avoid the panic by returning an error in this case. Skip directness diagnostics that run into this error, rather than invalidating all diagnostics. Fixes golang/go#50425 Change-Id: Ic6379ecc48581e7fd7b470ed295e449833c351dd Reviewed-on: https://go-review.googlesource.com/c/tools/+/376394 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Hyang-Ah Hana Kim gopls-CI: kokoro TryBot-Result: Gopher Robot --- internal/lsp/cache/mod_tidy.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/internal/lsp/cache/mod_tidy.go b/internal/lsp/cache/mod_tidy.go index 7c92746e54..f6c74c5d1b 100644 --- a/internal/lsp/cache/mod_tidy.go +++ b/internal/lsp/cache/mod_tidy.go @@ -212,7 +212,11 @@ func modTidyDiagnostics(ctx context.Context, snapshot source.Snapshot, pm *sourc // vice versa. srcDiag, err := directnessDiagnostic(pm.Mapper, req, snapshot.View().Options().ComputeEdits) if err != nil { - return nil, err + // We're probably in a bad state if we can't compute a + // directnessDiagnostic, but try to keep going so as to not suppress + // other, valid diagnostics. + event.Error(ctx, "computing directness diagnostic", err) + continue } diagnostics = append(diagnostics, srcDiag) } @@ -428,7 +432,14 @@ func switchDirectness(req *modfile.Require, m *protocol.ColumnMapper, computeEdi // Change the directness in the matching require statement. To avoid // reordering the require statements, rewrite all of them. var requires []*modfile.Require + seenVersions := make(map[string]string) for _, r := range copied.Require { + if seen := seenVersions[r.Mod.Path]; seen != "" && seen != r.Mod.Version { + // Avoid a panic in SetRequire below, which panics on conflicting + // versions. + return nil, fmt.Errorf("%q has conflicting versions: %q and %q", r.Mod.Path, seen, r.Mod.Version) + } + seenVersions[r.Mod.Path] = r.Mod.Version if r.Mod.Path == req.Mod.Path { requires = append(requires, &modfile.Require{ Mod: r.Mod,