π Duplicate Code Detected: Discarded-Error Linter Scaffolding
Analysis of commit 31e5fda
Assignee: @copilot
Summary
Three "ignored/discarded error" analyzers in pkg/linters/ β strconvparseignorederror, globwalkignorederror, and jsonmarshalignoredeerror β implement nearly identical AST traversal and pattern-matching logic to detect val, _ := pkg.Func(...) assignments where the error return is discarded. The run setup and the core "2-LHS / blank second ident / selector call / resolve PkgName / match import path" block are structurally duplicated across all three files.
Duplication Details
Pattern: Discarded-error assignment detection
- Severity: Medium
- Occurrences: 3 analyzers (plus repeated
run boilerplate)
- Locations:
pkg/linters/strconvparseignorederror/strconvparseignorederror.go (lines 42-82, esp. 44-71)
pkg/linters/globwalkignorederror/globwalkignorederror.go (lines 40-85, esp. 42-66)
pkg/linters/jsonmarshalignoredeerror/jsonmarshalignoredeerror.go (lines 46-71, 95-112)
- Code Sample (near-identical in
strconvparse and globwalk):
assign, ok := n.(*ast.AssignStmt)
if !ok {
return
}
if len(assign.Lhs) != 2 || len(assign.Rhs) != 1 {
return
}
blank, ok := assign.Lhs[1].(*ast.Ident)
if !ok || blank.Name != "_" {
return
}
call, ok := assign.Rhs[0].(*ast.CallExpr)
if !ok {
return
}
sel, ok := call.Fun.(*ast.SelectorExpr)
if !ok {
return
}
ident, ok := sel.X.(*ast.Ident)
if !ok {
return
}
obj := pass.TypesInfo.Uses[ident]
pkgName, ok := obj.(*types.PkgName)
if !ok /* || path mismatch */ {
return
}
The jsonmarshalignoredeerror.isJSONFunc helper repeats the same selector β ident β PkgName β import-path resolution.
Impact Analysis
- Maintainability: A change to how discarded-error detection handles aliases, dot-imports, or multi-assignment must be applied in three places.
- Bug Risk: The three copies have already diverged slightly (e.g.
strconvparse uses map[string]bool, globwalk uses map[string]map[string]struct{}, jsonmarshal hardcodes names), so fixes risk being applied inconsistently.
- Code Bloat: ~60-80 duplicated lines of matching logic across the three files.
Refactoring Recommendations
-
Extract a shared "discarded error call" matcher
- Add a helper to
pkg/linters/internal/astutil (e.g. MatchDiscardedErrorCall(pass, assign) (call *ast.CallExpr, pkgPath, funcName string, ok bool)) encapsulating the LHS/blank/selector/PkgName resolution.
- Each analyzer supplies only a
map[pkgPath]set(funcName) and a message template.
- Estimated effort: 3-4 hours
- Benefits: single tested implementation of the fiddly type-resolution logic; analyzers shrink to declarations.
-
Share the run + Indexes + Preorder boilerplate
- Provide an
analyzerutil helper that wires a per-assignment callback, removing the repeated run function.
Implementation Checklist
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 Β· β·
π Duplicate Code Detected: Discarded-Error Linter Scaffolding
Analysis of commit 31e5fda
Assignee:
@copilotSummary
Three "ignored/discarded error" analyzers in
pkg/linters/βstrconvparseignorederror,globwalkignorederror, andjsonmarshalignoredeerrorβ implement nearly identical AST traversal and pattern-matching logic to detectval, _ := pkg.Func(...)assignments where the error return is discarded. Therunsetup and the core "2-LHS / blank second ident / selector call / resolve PkgName / match import path" block are structurally duplicated across all three files.Duplication Details
Pattern: Discarded-error assignment detection
runboilerplate)pkg/linters/strconvparseignorederror/strconvparseignorederror.go(lines 42-82, esp. 44-71)pkg/linters/globwalkignorederror/globwalkignorederror.go(lines 40-85, esp. 42-66)pkg/linters/jsonmarshalignoredeerror/jsonmarshalignoredeerror.go(lines 46-71, 95-112)strconvparseandglobwalk):The
jsonmarshalignoredeerror.isJSONFunchelper repeats the same selector β ident βPkgNameβ import-path resolution.Impact Analysis
strconvparseusesmap[string]bool,globwalkusesmap[string]map[string]struct{},jsonmarshalhardcodes names), so fixes risk being applied inconsistently.Refactoring Recommendations
Extract a shared "discarded error call" matcher
pkg/linters/internal/astutil(e.g.MatchDiscardedErrorCall(pass, assign) (call *ast.CallExpr, pkgPath, funcName string, ok bool)) encapsulating the LHS/blank/selector/PkgName resolution.map[pkgPath]set(funcName)and a message template.Share the
run+Indexes+Preorderboilerplateanalyzerutilhelper that wires a per-assignment callback, removing the repeatedrunfunction.Implementation Checklist
astutilAnalysis Metadata