github.com/songshiyun/revive@v1.1.5-0.20220323112655-f8433a19b3c5/rule/time-equal.go (about) 1 package rule 2 3 import ( 4 "fmt" 5 "go/ast" 6 "go/token" 7 8 "github.com/songshiyun/revive/lint" 9 ) 10 11 // TimeEqualRule shows where "==" and "!=" used for equality check time.Time 12 type TimeEqualRule struct{} 13 14 // Apply applies the rule to given file. 15 func (*TimeEqualRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 16 var failures []lint.Failure 17 18 onFailure := func(failure lint.Failure) { 19 failures = append(failures, failure) 20 } 21 22 w := &lintTimeEqual{file, onFailure} 23 if w.file.Pkg.TypeCheck() != nil { 24 return nil 25 } 26 27 ast.Walk(w, file.AST) 28 return failures 29 } 30 31 // Name returns the rule name. 32 func (*TimeEqualRule) Name() string { 33 return "time-equal" 34 } 35 36 type lintTimeEqual struct { 37 file *lint.File 38 onFailure func(lint.Failure) 39 } 40 41 func (l *lintTimeEqual) Visit(node ast.Node) ast.Visitor { 42 expr, ok := node.(*ast.BinaryExpr) 43 if !ok { 44 return l 45 } 46 47 switch expr.Op { 48 case token.EQL, token.NEQ: 49 default: 50 return l 51 } 52 53 xtyp := l.file.Pkg.TypeOf(expr.X) 54 ytyp := l.file.Pkg.TypeOf(expr.Y) 55 56 if !isNamedType(xtyp, "time", "Time") || !isNamedType(ytyp, "time", "Time") { 57 return l 58 } 59 60 var failure string 61 switch expr.Op { 62 case token.EQL: 63 failure = fmt.Sprintf("use %s.Equal(%s) instead of %q operator", expr.X, expr.Y, expr.Op) 64 case token.NEQ: 65 failure = fmt.Sprintf("use !%s.Equal(%s) instead of %q operator", expr.X, expr.Y, expr.Op) 66 } 67 68 l.onFailure(lint.Failure{ 69 Category: "time", 70 Confidence: 1, 71 Node: node, 72 Failure: failure, 73 }) 74 75 return l 76 }