gopls/internal/lsp: differentiate govulncheck/vulncheck imports diags

Use different diagnostic source names for diagnostics from govulncheck
run ("govulncheck") and diagnostics from gopls's imports analysis
("vulncheck imports").

Fixes golang/vscode-go#2575

Change-Id: Ic79418146e4793bfc35fbf68d7539c7f0df1a636
Reviewed-on: https://go-review.googlesource.com/c/tools/+/461556
Auto-Submit: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Suzy Mueller <suzmue@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/gopls/internal/lsp/command.go b/gopls/internal/lsp/command.go
index a1ff862..cb3065f 100644
--- a/gopls/internal/lsp/command.go
+++ b/gopls/internal/lsp/command.go
@@ -223,7 +223,7 @@
 			c.s.clearDiagnosticSource(modCheckUpgradesSource)
 		}
 
-		if args.DiagnosticSource == "" || args.DiagnosticSource == string(source.Vulncheck) {
+		if args.DiagnosticSource == "" || args.DiagnosticSource == string(source.Govulncheck) {
 			deps.snapshot.View().SetVulnerabilities(args.URI.SpanURI(), nil)
 			c.s.clearDiagnosticSource(modVulncheckSource)
 		}
diff --git a/gopls/internal/lsp/diagnostics.go b/gopls/internal/lsp/diagnostics.go
index a58f404..e473bca 100644
--- a/gopls/internal/lsp/diagnostics.go
+++ b/gopls/internal/lsp/diagnostics.go
@@ -39,7 +39,7 @@
 	orphanedSource
 	workSource
 	modCheckUpgradesSource
-	modVulncheckSource
+	modVulncheckSource // source.Govulncheck + source.Vulncheck
 )
 
 // A diagnosticReport holds results for a single diagnostic source.
diff --git a/gopls/internal/lsp/mod/diagnostics.go b/gopls/internal/lsp/mod/diagnostics.go
index fdab833..7b598cf 100644
--- a/gopls/internal/lsp/mod/diagnostics.go
+++ b/gopls/internal/lsp/mod/diagnostics.go
@@ -191,20 +191,20 @@
 		return nil, err
 	}
 
-	fromGovulncheck := true
+	diagSource := source.Govulncheck
 	vs := snapshot.View().Vulnerabilities(fh.URI())[fh.URI()]
 	if vs == nil && snapshot.View().Options().Vulncheck == source.ModeVulncheckImports {
 		vs, err = snapshot.ModVuln(ctx, fh.URI())
 		if err != nil {
 			return nil, err
 		}
-		fromGovulncheck = false
+		diagSource = source.Vulncheck
 	}
 	if vs == nil || len(vs.Vulns) == 0 {
 		return nil, nil
 	}
 
-	suggestRunOrResetGovulncheck, err := suggestGovulncheckAction(fromGovulncheck, fh.URI())
+	suggestRunOrResetGovulncheck, err := suggestGovulncheckAction(diagSource == source.Govulncheck, fh.URI())
 	if err != nil {
 		// must not happen
 		return nil, err // TODO: bug report
@@ -310,8 +310,8 @@
 				URI:            fh.URI(),
 				Range:          rng,
 				Severity:       protocol.SeverityWarning,
-				Source:         source.Vulncheck,
-				Message:        getVulnMessage(req.Mod.Path, warning, true, fromGovulncheck),
+				Source:         diagSource,
+				Message:        getVulnMessage(req.Mod.Path, warning, true, diagSource == source.Govulncheck),
 				SuggestedFixes: warningFixes,
 				Related:        relatedInfo,
 			})
@@ -322,8 +322,8 @@
 				URI:            fh.URI(),
 				Range:          rng,
 				Severity:       protocol.SeverityInformation,
-				Source:         source.Vulncheck,
-				Message:        getVulnMessage(req.Mod.Path, info, false, fromGovulncheck),
+				Source:         diagSource,
+				Message:        getVulnMessage(req.Mod.Path, info, false, diagSource == source.Govulncheck),
 				SuggestedFixes: infoFixes,
 				Related:        relatedInfo,
 			})
@@ -365,8 +365,8 @@
 				URI:            fh.URI(),
 				Range:          rng,
 				Severity:       protocol.SeverityWarning,
-				Source:         source.Vulncheck,
-				Message:        getVulnMessage(stdlib, warning, true, fromGovulncheck),
+				Source:         diagSource,
+				Message:        getVulnMessage(stdlib, warning, true, diagSource == source.Govulncheck),
 				SuggestedFixes: fixes,
 				Related:        relatedInfo,
 			})
@@ -377,8 +377,8 @@
 				URI:            fh.URI(),
 				Range:          rng,
 				Severity:       protocol.SeverityInformation,
-				Source:         source.Vulncheck,
-				Message:        getVulnMessage(stdlib, info, false, fromGovulncheck),
+				Source:         diagSource,
+				Message:        getVulnMessage(stdlib, info, false, diagSource == source.Govulncheck),
 				SuggestedFixes: fixes,
 				Related:        relatedInfo,
 			})
@@ -396,7 +396,7 @@
 	if fromGovulncheck {
 		resetVulncheck, err := command.NewResetGoModDiagnosticsCommand("Reset govulncheck result", command.ResetGoModDiagnosticsArgs{
 			URIArg:           command.URIArg{URI: protocol.DocumentURI(uri)},
-			DiagnosticSource: string(source.Vulncheck),
+			DiagnosticSource: string(source.Govulncheck),
 		})
 		if err != nil {
 			return source.SuggestedFix{}, err
diff --git a/gopls/internal/lsp/source/view.go b/gopls/internal/lsp/source/view.go
index 5f4e3f5..c581286 100644
--- a/gopls/internal/lsp/source/view.go
+++ b/gopls/internal/lsp/source/view.go
@@ -840,7 +840,8 @@
 	ModTidyError             DiagnosticSource = "go mod tidy"
 	OptimizationDetailsError DiagnosticSource = "optimizer details"
 	UpgradeNotification      DiagnosticSource = "upgrade available"
-	Vulncheck                DiagnosticSource = "govulncheck"
+	Vulncheck                DiagnosticSource = "vulncheck imports"
+	Govulncheck              DiagnosticSource = "govulncheck"
 	TemplateError            DiagnosticSource = "template"
 	WorkFileError            DiagnosticSource = "go.work file"
 )
diff --git a/gopls/internal/regtest/misc/vuln_test.go b/gopls/internal/regtest/misc/vuln_test.go
index e311356..8badc87 100644
--- a/gopls/internal/regtest/misc/vuln_test.go
+++ b/gopls/internal/regtest/misc/vuln_test.go
@@ -20,6 +20,7 @@
 	"golang.org/x/tools/gopls/internal/lsp/command"
 	"golang.org/x/tools/gopls/internal/lsp/protocol"
 	. "golang.org/x/tools/gopls/internal/lsp/regtest"
+	"golang.org/x/tools/gopls/internal/lsp/source"
 	"golang.org/x/tools/gopls/internal/lsp/tests/compare"
 	"golang.org/x/tools/gopls/internal/vulncheck"
 	"golang.org/x/tools/gopls/internal/vulncheck/vulntest"
@@ -502,6 +503,7 @@
 					{
 						msg:      "golang.org/amod has known vulnerabilities GO-2022-01, GO-2022-03.",
 						severity: protocol.SeverityInformation,
+						source:   string(source.Vulncheck),
 						codeActions: []string{
 							"Run govulncheck to verify",
 							"Upgrade to v1.0.6",
@@ -521,6 +523,7 @@
 					{
 						msg:      "golang.org/bmod has a vulnerability GO-2022-02.",
 						severity: protocol.SeverityInformation,
+						source:   string(source.Vulncheck),
 						codeActions: []string{
 							"Run govulncheck to verify",
 						},
@@ -654,6 +657,7 @@
 					{
 						msg:      "golang.org/amod has a vulnerability used in the code: GO-2022-01.",
 						severity: protocol.SeverityWarning,
+						source:   string(source.Govulncheck),
 						codeActions: []string{
 							"Upgrade to v1.0.4",
 							"Upgrade to latest",
@@ -667,6 +671,7 @@
 					{
 						msg:      "golang.org/amod has a vulnerability GO-2022-03 that is not used in the code.",
 						severity: protocol.SeverityInformation,
+						source:   string(source.Govulncheck),
 						codeActions: []string{
 							"Upgrade to v1.0.6",
 							"Upgrade to latest",
@@ -690,6 +695,7 @@
 					{
 						msg:      "golang.org/bmod has a vulnerability used in the code: GO-2022-02.",
 						severity: protocol.SeverityWarning,
+						source:   string(source.Govulncheck),
 						codeActions: []string{
 							"Reset govulncheck result", // no fix, but we should give an option to reset.
 						},
@@ -817,6 +823,7 @@
 					{
 						msg:      "golang.org/bmod has a vulnerability GO-2022-02 that is not used in the code.",
 						severity: protocol.SeverityInformation,
+						source:   string(source.Govulncheck),
 						codeActions: []string{
 							"Reset govulncheck result",
 						},
@@ -879,8 +886,8 @@
 			t.Errorf("no diagnostic at %q matching %q found\n", pattern, w.msg)
 			continue
 		}
-		if diag.Severity != w.severity {
-			t.Errorf("incorrect severity for %q, want %s got %s\n", w.msg, w.severity, diag.Severity)
+		if diag.Severity != w.severity || diag.Source != w.source {
+			t.Errorf("incorrect (severity, source) for %q, want (%s, %s) got (%s, %s)\n", w.msg, w.severity, w.source, diag.Severity, diag.Source)
 		}
 		sort.Slice(w.relatedInfo, func(i, j int) bool { return w.relatedInfo[i].less(w.relatedInfo[j]) })
 		if got, want := summarizeRelatedInfo(diag.RelatedInformation), w.relatedInfo; !cmp.Equal(got, want) {
@@ -937,6 +944,8 @@
 	// relatedInfo is related info message prefixed by the file base.
 	// See summarizeRelatedInfo.
 	relatedInfo []vulnRelatedInfo
+	// diagnostic source.
+	source string
 }
 
 func (i vulnRelatedInfo) less(j vulnRelatedInfo) bool {