s1037.go (1863B)
1 package s1037 2 3 import ( 4 "go/ast" 5 6 "honnef.co/go/tools/analysis/code" 7 "honnef.co/go/tools/analysis/edit" 8 "honnef.co/go/tools/analysis/facts/generated" 9 "honnef.co/go/tools/analysis/lint" 10 "honnef.co/go/tools/analysis/report" 11 "honnef.co/go/tools/pattern" 12 13 "golang.org/x/tools/go/analysis" 14 ) 15 16 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ 17 Analyzer: &analysis.Analyzer{ 18 Name: "S1037", 19 Run: run, 20 Requires: append([]*analysis.Analyzer{generated.Analyzer}, code.RequiredAnalyzers...), 21 }, 22 Doc: &lint.RawDocumentation{ 23 Title: `Elaborate way of sleeping`, 24 Text: `Using a select statement with a single case receiving 25 from the result of \'time.After\' is a very elaborate way of sleeping that 26 can much simpler be expressed with a simple call to time.Sleep.`, 27 Since: "2020.1", 28 MergeIf: lint.MergeIfAny, 29 }, 30 }) 31 32 var Analyzer = SCAnalyzer.Analyzer 33 34 var ( 35 checkElaborateSleepQ = pattern.MustParse(`(SelectStmt (CommClause (UnaryExpr "<-" (CallExpr (Symbol "time.After") [arg])) body))`) 36 checkElaborateSleepR = pattern.MustParse(`(CallExpr (SelectorExpr (Ident "time") (Ident "Sleep")) [arg])`) 37 ) 38 39 func run(pass *analysis.Pass) (any, error) { 40 for node, m := range code.Matches(pass, checkElaborateSleepQ) { 41 if body, ok := m.State["body"].([]ast.Stmt); ok && len(body) == 0 { 42 report.Report(pass, node, "should use time.Sleep instead of elaborate way of sleeping", 43 report.ShortRange(), 44 report.FilterGenerated(), 45 report.Fixes(edit.Fix("Use time.Sleep", edit.ReplaceWithPattern(pass.Fset, node, checkElaborateSleepR, m.State)))) 46 } else { 47 // TODO(dh): we could make a suggested fix if the body 48 // doesn't declare or shadow any identifiers 49 report.Report(pass, node, "should use time.Sleep instead of elaborate way of sleeping", 50 report.ShortRange(), 51 report.FilterGenerated()) 52 } 53 } 54 return nil, nil 55 }