gopls/internal/settings: factor analyzer suites This CL changes gopls' registration of analyzers to make use of the vet.Suite and fix.Suite constants so that as new analyzers are added, gopls will pick them up automatically. (We had forgotten the slicesbackward analyzer.) Also: - add no-duplicate assertion. - remove now-redundant goplsexport hack. Change-Id: I82f3482f4ae8c0a419aa612189ffc43bea1dcad4 Reviewed-on: https://go-review.googlesource.com/c/tools/+/787060 Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: Madeline Kalil <mkalil@google.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/go/analysis/passes/modernize/export_test.go b/go/analysis/passes/modernize/export_test.go new file mode 100644 index 0000000..0823331 --- /dev/null +++ b/go/analysis/passes/modernize/export_test.go
@@ -0,0 +1,12 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file exposes yet-unpublished analyzers to the tests. + +package modernize + +var ( + SlicesBackwardAnalyzer = slicesBackwardAnalyzer + UnsafeFuncsAnalyzer = unsafeFuncsAnalyzer +)
diff --git a/go/analysis/passes/modernize/modernize.go b/go/analysis/passes/modernize/modernize.go index 8049127..1046876 100644 --- a/go/analysis/passes/modernize/modernize.go +++ b/go/analysis/passes/modernize/modernize.go
@@ -35,11 +35,8 @@ var Suite = []*analysis.Analyzer{ AnyAnalyzer, AtomicTypesAnalyzer, - // AppendClippedAnalyzer, // not nil-preserving! - // BLoopAnalyzer, // may skew benchmark results, see golang/go#74967 EmbedLitAnalyzer, ErrorsAsTypeAnalyzer, - // FmtAppendfAnalyzer, // makes code less clear, see golang/go#77581 ForVarAnalyzer, MapsLoopAnalyzer, MinMaxAnalyzer, @@ -48,9 +45,8 @@ PlusBuildAnalyzer, RangeIntAnalyzer, ReflectTypeForAnalyzer, - slicesBackwardAnalyzer, + slicesBackwardAnalyzer, // awaiting public symbol SlicesContainsAnalyzer, - // SlicesDeleteAnalyzer, // not nil-preserving! SlicesSortAnalyzer, StdIteratorsAnalyzer, StringsCutAnalyzer, @@ -58,8 +54,15 @@ StringsSeqAnalyzer, StringsBuilderAnalyzer, TestingContextAnalyzer, - unsafeFuncsAnalyzer, + unsafeFuncsAnalyzer, // awaiting public symbol WaitGroupGoAnalyzer, + + // Not included: + // + // AppendClippedAnalyzer, // not nil-preserving + // BLoopAnalyzer, // may skew benchmark results, see golang/go#74967 + // FmtAppendfAnalyzer, // makes code less clear, see golang/go#77581 + // SlicesDeleteAnalyzer, // not nil-preserving } // -- helpers --
diff --git a/go/analysis/passes/modernize/modernize_test.go b/go/analysis/passes/modernize/modernize_test.go index 9532c0c..bc8ecfb 100644 --- a/go/analysis/passes/modernize/modernize_test.go +++ b/go/analysis/passes/modernize/modernize_test.go
@@ -9,7 +9,6 @@ . "golang.org/x/tools/go/analysis/analysistest" "golang.org/x/tools/go/analysis/passes/modernize" - "golang.org/x/tools/internal/goplsexport" "golang.org/x/tools/internal/testenv" ) @@ -94,7 +93,7 @@ func TestSlicesBackward(t *testing.T) { testenv.NeedsGo1Point(t, 23) - RunWithSuggestedFixes(t, TestData(), goplsexport.SlicesBackwardModernizer, "slicesbackward") + RunWithSuggestedFixes(t, TestData(), modernize.SlicesBackwardAnalyzer, "slicesbackward") } func TestSlicesContains(t *testing.T) { @@ -132,7 +131,7 @@ } func TestUnsafeFuncs(t *testing.T) { - RunWithSuggestedFixes(t, TestData(), goplsexport.UnsafeFuncsModernizer, "unsafefuncs") + RunWithSuggestedFixes(t, TestData(), modernize.UnsafeFuncsAnalyzer, "unsafefuncs") } func TestWaitGroupGo(t *testing.T) {
diff --git a/go/analysis/passes/modernize/slicesbackward.go b/go/analysis/passes/modernize/slicesbackward.go index 305b5e5..02cd30a 100644 --- a/go/analysis/passes/modernize/slicesbackward.go +++ b/go/analysis/passes/modernize/slicesbackward.go
@@ -18,12 +18,12 @@ "golang.org/x/tools/internal/analysis/analyzerutil" typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex" "golang.org/x/tools/internal/astutil" - "golang.org/x/tools/internal/goplsexport" "golang.org/x/tools/internal/refactor" "golang.org/x/tools/internal/typesinternal/typeindex" "golang.org/x/tools/internal/versions" ) +// TODO(adonovan): needs a proposal for a public symbol. var slicesBackwardAnalyzer = &analysis.Analyzer{ Name: "slicesbackward", Doc: analyzerutil.MustExtractDoc(doc, "slicesbackward"), @@ -35,11 +35,6 @@ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesbackward", } -func init() { - // Export to gopls until this is a published modernizer. - goplsexport.SlicesBackwardModernizer = slicesBackwardAnalyzer -} - // slicesbackward offers a fix to replace a manually-written backward loop: // // for i := len(s) - 1; i >= 0; i-- {
diff --git a/go/analysis/passes/modernize/unsafefuncs.go b/go/analysis/passes/modernize/unsafefuncs.go index 91c2f37..34c135c 100644 --- a/go/analysis/passes/modernize/unsafefuncs.go +++ b/go/analysis/passes/modernize/unsafefuncs.go
@@ -16,7 +16,6 @@ "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/internal/analysis/analyzerutil" "golang.org/x/tools/internal/astutil" - "golang.org/x/tools/internal/goplsexport" "golang.org/x/tools/internal/refactor" "golang.org/x/tools/internal/typesinternal" "golang.org/x/tools/internal/versions" @@ -29,6 +28,7 @@ // func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType // func SliceData(slice []ArbitraryType) *ArbitraryType +// TODO(adonovan): needs a proposal for a public symbol. var unsafeFuncsAnalyzer = &analysis.Analyzer{ Name: "unsafefuncs", Doc: analyzerutil.MustExtractDoc(doc, "unsafefuncs"), @@ -37,11 +37,6 @@ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#unsafefuncs", } -func init() { - // Export to gopls until this is a published modernizer. - goplsexport.UnsafeFuncsModernizer = unsafeFuncsAnalyzer -} - func unsafefuncs(pass *analysis.Pass) (any, error) { // Short circuit if the package doesn't use unsafe. // (In theory one could use some imported alias of unsafe.Pointer,
diff --git a/gopls/doc/analyzers.md b/gopls/doc/analyzers.md index 783919a..8cbe47e 100644 --- a/gopls/doc/analyzers.md +++ b/gopls/doc/analyzers.md
@@ -4017,6 +4017,30 @@ Package documentation: [simplifyslice](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyslice) +<a id='slicesbackward'></a> +## `slicesbackward`: replace backward loops over slices with slices.Backward + +The slicesbackward analyzer suggests replacing manually-written backward loops of the form + + for i := len(s) - 1; i >= 0; i-- { + use(s[i]) + } + +with the more readable Go 1.23 style using slices.Backward: + + for _, v := range slices.Backward(s) { + use(v) + } + +If the loop index is needed beyond just indexing into the slice, both the index and value variables are kept: + + for i, v := range slices.Backward(s) { ... } + + +Default: on. + +Package documentation: [slicesbackward](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesbackward) + <a id='slicescontains'></a> ## `slicescontains`: replace loops with slices.Contains or slices.ContainsFunc
diff --git a/gopls/internal/doc/api.json b/gopls/internal/doc/api.json index 975c660..290c900 100644 --- a/gopls/internal/doc/api.json +++ b/gopls/internal/doc/api.json
@@ -1677,6 +1677,12 @@ "Status": "" }, { + "Name": "\"slicesbackward\"", + "Doc": "replace backward loops over slices with slices.Backward\n\nThe slicesbackward analyzer suggests replacing manually-written backward\nloops of the form\n\n\tfor i := len(s) - 1; i \u003e= 0; i-- {\n\t use(s[i])\n\t}\n\nwith the more readable Go 1.23 style using slices.Backward:\n\n\tfor _, v := range slices.Backward(s) {\n\t use(v)\n\t}\n\nIf the loop index is needed beyond just indexing into the slice, both\nthe index and value variables are kept:\n\n\tfor i, v := range slices.Backward(s) { ... }", + "Default": "true", + "Status": "" + }, + { "Name": "\"slicescontains\"", "Doc": "replace loops with slices.Contains or slices.ContainsFunc\n\nThe slicescontains analyzer simplifies loops that check for the existence of\nan element in a slice. It replaces them with calls to `slices.Contains` or\n`slices.ContainsFunc`, which were added in Go 1.21.\n\nIf the expression for the target element has side effects, this\ntransformation will cause those effects to occur only once, not\nonce per tested slice element.", "Default": "true", @@ -3672,6 +3678,12 @@ "Default": true }, { + "Name": "slicesbackward", + "Doc": "replace backward loops over slices with slices.Backward\n\nThe slicesbackward analyzer suggests replacing manually-written backward\nloops of the form\n\n\tfor i := len(s) - 1; i \u003e= 0; i-- {\n\t use(s[i])\n\t}\n\nwith the more readable Go 1.23 style using slices.Backward:\n\n\tfor _, v := range slices.Backward(s) {\n\t use(v)\n\t}\n\nIf the loop index is needed beyond just indexing into the slice, both\nthe index and value variables are kept:\n\n\tfor i, v := range slices.Backward(s) { ... }", + "URL": "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesbackward", + "Default": true + }, + { "Name": "slicescontains", "Doc": "replace loops with slices.Contains or slices.ContainsFunc\n\nThe slicescontains analyzer simplifies loops that check for the existence of\nan element in a slice. It replaces them with calls to `slices.Contains` or\n`slices.ContainsFunc`, which were added in Go 1.21.\n\nIf the expression for the target element has side effects, this\ntransformation will cause those effects to occur only once, not\nonce per tested slice element.", "URL": "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicescontains",
diff --git a/gopls/internal/settings/analysis.go b/gopls/internal/settings/analysis.go index 7cd71dd..247d7b7 100644 --- a/gopls/internal/settings/analysis.go +++ b/gopls/internal/settings/analysis.go
@@ -6,55 +6,21 @@ import ( "log" - "slices" "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/analysis/passes/appends" - "golang.org/x/tools/go/analysis/passes/asmdecl" - "golang.org/x/tools/go/analysis/passes/assign" - "golang.org/x/tools/go/analysis/passes/atomic" "golang.org/x/tools/go/analysis/passes/atomicalign" - "golang.org/x/tools/go/analysis/passes/bools" - "golang.org/x/tools/go/analysis/passes/buildtag" - "golang.org/x/tools/go/analysis/passes/cgocall" - "golang.org/x/tools/go/analysis/passes/composite" - "golang.org/x/tools/go/analysis/passes/copylock" "golang.org/x/tools/go/analysis/passes/deepequalerrors" - "golang.org/x/tools/go/analysis/passes/defers" - "golang.org/x/tools/go/analysis/passes/directive" - "golang.org/x/tools/go/analysis/passes/errorsas" "golang.org/x/tools/go/analysis/passes/fieldalignment" - "golang.org/x/tools/go/analysis/passes/framepointer" - "golang.org/x/tools/go/analysis/passes/hostport" - "golang.org/x/tools/go/analysis/passes/httpresponse" - "golang.org/x/tools/go/analysis/passes/ifaceassert" "golang.org/x/tools/go/analysis/passes/inline" - "golang.org/x/tools/go/analysis/passes/loopclosure" - "golang.org/x/tools/go/analysis/passes/lostcancel" "golang.org/x/tools/go/analysis/passes/modernize" - "golang.org/x/tools/go/analysis/passes/nilfunc" "golang.org/x/tools/go/analysis/passes/nilness" - "golang.org/x/tools/go/analysis/passes/printf" "golang.org/x/tools/go/analysis/passes/scannererr" "golang.org/x/tools/go/analysis/passes/shadow" - "golang.org/x/tools/go/analysis/passes/shift" - "golang.org/x/tools/go/analysis/passes/sigchanyzer" - "golang.org/x/tools/go/analysis/passes/slog" "golang.org/x/tools/go/analysis/passes/sortslice" "golang.org/x/tools/go/analysis/passes/sqlrowserr" - "golang.org/x/tools/go/analysis/passes/stdmethods" - "golang.org/x/tools/go/analysis/passes/stdversion" - "golang.org/x/tools/go/analysis/passes/stringintconv" - "golang.org/x/tools/go/analysis/passes/structtag" - "golang.org/x/tools/go/analysis/passes/testinggoroutine" - "golang.org/x/tools/go/analysis/passes/tests" - "golang.org/x/tools/go/analysis/passes/timeformat" - "golang.org/x/tools/go/analysis/passes/unmarshal" - "golang.org/x/tools/go/analysis/passes/unreachable" - "golang.org/x/tools/go/analysis/passes/unsafeptr" - "golang.org/x/tools/go/analysis/passes/unusedresult" "golang.org/x/tools/go/analysis/passes/unusedwrite" - "golang.org/x/tools/go/analysis/passes/waitgroup" + "golang.org/x/tools/go/analysis/suite/fix" + "golang.org/x/tools/go/analysis/suite/vet" "golang.org/x/tools/gopls/internal/analysis/deprecated" "golang.org/x/tools/gopls/internal/analysis/embeddirective" "golang.org/x/tools/gopls/internal/analysis/errorsastypeshadow" @@ -73,11 +39,13 @@ "golang.org/x/tools/gopls/internal/analysis/writestring" "golang.org/x/tools/gopls/internal/analysis/yield" "golang.org/x/tools/gopls/internal/protocol" - "golang.org/x/tools/internal/goplsexport" "honnef.co/go/tools/analysis/lint" ) -var AllAnalyzers = slices.Concat(DefaultAnalyzers, StaticcheckAnalyzers) +// AllAnalyzers holds the list of Analyzers available to all gopls +// sessions, independent of build version. It is the source from which +// gopls/doc/analyzers.md is generated. +var AllAnalyzers = initAnalyzers() // Analyzer augments an [analysis.Analyzer] with additional LSP configuration. // @@ -160,143 +128,107 @@ // String returns the name of this analyzer. func (a *Analyzer) String() string { return a.analyzer.String() } -// DefaultAnalyzers holds the list of Analyzers available to all gopls -// sessions, independent of build version. It is the source from which -// gopls/doc/analyzers.md is generated. -var DefaultAnalyzers = []*Analyzer{ - // See [Analyzer.Severity] for guidance on setting analyzer severity below. +func initAnalyzers() (res []*Analyzer) { + seen := make(map[*analysis.Analyzer]bool) - // The traditional vet suite: - {analyzer: appends.Analyzer}, - {analyzer: asmdecl.Analyzer}, - {analyzer: assign.Analyzer}, - {analyzer: atomic.Analyzer}, - {analyzer: bools.Analyzer}, - {analyzer: buildtag.Analyzer}, - {analyzer: cgocall.Analyzer}, - {analyzer: composite.Analyzer}, - {analyzer: copylock.Analyzer}, - {analyzer: defers.Analyzer}, - { - analyzer: deprecated.Analyzer, - severity: protocol.SeverityHint, - tags: []protocol.DiagnosticTag{protocol.Deprecated}, - }, - {analyzer: directive.Analyzer}, - {analyzer: errorsas.Analyzer}, - {analyzer: framepointer.Analyzer}, - {analyzer: hostport.Analyzer}, - {analyzer: httpresponse.Analyzer}, - {analyzer: ifaceassert.Analyzer}, - {analyzer: loopclosure.Analyzer}, - {analyzer: lostcancel.Analyzer}, - {analyzer: nilfunc.Analyzer}, - {analyzer: printf.Analyzer}, - {analyzer: shift.Analyzer}, - {analyzer: sigchanyzer.Analyzer}, - {analyzer: slog.Analyzer}, - {analyzer: stdmethods.Analyzer}, - {analyzer: stdversion.Analyzer}, - {analyzer: stringintconv.Analyzer}, - {analyzer: structtag.Analyzer}, - {analyzer: testinggoroutine.Analyzer}, - {analyzer: tests.Analyzer}, - {analyzer: timeformat.Analyzer}, - {analyzer: unmarshal.Analyzer}, - {analyzer: unreachable.Analyzer}, - {analyzer: unsafeptr.Analyzer}, - {analyzer: unusedresult.Analyzer}, - {analyzer: waitgroup.Analyzer}, + // Start with the traditional vet and fix suites. + for _, suite := range []struct { + name string + analyzers []*analysis.Analyzer + severity protocol.DiagnosticSeverity + }{ + {"fix.Suite", fix.Suite, protocol.SeverityHint}, + {"vet.Suite", vet.Suite, protocol.SeverityWarning}, + } { + for _, a := range suite.analyzers { + // De-duplicate, since the suites overlap. + if !seen[a] { + seen[a] = true + res = append(res, &Analyzer{analyzer: a, severity: suite.severity}) + } + } + } - // not suitable for vet: - // - some (nilness, yield) use go/ssa; see #59714. - // - others don't meet the "frequency" criterion; - // see GOROOT/src/cmd/vet/README. - {analyzer: atomicalign.Analyzer}, - {analyzer: deepequalerrors.Analyzer}, - {analyzer: nilness.Analyzer}, // uses go/ssa - {analyzer: yield.Analyzer}, // uses go/ssa - {analyzer: sortslice.Analyzer}, - {analyzer: embeddirective.Analyzer}, - {analyzer: scannererr.Analyzer}, // to appear in cmd/vet@go1.28 - {analyzer: sqlrowserr.Analyzer}, // to appear in cmd/vet@go1.28 - {analyzer: recursiveiter.Analyzer}, // under evaluation - {analyzer: errorsastypeshadow.Analyzer}, // under evaluation - {analyzer: writestring.Analyzer}, // under evaluation - - // disabled due to high false positives - {analyzer: shadow.Analyzer, severity: protocol.SeverityHint, nonDefault: true}, // very noisy - {analyzer: fieldalignment.Analyzer, severity: protocol.SeverityHint, nonDefault: true}, // #67762, #76237 - - // simplifiers and modernizers - // - // These analyzers offer mere style fixes on correct code, - // thus they will never appear in cmd/vet and - // their severity level is "information". - // - // gofmt -s suite - { - analyzer: simplifycompositelit.Analyzer, - actionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix}, - severity: protocol.SeverityInformation, - }, - { - analyzer: simplifyrange.Analyzer, - actionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix}, - severity: protocol.SeverityInformation, - }, - { - analyzer: simplifyslice.Analyzer, - actionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix}, - severity: protocol.SeverityInformation, - }, - // other simplifiers - {analyzer: inline.Analyzer, severity: protocol.SeverityHint}, // (in -lazy_edit mode) - {analyzer: infertypeargs.Analyzer, severity: protocol.SeverityInformation}, - {analyzer: maprange.Analyzer, severity: protocol.SeverityHint}, - {analyzer: unusedparams.Analyzer, severity: protocol.SeverityInformation}, - {analyzer: unusedfunc.Analyzer, severity: protocol.SeverityInformation}, - {analyzer: unusedwrite.Analyzer, severity: protocol.SeverityInformation}, // uses go/ssa - // the modernize suite - {analyzer: modernize.AnyAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.AppendClippedAnalyzer, severity: protocol.SeverityHint, nonDefault: true}, // not nil-preserving - {analyzer: modernize.AtomicTypesAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.BLoopAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.EmbedLitAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.ErrorsAsTypeAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.FmtAppendfAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.ForVarAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.MapsLoopAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.MinMaxAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.NewExprAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.OmitZeroAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.PlusBuildAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.RangeIntAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.ReflectTypeForAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.SlicesContainsAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.SlicesDeleteAnalyzer, severity: protocol.SeverityHint, nonDefault: true}, // not nil-preserving - {analyzer: modernize.SlicesSortAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.StdIteratorsAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.StringsBuilderAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.StringsCutAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.StringsCutPrefixAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.StringsSeqAnalyzer, severity: protocol.SeverityHint}, - {analyzer: modernize.TestingContextAnalyzer, severity: protocol.SeverityHint}, - {analyzer: goplsexport.UnsafeFuncsModernizer, severity: protocol.SeverityHint}, - {analyzer: modernize.WaitGroupGoAnalyzer, severity: protocol.SeverityHint}, - - // type-error analyzers - // These analyzers enrich go/types errors with suggested fixes. - // Since they exist only to attach their fixes to type errors, their - // severity is irrelevant. - {analyzer: fillreturns.Analyzer}, - {analyzer: nonewvars.Analyzer}, - {analyzer: noresultvalues.Analyzer}, - {analyzer: unusedvariable.Analyzer}, -} - -func init() { + // set inline -lazy_edit mode if err := inline.Analyzer.Flags.Set("lazy_edits", "true"); err != nil { log.Fatalf("setting inline -lazy_edits flag: %v", err) } + + // See [Analyzer.Severity] for guidance on setting analyzer severity below. + for _, a := range []*Analyzer{ + // not suitable for vet.Suite: + // - some (nilness, yield) use go/ssa; see #59714. + // - others don't meet the "frequency" criterion; + // see GOROOT/src/cmd/vet/README. + {analyzer: atomicalign.Analyzer}, + {analyzer: deprecated.Analyzer, + severity: protocol.SeverityHint, + tags: []protocol.DiagnosticTag{protocol.Deprecated}, + }, + {analyzer: deepequalerrors.Analyzer}, + {analyzer: nilness.Analyzer}, // uses go/ssa + {analyzer: yield.Analyzer}, // uses go/ssa + {analyzer: sortslice.Analyzer}, + {analyzer: embeddirective.Analyzer}, + {analyzer: scannererr.Analyzer}, // to appear in cmd/vet@go1.28 + {analyzer: sqlrowserr.Analyzer}, // to appear in cmd/vet@go1.28 + {analyzer: recursiveiter.Analyzer}, // under evaluation + {analyzer: errorsastypeshadow.Analyzer}, // under evaluation + {analyzer: writestring.Analyzer}, // under evaluation + + // disabled due to high false positives + {analyzer: shadow.Analyzer, severity: protocol.SeverityHint, nonDefault: true}, // very noisy + {analyzer: fieldalignment.Analyzer, severity: protocol.SeverityHint, nonDefault: true}, // #67762, #76237 + + // simplifiers and modernizers (beyond fix.Suite) + // + // These analyzers offer mere style fixes on correct code, + // thus they will never appear in cmd/vet or cmd/fix and + // their severity level is "information". + // + // gofmt -s suite + { + analyzer: simplifycompositelit.Analyzer, + actionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix}, + severity: protocol.SeverityInformation, + }, + { + analyzer: simplifyrange.Analyzer, + actionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix}, + severity: protocol.SeverityInformation, + }, + { + analyzer: simplifyslice.Analyzer, + actionKinds: []protocol.CodeActionKind{protocol.SourceFixAll, protocol.QuickFix}, + severity: protocol.SeverityInformation, + }, + // other simplifiers + {analyzer: infertypeargs.Analyzer, severity: protocol.SeverityInformation}, + {analyzer: maprange.Analyzer, severity: protocol.SeverityHint}, + {analyzer: unusedparams.Analyzer, severity: protocol.SeverityInformation}, + {analyzer: unusedfunc.Analyzer, severity: protocol.SeverityInformation}, + {analyzer: unusedwrite.Analyzer, severity: protocol.SeverityInformation}, // uses go/ssa + // modernizers not included in modernize.Suite (nor fix.Suite) + {analyzer: modernize.AppendClippedAnalyzer, nonDefault: true}, // not nil-preserving + {analyzer: modernize.BLoopAnalyzer}, // may skew benchmark results, see golang/go#74967 + {analyzer: modernize.FmtAppendfAnalyzer}, // makes code less clear, see golang/go#77581 + {analyzer: modernize.SlicesDeleteAnalyzer, nonDefault: true}, // not nil-preserving + + // type-error analyzers + // These analyzers enrich go/types errors with suggested fixes. + // Since they exist only to attach their fixes to type errors, their + // severity is irrelevant. + {analyzer: fillreturns.Analyzer}, + {analyzer: nonewvars.Analyzer}, + {analyzer: noresultvalues.Analyzer}, + {analyzer: unusedvariable.Analyzer}, + } { + if seen[a.analyzer] { + log.Fatalf("duplicate analyzer: %q", a.analyzer.Name) + } + seen[a.analyzer] = true + res = append(res, a) + } + + return append(res, staticcheckAnalyzers()...) }
diff --git a/gopls/internal/settings/staticcheck.go b/gopls/internal/settings/staticcheck.go index 04b89d5..cf9c9a3 100644 --- a/gopls/internal/settings/staticcheck.go +++ b/gopls/internal/settings/staticcheck.go
@@ -177,10 +177,7 @@ "honnef.co/go/tools/stylecheck/st1023" ) -// StaticcheckAnalyzers lists available Staticcheck analyzers. -var StaticcheckAnalyzers = initStaticcheckAnalyzers() - -func initStaticcheckAnalyzers() (res []*Analyzer) { +func staticcheckAnalyzers() (res []*Analyzer) { mapSeverity := func(severity lint.Severity) protocol.DiagnosticSeverity { switch severity {
diff --git a/internal/goplsexport/export.go b/internal/goplsexport/export.go deleted file mode 100644 index 414c9cb..0000000 --- a/internal/goplsexport/export.go +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package goplsexport provides various backdoors to not-yet-published -// parts of x/tools that are needed by gopls. -package goplsexport - -import "golang.org/x/tools/go/analysis" - -var ( - ErrorsAsTypeModernizer *analysis.Analyzer // = modernize.errorsastypeAnalyzer - SlicesBackwardModernizer *analysis.Analyzer // = modernize.slicesbackwardAnalyzer - StdIteratorsModernizer *analysis.Analyzer // = modernize.stditeratorsAnalyzer - PlusBuildModernizer *analysis.Analyzer // = modernize.plusbuildAnalyzer - StringsCutModernizer *analysis.Analyzer // = modernize.stringscutAnalyzer - UnsafeFuncsModernizer *analysis.Analyzer // = modernize.unsafeFuncsAnalyzer - AtomicTypesModernizer *analysis.Analyzer // = modernize.atomicTypesAnalyzer - EmbedLitModernizer *analysis.Analyzer // = modernize.embedLitAnalyzer -)