1
0
mirror of https://github.com/mgechev/revive.git synced 2024-12-02 09:02:23 +02:00
revive/rule/identical-branches.go
2022-10-24 17:21:48 +02:00

85 lines
1.7 KiB
Go

package rule
import (
"go/ast"
"github.com/mgechev/revive/lint"
)
// IdenticalBranchesRule warns on constant logical expressions.
type IdenticalBranchesRule struct{}
// Apply applies the rule to given file.
func (*IdenticalBranchesRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
var failures []lint.Failure
onFailure := func(failure lint.Failure) {
failures = append(failures, failure)
}
astFile := file.AST
w := &lintIdenticalBranches{astFile, onFailure}
ast.Walk(w, astFile)
return failures
}
// Name returns the rule name.
func (*IdenticalBranchesRule) Name() string {
return "identical-branches"
}
type lintIdenticalBranches struct {
file *ast.File
onFailure func(lint.Failure)
}
func (w *lintIdenticalBranches) Visit(node ast.Node) ast.Visitor {
n, ok := node.(*ast.IfStmt)
if !ok {
return w
}
if n.Else == nil {
return w
}
branches := []*ast.BlockStmt{n.Body}
elseBranch, ok := n.Else.(*ast.BlockStmt)
if !ok { // if-else-if construction
return w
}
branches = append(branches, elseBranch)
if w.identicalBranches(branches) {
w.newFailure(n, "both branches of the if are identical")
}
return w
}
func (lintIdenticalBranches) identicalBranches(branches []*ast.BlockStmt) bool {
if len(branches) < 2 {
return false
}
ref := gofmt(branches[0])
refSize := len(branches[0].List)
for i := 1; i < len(branches); i++ {
currentSize := len(branches[i].List)
if currentSize != refSize || gofmt(branches[i]) != ref {
return false
}
}
return true
}
func (w lintIdenticalBranches) newFailure(node ast.Node, msg string) {
w.onFailure(lint.Failure{
Confidence: 1,
Node: node,
Category: "logic",
Failure: msg,
})
}