Add staticcheck tool
This commit is contained in:
128
vendor/honnef.co/go/tools/simple/s1032/s1032.go
vendored
Normal file
128
vendor/honnef.co/go/tools/simple/s1032/s1032.go
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
package s1032
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"sort"
|
||||
|
||||
"honnef.co/go/tools/analysis/code"
|
||||
"honnef.co/go/tools/analysis/facts/generated"
|
||||
"honnef.co/go/tools/analysis/lint"
|
||||
"honnef.co/go/tools/analysis/report"
|
||||
"honnef.co/go/tools/knowledge"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
)
|
||||
|
||||
var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
|
||||
Analyzer: &analysis.Analyzer{
|
||||
Name: "S1032",
|
||||
Run: run,
|
||||
Requires: []*analysis.Analyzer{inspect.Analyzer, generated.Analyzer},
|
||||
},
|
||||
Doc: &lint.RawDocumentation{
|
||||
Title: `Use \'sort.Ints(x)\', \'sort.Float64s(x)\', and \'sort.Strings(x)\'`,
|
||||
Text: `The \'sort.Ints\', \'sort.Float64s\' and \'sort.Strings\' functions are easier to
|
||||
read than \'sort.Sort(sort.IntSlice(x))\', \'sort.Sort(sort.Float64Slice(x))\'
|
||||
and \'sort.Sort(sort.StringSlice(x))\'.`,
|
||||
Before: `sort.Sort(sort.StringSlice(x))`,
|
||||
After: `sort.Strings(x)`,
|
||||
Since: "2019.1",
|
||||
MergeIf: lint.MergeIfAny,
|
||||
},
|
||||
})
|
||||
|
||||
var Analyzer = SCAnalyzer.Analyzer
|
||||
|
||||
func isPermissibleSort(pass *analysis.Pass, node ast.Node) bool {
|
||||
call := node.(*ast.CallExpr)
|
||||
typeconv, ok := call.Args[0].(*ast.CallExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
sel, ok := typeconv.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
name := code.SelectorName(pass, sel)
|
||||
switch name {
|
||||
case "sort.IntSlice", "sort.Float64Slice", "sort.StringSlice":
|
||||
default:
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func run(pass *analysis.Pass) (any, error) {
|
||||
type Error struct {
|
||||
node ast.Node
|
||||
msg string
|
||||
}
|
||||
var allErrors []Error
|
||||
fn := func(node ast.Node) {
|
||||
var body *ast.BlockStmt
|
||||
switch node := node.(type) {
|
||||
case *ast.FuncLit:
|
||||
body = node.Body
|
||||
case *ast.FuncDecl:
|
||||
body = node.Body
|
||||
default:
|
||||
lint.ExhaustiveTypeSwitch(node)
|
||||
}
|
||||
if body == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var errors []Error
|
||||
permissible := false
|
||||
fnSorts := func(node ast.Node) bool {
|
||||
if permissible {
|
||||
return false
|
||||
}
|
||||
if !code.IsCallTo(pass, node, "sort.Sort") {
|
||||
return true
|
||||
}
|
||||
if isPermissibleSort(pass, node) {
|
||||
permissible = true
|
||||
return false
|
||||
}
|
||||
call := node.(*ast.CallExpr)
|
||||
// isPermissibleSort guarantees that this type assertion will succeed
|
||||
typeconv := call.Args[knowledge.Arg("sort.Sort.data")].(*ast.CallExpr)
|
||||
sel := typeconv.Fun.(*ast.SelectorExpr)
|
||||
name := code.SelectorName(pass, sel)
|
||||
|
||||
switch name {
|
||||
case "sort.IntSlice":
|
||||
errors = append(errors, Error{node, "should use sort.Ints(...) instead of sort.Sort(sort.IntSlice(...))"})
|
||||
case "sort.Float64Slice":
|
||||
errors = append(errors, Error{node, "should use sort.Float64s(...) instead of sort.Sort(sort.Float64Slice(...))"})
|
||||
case "sort.StringSlice":
|
||||
errors = append(errors, Error{node, "should use sort.Strings(...) instead of sort.Sort(sort.StringSlice(...))"})
|
||||
}
|
||||
return true
|
||||
}
|
||||
ast.Inspect(body, fnSorts)
|
||||
|
||||
if permissible {
|
||||
return
|
||||
}
|
||||
allErrors = append(allErrors, errors...)
|
||||
}
|
||||
code.Preorder(pass, fn, (*ast.FuncLit)(nil), (*ast.FuncDecl)(nil))
|
||||
sort.Slice(allErrors, func(i, j int) bool {
|
||||
return allErrors[i].node.Pos() < allErrors[j].node.Pos()
|
||||
})
|
||||
var prev token.Pos
|
||||
for _, err := range allErrors {
|
||||
if err.node.Pos() == prev {
|
||||
continue
|
||||
}
|
||||
prev = err.node.Pos()
|
||||
report.Report(pass, err.node, err.msg, report.FilterGenerated())
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
Reference in New Issue
Block a user