Skip to content

[duplicate-code] fmt.Sprintf to strconv Fix Builders Duplicated in sprintfbool and sprintfint #65439

Description

@github-actions

🔍 Duplicate Code Detected: fmt.Sprintf→strconv Fix Builders

Analysis of commit 31e5fda

Assignee: @copilot

Summary

The sprintfbool and sprintfint analyzers in pkg/linters/ contain essentially identical candidate-collection and suggested-fix logic for rewriting fmt.Sprintf("%t"/"%d", x) into a strconv call. The qualifier-resolution block and the buildImportEdits function (which adds strconv and removes an orphaned fmt import) are near-verbatim copies.

Duplication Details

Pattern: strconv-qualifier resolution + import-swap fix

  • Severity: Medium
  • Occurrences: 2 analyzers (with 3+ duplicated blocks across them)
  • Locations:
    • pkg/linters/sprintfbool/sprintfbool.go (buildImportEdits lines 167-197, replacementForCall lines 199-233)
    • pkg/linters/sprintfint/sprintfint.go (buildItoaFix lines 96-140, buildImportEdits lines 142-159)
  • Code Sample (qualifier resolution — identical in both):
qualifier := strconvPkg
if file != nil {
    if localName, imported := astutil.ImportedAs(file, pass.TypesInfo, strconvPkg); imported {
        if localName == "." || localName == "_" {
            return /* no fix */
        }
        qualifier = localName
    }
}
if astutil.QualifierShadowed(pass.Pkg, call.Pos(), qualifier, strconvPkg) {
    return /* no fix */
}

buildImportEdits in both files computes orphanFmt and calls astutil.SwapPkgImportEdits(pass, file, strconvPkg, fmtPkg, orphanFmt) with the same seenImportFiles guard. Both files also redeclare the strconvPkg/fmtPkg constants.

Impact Analysis

  • Maintainability: Any change to how the fix handles aliases, blank/dot imports, shadowing, or fmt orphan removal must be mirrored in both analyzers.
  • Bug Risk: The two copies already differ (bool version adds computeOrphanFmtStatus/orphanFmtByFile plumbing, int version inlines CountPkgUsesInFile(...) == 1), making divergence likely.
  • Code Bloat: ~60 duplicated lines of fix-construction logic.

Refactoring Recommendations

  1. Extract a shared "Sprintf → strconv" fix builder

    • Add an astutil/internal helper BuildStrconvSwapFix(pass, call, argText, replacementFunc string, seen) []analysis.SuggestedFix encapsulating qualifier resolution, shadow checks, and the fmt→strconv import swap.
    • sprintfbool passes "FormatBool"; sprintfint passes "Itoa".
    • Estimated effort: 3-4 hours
    • Benefits: one implementation of the import/alias/shadow edge cases; future sprintf* linters reuse it.
  2. Share candidate predicate helpers

    • Factor the common fmt.Sprintf selector/arg-count/format-literal checks into a reusable predicate.

Implementation Checklist

  • Review duplication findings
  • Prioritize refactoring tasks
  • Create refactoring plan
  • Implement shared fix builder in astutil
  • Migrate sprintfbool and sprintfint
  • Update tests
  • Verify no functionality broken
Analysis Metadata
  • Analyzed Files: pkg/linters (77 analyzer packages)
  • Detection Method: Serena semantic code analysis
  • Commit: 31e5fda
  • Analysis Date: 2026-10-03T22:48:41.609Z

Generated by 🔍 Duplicate Code Detector · pi · opus48 · 361.7 AIC · ⌖ 46.9 AIC · ⊞ 4.4K · ◷

  • expires on Oct 5, 2026, 2:50 PM UTC-08:00

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions