66 lines
1.8 KiB
Go
66 lines
1.8 KiB
Go
|
|
package qf1004
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"go/ast"
|
||
|
|
"go/token"
|
||
|
|
|
||
|
|
"honnef.co/go/tools/analysis/edit"
|
||
|
|
"honnef.co/go/tools/analysis/lint"
|
||
|
|
"honnef.co/go/tools/analysis/report"
|
||
|
|
typeindexanalyzer "honnef.co/go/tools/internal/analysisinternal/typeindex"
|
||
|
|
"honnef.co/go/tools/internal/typesinternal/typeindex"
|
||
|
|
|
||
|
|
"golang.org/x/tools/go/analysis"
|
||
|
|
)
|
||
|
|
|
||
|
|
var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
|
||
|
|
Analyzer: &analysis.Analyzer{
|
||
|
|
Name: "QF1004",
|
||
|
|
Run: run,
|
||
|
|
Requires: []*analysis.Analyzer{typeindexanalyzer.Analyzer},
|
||
|
|
},
|
||
|
|
Doc: &lint.RawDocumentation{
|
||
|
|
Title: `Use \'strings.ReplaceAll\' instead of \'strings.Replace\' with \'n == -1\'`,
|
||
|
|
Since: "2021.1",
|
||
|
|
Severity: lint.SeverityHint,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
|
||
|
|
var Analyzer = SCAnalyzer.Analyzer
|
||
|
|
|
||
|
|
var fns = []struct {
|
||
|
|
path string
|
||
|
|
name string
|
||
|
|
replacement string
|
||
|
|
}{
|
||
|
|
{"strings", "Replace", "strings.ReplaceAll"},
|
||
|
|
{"strings", "SplitN", "strings.Split"},
|
||
|
|
{"strings", "SplitAfterN", "strings.SplitAfter"},
|
||
|
|
{"bytes", "Replace", "bytes.ReplaceAll"},
|
||
|
|
{"bytes", "SplitN", "bytes.Split"},
|
||
|
|
{"bytes", "SplitAfterN", "bytes.SplitAfter"},
|
||
|
|
}
|
||
|
|
|
||
|
|
func run(pass *analysis.Pass) (any, error) {
|
||
|
|
// XXX respect minimum Go version
|
||
|
|
|
||
|
|
// FIXME(dh): create proper suggested fix for renamed import
|
||
|
|
|
||
|
|
index := pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||
|
|
for _, fn := range fns {
|
||
|
|
for c := range index.Calls(index.Object(fn.path, fn.name)) {
|
||
|
|
call := c.Node().(*ast.CallExpr)
|
||
|
|
if op, ok := call.Args[len(call.Args)-1].(*ast.UnaryExpr); ok && op.Op == token.SUB {
|
||
|
|
if lit, ok := op.X.(*ast.BasicLit); ok && lit.Value == "1" {
|
||
|
|
report.Report(pass, call.Fun, fmt.Sprintf("could use %s instead", fn.replacement),
|
||
|
|
report.Fixes(edit.Fix(fmt.Sprintf("Use %s instead", fn.replacement),
|
||
|
|
edit.ReplaceWithString(call.Fun, fn.replacement),
|
||
|
|
edit.Delete(op))))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil, nil
|
||
|
|
}
|