github.com/songshiyun/revive@v1.1.5-0.20220323112655-f8433a19b3c5/rule/unnecessary-stmt.go (about) 1 package rule 2 3 import ( 4 "go/ast" 5 "go/token" 6 7 "github.com/songshiyun/revive/lint" 8 ) 9 10 // UnnecessaryStmtRule warns on unnecessary statements. 11 type UnnecessaryStmtRule struct{} 12 13 // Apply applies the rule to given file. 14 func (r *UnnecessaryStmtRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 15 var failures []lint.Failure 16 onFailure := func(failure lint.Failure) { 17 failures = append(failures, failure) 18 } 19 20 w := lintUnnecessaryStmtRule{onFailure} 21 ast.Walk(w, file.AST) 22 return failures 23 } 24 25 // Name returns the rule name. 26 func (r *UnnecessaryStmtRule) Name() string { 27 return "unnecessary-stmt" 28 } 29 30 type lintUnnecessaryStmtRule struct { 31 onFailure func(lint.Failure) 32 } 33 34 func (w lintUnnecessaryStmtRule) Visit(node ast.Node) ast.Visitor { 35 switch n := node.(type) { 36 case *ast.FuncDecl: 37 if n.Body == nil || n.Type.Results != nil { 38 return w 39 } 40 stmts := n.Body.List 41 if len(stmts) == 0 { 42 return w 43 } 44 45 lastStmt := stmts[len(stmts)-1] 46 rs, ok := lastStmt.(*ast.ReturnStmt) 47 if !ok { 48 return w 49 } 50 51 if len(rs.Results) == 0 { 52 w.newFailure(lastStmt, "omit unnecessary return statement") 53 } 54 55 case *ast.SwitchStmt: 56 w.checkSwitchBody(n.Body) 57 case *ast.TypeSwitchStmt: 58 w.checkSwitchBody(n.Body) 59 case *ast.CaseClause: 60 if n.Body == nil { 61 return w 62 } 63 stmts := n.Body 64 if len(stmts) == 0 { 65 return w 66 } 67 68 lastStmt := stmts[len(stmts)-1] 69 rs, ok := lastStmt.(*ast.BranchStmt) 70 if !ok { 71 return w 72 } 73 74 if rs.Tok == token.BREAK && rs.Label == nil { 75 w.newFailure(lastStmt, "omit unnecessary break at the end of case clause") 76 } 77 } 78 79 return w 80 } 81 82 func (w lintUnnecessaryStmtRule) checkSwitchBody(b *ast.BlockStmt) { 83 cases := b.List 84 if len(cases) != 1 { 85 return 86 } 87 88 cc, ok := cases[0].(*ast.CaseClause) 89 if !ok { 90 return 91 } 92 93 if len(cc.List) > 1 { // skip cases with multiple expressions 94 return 95 } 96 97 w.newFailure(b, "switch with only one case can be replaced by an if-then") 98 } 99 100 func (w lintUnnecessaryStmtRule) newFailure(node ast.Node, msg string) { 101 w.onFailure(lint.Failure{ 102 Confidence: 1, 103 Node: node, 104 Category: "style", 105 Failure: msg, 106 }) 107 }