|
| 1 | +package setuplognilerrorcheck |
| 2 | + |
| 3 | +import ( |
| 4 | + "go/ast" |
| 5 | + "golang.org/x/tools/go/analysis" |
| 6 | +) |
| 7 | + |
| 8 | +var SetupLogNilErrorCheck = &analysis.Analyzer{ |
| 9 | + Name: "setuplognilerrorcheck", |
| 10 | + Doc: "check for setupLog.Error(nil, ...) calls with nil as the first argument", |
| 11 | + Run: runSetupLogNilErrorCheck, |
| 12 | +} |
| 13 | + |
| 14 | +func runSetupLogNilErrorCheck(pass *analysis.Pass) (interface{}, error) { |
| 15 | + for _, f := range pass.Files { |
| 16 | + ast.Inspect(f, func(n ast.Node) bool { |
| 17 | + expr, ok := n.(*ast.CallExpr) |
| 18 | + if !ok { |
| 19 | + return true |
| 20 | + } |
| 21 | + |
| 22 | + selectorExpr, ok := expr.Fun.(*ast.SelectorExpr) |
| 23 | + if !ok || selectorExpr.Sel.Name != "Error" { |
| 24 | + return true |
| 25 | + } |
| 26 | + |
| 27 | + i, ok := selectorExpr.X.(*ast.Ident) |
| 28 | + if !ok || i.Name != "setupLog" { |
| 29 | + return true |
| 30 | + } |
| 31 | + |
| 32 | + if len(expr.Args) > 0 { |
| 33 | + if arg, ok := expr.Args[0].(*ast.Ident); ok && arg.Name == "nil" { |
| 34 | + pass.Reportf(expr.Pos(), "Avoid using 'setupLog.Error(nil, ...)'. Instead, use 'errors.New()' "+ |
| 35 | + "or 'fmt.Errorf()' to ensure logs are created. Using 'nil' for errors can result in silent "+ |
| 36 | + "failures, making bugs harder to detect.") |
| 37 | + } |
| 38 | + } |
| 39 | + return true |
| 40 | + }) |
| 41 | + } |
| 42 | + return nil, nil |
| 43 | +} |
0 commit comments