github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/staticcheck/sa3001/sa3001.go (about) 1 package sa3001 2 3 import ( 4 "fmt" 5 "go/ast" 6 7 "github.com/amarpal/go-tools/analysis/code" 8 "github.com/amarpal/go-tools/analysis/lint" 9 "github.com/amarpal/go-tools/analysis/report" 10 11 "golang.org/x/tools/go/analysis" 12 "golang.org/x/tools/go/analysis/passes/inspect" 13 ) 14 15 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ 16 Analyzer: &analysis.Analyzer{ 17 Name: "SA3001", 18 Run: run, 19 Requires: []*analysis.Analyzer{inspect.Analyzer}, 20 }, 21 Doc: &lint.Documentation{ 22 Title: `Assigning to \'b.N\' in benchmarks distorts the results`, 23 Text: `The testing package dynamically sets \'b.N\' to improve the reliability of 24 benchmarks and uses it in computations to determine the duration of a 25 single operation. Benchmark code must not alter \'b.N\' as this would 26 falsify results.`, 27 Since: "2017.1", 28 Severity: lint.SeverityError, 29 MergeIf: lint.MergeIfAny, 30 }, 31 }) 32 33 var Analyzer = SCAnalyzer.Analyzer 34 35 func run(pass *analysis.Pass) (interface{}, error) { 36 fn := func(node ast.Node) { 37 assign := node.(*ast.AssignStmt) 38 if len(assign.Lhs) != 1 || len(assign.Rhs) != 1 { 39 return 40 } 41 sel, ok := assign.Lhs[0].(*ast.SelectorExpr) 42 if !ok { 43 return 44 } 45 if sel.Sel.Name != "N" { 46 return 47 } 48 if !code.IsOfType(pass, sel.X, "*testing.B") { 49 return 50 } 51 report.Report(pass, assign, fmt.Sprintf("should not assign to %s", report.Render(pass, sel))) 52 } 53 code.Preorder(pass, fn, (*ast.AssignStmt)(nil)) 54 return nil, nil 55 }