Skip to content

lenstringzero: diagnostic message hardcodes literal "s"/"len(s)" text, misreporting every violation's actual expression #54717

Description

@github-actions

Problem

lenstringzero's diagnostic message hardcodes the literal placeholder text s and len(s) instead of interpolating the actual matched expression, for every violation it reports (not just the alias-tracking path).

Location

pkg/linters/lenstringzero/lenstringzero.go:74-79

pass.Report(analysis.Diagnostic{
    Pos:            expr.Pos(),
    End:            expr.End(),
    Message:        fmt.Sprintf(`use s %s "" to check for %s string instead of len(s) %s %d`, fixOp, cmpVerb, normalOp, lit),
    SuggestedFixes: fixes,
})

Only fixOp, cmpVerb, normalOp, and lit are interpolated — s and len(s) are literal text in the format string, not placeholders for the real expression.

Evidence / impact

For source code like:

if len(username) == 0 {

the emitted diagnostic reads:

use s == "" to check for empty string instead of len(s) == 0

instead of the actionable:

use username == "" to check for empty string instead of len(username) == 0

This makes every diagnostic from this linter misleading about which variable is affected — a contributor has to cross-reference the reported line/column manually instead of reading the message. It's the same defect class already fixed twice elsewhere in this codebase for the identical reason (#53579 bytescomparestring, #52826 stringbytesroundtrip: "diagnostic message hardcodes ... and misrepresents"), but it has reappeared in lenstringzero, which is not yet CI-enforced (missing from LINTER_FLAGS in .github/workflows/cgo.yml), so it hasn't been caught by day-to-day usage yet.

The alias-tracking path (n := len(s); if n == 0) is doubly affected: it reports len(s) even though the source text is n, and there is no s in scope at all — so the message references code that isn't there.

Recommendation

Use astutil.NodeText(pass.Fset, lenArg) (already imported and used by buildLenStringFix) to build the message dynamically for both the direct and alias cases, mirroring how sibling linters like mapdeletecheck (mText/kText) and the current stringbytesroundtrip/bytescomparestring already do it correctly.

Validation checklist

  • Message text uses the real expression (e.g. username, or the alias variable name for the n := len(s) case), not literal s/len(s)
  • analysistest golden files updated/added to assert the exact message text for a non-trivial variable name
  • No change to SuggestedFixes behavior (autofix is already correct; only the message is wrong)

Effort

Small — the fix is confined to one fmt.Sprintf call plus updating expected test fixture strings.

Generated by 🤖 Sergo - Serena Go Expert · agent · 275.9 AIC · ⌖ 9.07 AIC · ⊞ 6.8K ·

  • expires on Aug 28, 2026, 8:16 PM UTC-08:00

Metadata

Metadata

Labels

cookieIssue Monster Loves Cookies!sergo

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions