github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/identical-branches.go (about) 1 package rule 2 3 import ( 4 "go/ast" 5 6 "github.com/mgechev/revive/lint" 7 ) 8 9 // IdenticalBranchesRule warns on constant logical expressions. 10 type IdenticalBranchesRule struct{} 11 12 // Apply applies the rule to given file. 13 func (r *IdenticalBranchesRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 14 var failures []lint.Failure 15 16 onFailure := func(failure lint.Failure) { 17 failures = append(failures, failure) 18 } 19 20 astFile := file.AST 21 w := &lintIdenticalBranches{astFile, onFailure} 22 ast.Walk(w, astFile) 23 return failures 24 } 25 26 // Name returns the rule name. 27 func (r *IdenticalBranchesRule) Name() string { 28 return "identical-branches" 29 } 30 31 type lintIdenticalBranches struct { 32 file *ast.File 33 onFailure func(lint.Failure) 34 } 35 36 func (w *lintIdenticalBranches) Visit(node ast.Node) ast.Visitor { 37 n, ok := node.(*ast.IfStmt) 38 if !ok { 39 return w 40 } 41 42 if n.Else == nil { 43 return w 44 } 45 branches := []*ast.BlockStmt{n.Body} 46 47 elseBranch, ok := n.Else.(*ast.BlockStmt) 48 if !ok { // if-else-if construction 49 return w 50 } 51 branches = append(branches, elseBranch) 52 53 if w.identicalBranches(branches) { 54 w.newFailure(n, "both branches of the if are identical") 55 } 56 57 return w 58 } 59 60 func (w *lintIdenticalBranches) identicalBranches(branches []*ast.BlockStmt) bool { 61 if len(branches) < 2 { 62 return false 63 } 64 65 ref := gofmt(branches[0]) 66 for i := 1; i < len(branches); i++ { 67 if gofmt(branches[i]) != ref { 68 return false 69 } 70 } 71 72 return true 73 } 74 75 func (w lintIdenticalBranches) newFailure(node ast.Node, msg string) { 76 w.onFailure(lint.Failure{ 77 Confidence: 1, 78 Node: node, 79 Category: "logic", 80 Failure: msg, 81 }) 82 }