mirror of
https://github.com/mgechev/revive.git
synced 2025-03-17 20:57:58 +02:00
add new rule time equal (#584)
This commit is contained in:
parent
111721be47
commit
62db66915b
@ -398,6 +398,7 @@ List of all available rules. The rules ported from `golint` are left unchanged a
|
||||
| Name | Config | Description | `golint` | Typed |
|
||||
| --------------------- | :----: | :--------------------------------------------------------------- | :------: | :---: |
|
||||
| [`context-keys-type`](./RULES_DESCRIPTIONS.md#context-key-types) | n/a | Disallows the usage of basic types in `context.WithValue`. | yes | yes |
|
||||
| [`time-equal`](./RULES_DESCRIPTIONS.md#time-equal) | n/a | Suggests to use `time.Time.Equal` instead of `==` and `!=` for equality check time. | no | yes |
|
||||
| [`time-naming`](./RULES_DESCRIPTIONS.md#time-naming) | n/a | Conventions around the naming of time variables. | yes | yes |
|
||||
| [`var-declaration`](./RULES_DESCRIPTIONS.md#var-declaration) | n/a | Reduces redundancies around variable declaration. | yes | yes |
|
||||
| [`unexported-return`](./RULES_DESCRIPTIONS.md#unexported-return) | n/a | Warns when a public return is from unexported type. | yes | yes |
|
||||
|
@ -56,6 +56,7 @@ List of all available rules.
|
||||
- [struct-tag](#struct-tag)
|
||||
- [string-format](#string-format)
|
||||
- [superfluous-else](#superfluous-else)
|
||||
- [time-equal](#time-equal)
|
||||
- [time-naming](#time-naming)
|
||||
- [var-naming](#var-naming)
|
||||
- [var-declaration](#var-declaration)
|
||||
@ -547,6 +548,12 @@ This rule highlights redundant _else-blocks_ that can be eliminated from the cod
|
||||
|
||||
_Configuration_: N/A
|
||||
|
||||
## time-equal
|
||||
|
||||
_Description_: This rule warns when using `==` and `!=` for equality check `time.Time` and suggest to `time.time.Equal` method, for about information follow this [link](https://pkg.go.dev/time#Time)
|
||||
|
||||
_Configuration_: N/A
|
||||
|
||||
## time-naming
|
||||
|
||||
_Description_: Using unit-specific suffix like "Secs", "Mins", ... when naming variables of type `time.Duration` can be misleading, this rule highlights those cases.
|
||||
|
@ -81,6 +81,7 @@ var allRules = append([]lint.Rule{
|
||||
&rule.NestedStructs{},
|
||||
&rule.IfReturnRule{},
|
||||
&rule.UselessBreak{},
|
||||
&rule.TimeEqualRule{},
|
||||
}, defaultRules...)
|
||||
|
||||
var allFormatters = []lint.Formatter{
|
||||
|
76
rule/time-equal.go
Normal file
76
rule/time-equal.go
Normal file
@ -0,0 +1,76 @@
|
||||
package rule
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
|
||||
"github.com/mgechev/revive/lint"
|
||||
)
|
||||
|
||||
// TimeEqualRule shows where "==" and "!=" used for equality check time.Time
|
||||
type TimeEqualRule struct{}
|
||||
|
||||
// Apply applies the rule to given file.
|
||||
func (*TimeEqualRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
|
||||
var failures []lint.Failure
|
||||
|
||||
onFailure := func(failure lint.Failure) {
|
||||
failures = append(failures, failure)
|
||||
}
|
||||
|
||||
w := &lintTimeEqual{file, onFailure}
|
||||
if w.file.Pkg.TypeCheck() != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ast.Walk(w, file.AST)
|
||||
return failures
|
||||
}
|
||||
|
||||
// Name returns the rule name.
|
||||
func (*TimeEqualRule) Name() string {
|
||||
return "time-equal"
|
||||
}
|
||||
|
||||
type lintTimeEqual struct {
|
||||
file *lint.File
|
||||
onFailure func(lint.Failure)
|
||||
}
|
||||
|
||||
func (l *lintTimeEqual) Visit(node ast.Node) ast.Visitor {
|
||||
expr, ok := node.(*ast.BinaryExpr)
|
||||
if !ok {
|
||||
return l
|
||||
}
|
||||
|
||||
switch expr.Op {
|
||||
case token.EQL, token.NEQ:
|
||||
default:
|
||||
return l
|
||||
}
|
||||
|
||||
xtyp := l.file.Pkg.TypeOf(expr.X)
|
||||
ytyp := l.file.Pkg.TypeOf(expr.Y)
|
||||
|
||||
if !isNamedType(xtyp, "time", "Time") || !isNamedType(ytyp, "time", "Time") {
|
||||
return l
|
||||
}
|
||||
|
||||
var failure string
|
||||
switch expr.Op {
|
||||
case token.EQL:
|
||||
failure = fmt.Sprintf("use %s.Equal(%s) instead of %q operator", expr.X, expr.Y, expr.Op)
|
||||
case token.NEQ:
|
||||
failure = fmt.Sprintf("use !%s.Equal(%s) instead of %q operator", expr.X, expr.Y, expr.Op)
|
||||
}
|
||||
|
||||
l.onFailure(lint.Failure{
|
||||
Category: "time",
|
||||
Confidence: 1,
|
||||
Node: node,
|
||||
Failure: failure,
|
||||
})
|
||||
|
||||
return l
|
||||
}
|
12
test/time-equal_test.go
Normal file
12
test/time-equal_test.go
Normal file
@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mgechev/revive/rule"
|
||||
)
|
||||
|
||||
// TestTimeEqual rule.
|
||||
func TestTimeEqual(t *testing.T) {
|
||||
testRule(t, "time-equal", &rule.TimeEqualRule{})
|
||||
}
|
14
testdata/time-equal.go
vendored
Normal file
14
testdata/time-equal.go
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package pkg
|
||||
|
||||
import "time"
|
||||
|
||||
func t() bool {
|
||||
t := time.Now()
|
||||
u := t
|
||||
|
||||
if !t.After(u) {
|
||||
return t == u // MATCH /use t.Equal(u) instead of "==" operator/
|
||||
}
|
||||
|
||||
return t != u // MATCH /use !t.Equal(u) instead of "!=" operator/
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user