sa3001.go (1312B)
1 package sa3001 2 3 import ( 4 "fmt" 5 "go/ast" 6 7 "honnef.co/go/tools/analysis/code" 8 "honnef.co/go/tools/analysis/lint" 9 "honnef.co/go/tools/analysis/report" 10 "honnef.co/go/tools/pattern" 11 12 "golang.org/x/tools/go/analysis" 13 ) 14 15 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ 16 Analyzer: &analysis.Analyzer{ 17 Name: "SA3001", 18 Run: run, 19 Requires: code.RequiredAnalyzers, 20 }, 21 Doc: &lint.RawDocumentation{ 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 var query = pattern.MustParse(`(AssignStmt sel@(SelectorExpr selX (Ident "N")) "=" [_] )`) 36 37 func run(pass *analysis.Pass) (any, error) { 38 for node, m := range code.Matches(pass, query) { 39 assign := node.(*ast.AssignStmt) 40 if !code.IsOfPointerToTypeWithName(pass, m.State["selX"].(ast.Expr), "testing.B") { 41 continue 42 } 43 report.Report(pass, assign, 44 fmt.Sprintf("should not assign to %s", report.Render(pass, m.State["sel"]))) 45 } 46 return nil, nil 47 }