1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
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 (r *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 (r *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 (w *lintIdenticalBranches) identicalBranches(branches []*ast.BlockStmt) bool {
if len(branches) < 2 {
return false
}
ref := gofmt(branches[0])
for i := 1; i < len(branches); i++ {
if 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,
})
}
|