Files
odidere/vendor/honnef.co/go/tools/simple/s1005/s1005.go
2026-06-06 01:17:29 +00:00

109 lines
3.3 KiB
Go

package s1005
import (
"go/ast"
"go/types"
"honnef.co/go/tools/analysis/code"
"honnef.co/go/tools/analysis/edit"
"honnef.co/go/tools/analysis/facts/generated"
"honnef.co/go/tools/analysis/lint"
"honnef.co/go/tools/analysis/report"
"honnef.co/go/tools/go/ast/astutil"
"honnef.co/go/tools/pattern"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
)
var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
Analyzer: &analysis.Analyzer{
Name: "S1005",
Run: run,
Requires: []*analysis.Analyzer{inspect.Analyzer, generated.Analyzer},
},
Doc: &lint.RawDocumentation{
Title: `Drop unnecessary use of the blank identifier`,
Text: `In many cases, assigning to the blank identifier is unnecessary.`,
Before: `
for _ = range s {}
x, _ = someMap[key]
_ = <-ch`,
After: `
for range s{}
x = someMap[key]
<-ch`,
Since: "2017.1",
MergeIf: lint.MergeIfAny,
},
})
var Analyzer = SCAnalyzer.Analyzer
var (
checkUnnecessaryBlankQ1 = pattern.MustParse(`
(AssignStmt
[_ (Ident "_")]
_
(Or
(IndexExpr _ _)
(UnaryExpr "<-" _))) `)
checkUnnecessaryBlankQ2 = pattern.MustParse(`
(AssignStmt
(Ident "_") _ recv@(UnaryExpr "<-" _))`)
)
func run(pass *analysis.Pass) (any, error) {
fn1 := func(node ast.Node) {
if _, ok := code.Match(pass, checkUnnecessaryBlankQ1, node); ok {
r := *node.(*ast.AssignStmt)
r.Lhs = r.Lhs[0:1]
report.Report(pass, node, "unnecessary assignment to the blank identifier",
report.FilterGenerated(),
report.Fixes(edit.Fix("Remove assignment to blank identifier", edit.ReplaceWithNode(pass.Fset, node, &r))))
} else if m, ok := code.Match(pass, checkUnnecessaryBlankQ2, node); ok {
report.Report(pass, node, "unnecessary assignment to the blank identifier",
report.FilterGenerated(),
report.Fixes(edit.Fix("Simplify channel receive operation", edit.ReplaceWithNode(pass.Fset, node, m.State["recv"].(ast.Node)))))
}
}
fn3 := func(node ast.Node) {
rs := node.(*ast.RangeStmt)
if _, ok := pass.TypesInfo.TypeOf(rs.X).Underlying().(*types.Signature); ok {
// iteration variables are not optional with rangefunc
return
}
// for _
if rs.Value == nil && astutil.IsBlank(rs.Key) {
report.Report(pass, rs.Key, "unnecessary assignment to the blank identifier",
report.FilterGenerated(),
report.MinimumLanguageVersion("go1.4"),
report.Fixes(edit.Fix("Remove assignment to blank identifier", edit.Delete(edit.Range{rs.Key.Pos(), rs.TokPos + 1}))))
}
// for _, _
if astutil.IsBlank(rs.Key) && astutil.IsBlank(rs.Value) {
// FIXME we should mark both key and value
report.Report(pass, rs.Key, "unnecessary assignment to the blank identifier",
report.FilterGenerated(),
report.MinimumLanguageVersion("go1.4"),
report.Fixes(edit.Fix("Remove assignment to blank identifier", edit.Delete(edit.Range{rs.Key.Pos(), rs.TokPos + 1}))))
}
// for x, _
if !astutil.IsBlank(rs.Key) && astutil.IsBlank(rs.Value) {
report.Report(pass, rs.Value, "unnecessary assignment to the blank identifier",
report.FilterGenerated(),
report.MinimumLanguageVersion("go1.4"),
report.Fixes(edit.Fix("Remove assignment to blank identifier", edit.Delete(edit.Range{rs.Key.End(), rs.Value.End()}))))
}
}
code.Preorder(pass, fn1, (*ast.AssignStmt)(nil))
code.Preorder(pass, fn3, (*ast.RangeStmt)(nil))
return nil, nil
}