75 lines
2.0 KiB
Go
75 lines
2.0 KiB
Go
package s1020
|
|
|
|
import (
|
|
"fmt"
|
|
"go/ast"
|
|
"go/types"
|
|
|
|
"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/pattern"
|
|
|
|
"golang.org/x/tools/go/analysis"
|
|
)
|
|
|
|
var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
|
|
Analyzer: &analysis.Analyzer{
|
|
Name: "S1020",
|
|
Run: run,
|
|
Requires: append([]*analysis.Analyzer{generated.Analyzer}, code.RequiredAnalyzers...),
|
|
},
|
|
Doc: &lint.RawDocumentation{
|
|
Title: `Omit redundant nil check in type assertion`,
|
|
Before: `if _, ok := i.(T); ok && i != nil {}`,
|
|
After: `if _, ok := i.(T); ok {}`,
|
|
Since: "2017.1",
|
|
MergeIf: lint.MergeIfAny,
|
|
},
|
|
})
|
|
|
|
var Analyzer = SCAnalyzer.Analyzer
|
|
|
|
var (
|
|
checkAssertNotNilFn1Q = pattern.MustParse(`
|
|
(IfStmt
|
|
(AssignStmt [(Ident "_") ok@(Object _)] _ [(TypeAssertExpr assert@(Object _) _)])
|
|
(Or
|
|
(BinaryExpr ok "&&" (BinaryExpr assert "!=" (Builtin "nil")))
|
|
(BinaryExpr (BinaryExpr assert "!=" (Builtin "nil")) "&&" ok))
|
|
_
|
|
_)`)
|
|
checkAssertNotNilFn2Q = pattern.MustParse(`
|
|
(IfStmt
|
|
nil
|
|
(BinaryExpr lhs@(Object _) "!=" (Builtin "nil"))
|
|
[
|
|
ifstmt@(IfStmt
|
|
(AssignStmt [(Ident "_") ok@(Object _)] _ [(TypeAssertExpr lhs _)])
|
|
ok
|
|
_
|
|
nil)
|
|
]
|
|
nil)`)
|
|
)
|
|
|
|
func run(pass *analysis.Pass) (any, error) {
|
|
for node, m := range code.Matches(pass, checkAssertNotNilFn1Q) {
|
|
assert := m.State["assert"].(types.Object)
|
|
assign := m.State["ok"].(types.Object)
|
|
report.Report(pass, node, fmt.Sprintf("when %s is true, %s can't be nil", assign.Name(), assert.Name()),
|
|
report.ShortRange(),
|
|
report.FilterGenerated())
|
|
}
|
|
for _, m := range code.Matches(pass, checkAssertNotNilFn2Q) {
|
|
ifstmt := m.State["ifstmt"].(*ast.IfStmt)
|
|
lhs := m.State["lhs"].(types.Object)
|
|
assignIdent := m.State["ok"].(types.Object)
|
|
report.Report(pass, ifstmt, fmt.Sprintf("when %s is true, %s can't be nil", assignIdent.Name(), lhs.Name()),
|
|
report.ShortRange(),
|
|
report.FilterGenerated())
|
|
}
|
|
return nil, nil
|
|
}
|