s1020.go (2059B)
1 package s1020 2 3 import ( 4 "fmt" 5 "go/ast" 6 "go/types" 7 8 "honnef.co/go/tools/analysis/code" 9 "honnef.co/go/tools/analysis/facts/generated" 10 "honnef.co/go/tools/analysis/lint" 11 "honnef.co/go/tools/analysis/report" 12 "honnef.co/go/tools/pattern" 13 14 "golang.org/x/tools/go/analysis" 15 ) 16 17 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ 18 Analyzer: &analysis.Analyzer{ 19 Name: "S1020", 20 Run: run, 21 Requires: append([]*analysis.Analyzer{generated.Analyzer}, code.RequiredAnalyzers...), 22 }, 23 Doc: &lint.RawDocumentation{ 24 Title: `Omit redundant nil check in type assertion`, 25 Before: `if _, ok := i.(T); ok && i != nil {}`, 26 After: `if _, ok := i.(T); ok {}`, 27 Since: "2017.1", 28 MergeIf: lint.MergeIfAny, 29 }, 30 }) 31 32 var Analyzer = SCAnalyzer.Analyzer 33 34 var ( 35 checkAssertNotNilFn1Q = pattern.MustParse(` 36 (IfStmt 37 (AssignStmt [(Ident "_") ok@(Object _)] _ [(TypeAssertExpr assert@(Object _) _)]) 38 (Or 39 (BinaryExpr ok "&&" (BinaryExpr assert "!=" (Builtin "nil"))) 40 (BinaryExpr (BinaryExpr assert "!=" (Builtin "nil")) "&&" ok)) 41 _ 42 _)`) 43 checkAssertNotNilFn2Q = pattern.MustParse(` 44 (IfStmt 45 nil 46 (BinaryExpr lhs@(Object _) "!=" (Builtin "nil")) 47 [ 48 ifstmt@(IfStmt 49 (AssignStmt [(Ident "_") ok@(Object _)] _ [(TypeAssertExpr lhs _)]) 50 ok 51 _ 52 nil) 53 ] 54 nil)`) 55 ) 56 57 func run(pass *analysis.Pass) (any, error) { 58 for node, m := range code.Matches(pass, checkAssertNotNilFn1Q) { 59 assert := m.State["assert"].(types.Object) 60 assign := m.State["ok"].(types.Object) 61 report.Report(pass, node, fmt.Sprintf("when %s is true, %s can't be nil", assign.Name(), assert.Name()), 62 report.ShortRange(), 63 report.FilterGenerated()) 64 } 65 for _, m := range code.Matches(pass, checkAssertNotNilFn2Q) { 66 ifstmt := m.State["ifstmt"].(*ast.IfStmt) 67 lhs := m.State["lhs"].(types.Object) 68 assignIdent := m.State["ok"].(types.Object) 69 report.Report(pass, ifstmt, fmt.Sprintf("when %s is true, %s can't be nil", assignIdent.Name(), lhs.Name()), 70 report.ShortRange(), 71 report.FilterGenerated()) 72 } 73 return nil, nil 74 }