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  }