Skip to content

Commit 0b95e04

Browse files
committedJan 13, 2025·
gopls: filter out hints for closed files and make modernizers hints
- Document Analyzer.Severity to describe heuristics for how severity should be determined. - Filter out hint diagnostics for closed files. VS Code already suppresses hint diagnostics from the Problems tab, but other clients do not. This change makes the visibility of Hint diagnostics more similar across clients. - Downgrade 'modernize' to Hint level severity. Updates golang/go#70815 Change-Id: If93b57d25ed3eb8dc253a3c7ef016c4148086dc9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/641796 Reviewed-by: Alan Donovan <adonovan@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
1 parent 8f9869c commit 0b95e04

File tree

4 files changed

+81
-12
lines changed

4 files changed

+81
-12
lines changed
 

‎gopls/internal/cache/errors.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -270,15 +270,10 @@ func toSourceDiagnostic(srcAnalyzer *settings.Analyzer, gobDiag *gobDiagnostic)
270270
related = append(related, protocol.DiagnosticRelatedInformation(gobRelated))
271271
}
272272

273-
severity := srcAnalyzer.Severity()
274-
if severity == 0 {
275-
severity = protocol.SeverityWarning
276-
}
277-
278273
diag := &Diagnostic{
279274
URI: gobDiag.Location.URI,
280275
Range: gobDiag.Location.Range,
281-
Severity: severity,
276+
Severity: srcAnalyzer.Severity(),
282277
Code: gobDiag.Code,
283278
CodeHref: gobDiag.CodeHref,
284279
Source: DiagnosticSource(gobDiag.Source),

‎gopls/internal/server/diagnostics.go

+19
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"os"
1212
"path/filepath"
1313
"runtime"
14+
"slices"
1415
"sort"
1516
"strings"
1617
"sync"
@@ -511,6 +512,24 @@ func (s *server) diagnose(ctx context.Context, snapshot *cache.Snapshot) (diagMa
511512
// TODO(rfindley): here and above, we should avoid using the first result
512513
// if err is non-nil (though as of today it's OK).
513514
analysisDiags, err = golang.Analyze(ctx, snapshot, toAnalyze, s.progress)
515+
516+
// Filter out Hint diagnostics for closed files.
517+
// VS Code already omits Hint diagnostics in the Problems tab, but other
518+
// clients do not. This filter makes the visibility of Hints more similar
519+
// across clients.
520+
for uri, diags := range analysisDiags {
521+
if !snapshot.IsOpen(uri) {
522+
newDiags := slices.DeleteFunc(diags, func(diag *cache.Diagnostic) bool {
523+
return diag.Severity == protocol.SeverityHint
524+
})
525+
if len(newDiags) == 0 {
526+
delete(analysisDiags, uri)
527+
} else {
528+
analysisDiags[uri] = newDiags
529+
}
530+
}
531+
}
532+
514533
if err != nil {
515534
event.Error(ctx, "warning: analyzing package", err, append(snapshot.Labels(), label.Package.Of(keys.Join(moremaps.KeySlice(toDiagnose))))...)
516535
return

‎gopls/internal/settings/analysis.go

+32-6
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,35 @@ func (a *Analyzer) EnabledByDefault() bool { return !a.nonDefault }
8888
// TODO(rfindley): revisit.
8989
func (a *Analyzer) ActionKinds() []protocol.CodeActionKind { return a.actionKinds }
9090

91-
// Severity is the severity set for diagnostics reported by this
92-
// analyzer. If left unset it defaults to Warning.
91+
// Severity is the severity set for diagnostics reported by this analyzer.
92+
// The default severity is SeverityWarning.
9393
//
94-
// Note: diagnostics with severity protocol.SeverityHint do not show up in
95-
// the VS Code "problems" tab.
96-
func (a *Analyzer) Severity() protocol.DiagnosticSeverity { return a.severity }
94+
// While the LSP spec does not specify how severity should be used, here are
95+
// some guiding heuristics:
96+
// - Error: for parse and type errors, which would stop the build.
97+
// - Warning: for analyzer diagnostics reporting likely bugs.
98+
// - Info: for analyzer diagnostics that do not indicate bugs, but may
99+
// suggest inaccurate or superfluous code.
100+
// - Hint: for analyzer diagnostics that do not indicate mistakes, but offer
101+
// simplifications or modernizations. By their nature, hints should
102+
// generally carry quick fixes.
103+
//
104+
// The difference between Info and Hint is particularly subtle. Importantly,
105+
// Hint diagnostics do not appear in the Problems tab in VS Code, so they are
106+
// less intrusive than Info diagnostics. The rule of thumb is this: use Info if
107+
// the diagnostic is not a bug, but the author probably didn't mean to write
108+
// the code that way. Use Hint if the diagnostic is not a bug and the author
109+
// indended to write the code that way, but there is a simpler or more modern
110+
// way to express the same logic. An 'unused' diagnostic is Info level, since
111+
// the author probably didn't mean to check in unreachable code. A 'modernize'
112+
// or 'deprecated' diagnostic is Hint level, since the author intended to write
113+
// the code that way, but now there is a better way.
114+
func (a *Analyzer) Severity() protocol.DiagnosticSeverity {
115+
if a.severity == 0 {
116+
return protocol.SeverityWarning
117+
}
118+
return a.severity
119+
}
97120

98121
// Tags is extra tags (unnecessary, deprecated, etc) for diagnostics
99122
// reported by this analyzer.
@@ -109,6 +132,7 @@ func (a *Analyzer) String() string { return a.analyzer.String() }
109132
var DefaultAnalyzers = make(map[string]*Analyzer) // initialized below
110133

111134
func init() {
135+
// See [Analyzer.Severity] for guidance on setting analyzer severity below.
112136
analyzers := []*Analyzer{
113137
// The traditional vet suite:
114138
{analyzer: appends.Analyzer},
@@ -190,10 +214,12 @@ func init() {
190214
{analyzer: unusedparams.Analyzer, severity: protocol.SeverityInformation},
191215
{analyzer: unusedfunc.Analyzer, severity: protocol.SeverityInformation},
192216
{analyzer: unusedwrite.Analyzer, severity: protocol.SeverityInformation}, // uses go/ssa
193-
{analyzer: modernize.Analyzer, severity: protocol.SeverityInformation},
217+
{analyzer: modernize.Analyzer, severity: protocol.SeverityHint},
194218

195219
// type-error analyzers
196220
// These analyzers enrich go/types errors with suggested fixes.
221+
// Since they exist only to attach their fixes to type errors, their
222+
// severity is irrelevant.
197223
{analyzer: fillreturns.Analyzer},
198224
{analyzer: nonewvars.Analyzer},
199225
{analyzer: noresultvalues.Analyzer},

‎gopls/internal/test/integration/diagnostics/analysis_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,32 @@ func main() {
125125
}
126126
})
127127
}
128+
129+
func TestAnalysisFiltering(t *testing.T) {
130+
// This test checks that hint level diagnostics are only surfaced for open
131+
// files.
132+
133+
const src = `
134+
-- go.mod --
135+
module mod.com
136+
137+
go 1.20
138+
139+
-- a.go --
140+
package p
141+
142+
var x interface{}
143+
144+
-- b.go --
145+
package p
146+
147+
var y interface{}
148+
`
149+
Run(t, src, func(t *testing.T, env *Env) {
150+
env.OpenFile("a.go")
151+
env.AfterChange(
152+
Diagnostics(ForFile("a.go"), WithMessage("replaced by any")),
153+
NoDiagnostics(ForFile("b.go")),
154+
)
155+
})
156+
}

0 commit comments

Comments
 (0)
Please sign in to comment.