Summary
Two gaps in the heuristic/threshold linters excessivefuncparams and largefunc make them inconsistent with their siblings and not yet enforce-ready:
excessivefuncparams does not skip test files, while every other FuncDecl-walking linter does.
- Neither
excessivefuncparams nor largefunc honors //nolint directives, so a legitimately-large function or wide API signature cannot be suppressed at the call site — the only escape is raising the global threshold, which weakens the rule everywhere.
1. Missing test-file skip in excessivefuncparams
pkg/linters/excessivefuncparams/excessivefuncparams.go run (lines 44-68) reports on every *ast.FuncDecl with no filecheck.IsTestFile guard. Compare:
pkg/linters/largefunc/largefunc.go:66 — if filecheck.IsTestFile(...) { return }
pkg/linters/seenmapbool/seenmapbool.go:47 — skips test files
pkg/linters/errorfwrapv/errorfwrapv.go:75 — skips test files
pkg/linters/deferinloop/deferinloop.go:43 — skips test files
excessivefuncparams is the lone FuncDecl-based linter that analyzes _test.go. Test code routinely has many-parameter helpers (table-driven builders, mock constructors) that are not a design smell, so running the analyzer over tests (e.g. a local go vet -vettool=... ./... that does not pass -test=false) produces noise the sibling linters suppress.
2. No (nolint/redacted) suppression for either threshold linter
20 of the 32 registered analyzers wire nolint.BuildLineIndex / nolint.HasDirective (e.g. seenmapbool.go:32, errorfwrapv.go:62, deferinloop.go:34). largefunc and excessivefuncparams do not import internal/nolint at all.
For purely-mechanical linters (stdlib-pattern matches) the absence of //nolint is tolerable because there is always a clean rewrite. For heuristic threshold linters it is not: some functions are legitimately long (large switch/codegen) or legitimately take many parameters (stable public constructors), and the developer has no per-site escape hatch. This is a concrete blocker to CI enforcement — neither linter appears in the enforced set, and they cannot be safely enforced until a justified violation can be suppressed without loosening the global threshold for the whole tree.
Impact
- Inconsistent test-file handling vs. all sibling
FuncDecl linters → spurious diagnostics on test helpers.
- No
//nolint escape hatch on the two linters that most need one → cannot be promoted to CI enforcement without forcing awkward refactors or a globally-loosened threshold.
Recommended fix
- Add
if filecheck.IsTestFile(pass.Fset.Position(fn.Pos()).Filename) { return } to excessivefuncparams.run, matching largefunc.
- Wire
internal/nolint into both: noLint := nolint.BuildLineIndex(pass, "<name>") and gate ReportRangef on !nolint.HasDirective(pos, noLint), mirroring seenmapbool/errorfwrapv.
- Add testdata cases: a many-param function in a
_test.go (expect no diagnostic) and a //nolint:excessivefuncparams / //nolint:largefunc suppression case.
Effort
Small and mechanical — both changes follow established patterns already used by 20 sibling analyzers; fully coverable by analysistest.
Note on scope (honesty)
Several other non-enforced analyzers also lack //nolint support; this issue scopes the suppression request to the two heuristic threshold linters because their violations are the ones most often legitimate and unavoidable. The test-file-skip gap, by contrast, is unique to excessivefuncparams among FuncDecl linters.
Generated by 🤖 Sergo - Serena Go Expert · 357.9 AIC · ⌖ 10.9 AIC · ⊞ 5.8K · ◷
Summary
Two gaps in the heuristic/threshold linters
excessivefuncparamsandlargefuncmake them inconsistent with their siblings and not yet enforce-ready:excessivefuncparamsdoes not skip test files, while every otherFuncDecl-walking linter does.excessivefuncparamsnorlargefunchonors//nolintdirectives, so a legitimately-large function or wide API signature cannot be suppressed at the call site — the only escape is raising the global threshold, which weakens the rule everywhere.1. Missing test-file skip in excessivefuncparams
pkg/linters/excessivefuncparams/excessivefuncparams.gorun(lines 44-68) reports on every*ast.FuncDeclwith nofilecheck.IsTestFileguard. Compare:pkg/linters/largefunc/largefunc.go:66—if filecheck.IsTestFile(...) { return }pkg/linters/seenmapbool/seenmapbool.go:47— skips test filespkg/linters/errorfwrapv/errorfwrapv.go:75— skips test filespkg/linters/deferinloop/deferinloop.go:43— skips test filesexcessivefuncparamsis the loneFuncDecl-based linter that analyzes_test.go. Test code routinely has many-parameter helpers (table-driven builders, mock constructors) that are not a design smell, so running the analyzer over tests (e.g. a localgo vet -vettool=... ./...that does not pass-test=false) produces noise the sibling linters suppress.2. No (nolint/redacted) suppression for either threshold linter
20 of the 32 registered analyzers wire
nolint.BuildLineIndex/nolint.HasDirective(e.g.seenmapbool.go:32,errorfwrapv.go:62,deferinloop.go:34).largefuncandexcessivefuncparamsdo not importinternal/nolintat all.For purely-mechanical linters (stdlib-pattern matches) the absence of
//nolintis tolerable because there is always a clean rewrite. For heuristic threshold linters it is not: some functions are legitimately long (largeswitch/codegen) or legitimately take many parameters (stable public constructors), and the developer has no per-site escape hatch. This is a concrete blocker to CI enforcement — neither linter appears in the enforced set, and they cannot be safely enforced until a justified violation can be suppressed without loosening the global threshold for the whole tree.Impact
FuncDecllinters → spurious diagnostics on test helpers.//nolintescape hatch on the two linters that most need one → cannot be promoted to CI enforcement without forcing awkward refactors or a globally-loosened threshold.Recommended fix
if filecheck.IsTestFile(pass.Fset.Position(fn.Pos()).Filename) { return }toexcessivefuncparams.run, matchinglargefunc.internal/nolintinto both:noLint := nolint.BuildLineIndex(pass, "<name>")and gateReportRangefon!nolint.HasDirective(pos, noLint), mirroringseenmapbool/errorfwrapv._test.go(expect no diagnostic) and a//nolint:excessivefuncparams///nolint:largefuncsuppression case.Effort
Small and mechanical — both changes follow established patterns already used by 20 sibling analyzers; fully coverable by
analysistest.Note on scope (honesty)
Several other non-enforced analyzers also lack
//nolintsupport; this issue scopes the suppression request to the two heuristic threshold linters because their violations are the ones most often legitimate and unavoidable. The test-file-skip gap, by contrast, is unique toexcessivefuncparamsamongFuncDecllinters.