1
0
mirror of https://github.com/mgechev/revive.git synced 2025-11-23 22:04:49 +02:00

Refactors atomic rule code to move gofmt function to utils.go (issue #79) (#80)

* Refactoring on atomic rule:
-Main modification: move func gofmt to utils.go

* Refactoring on constant-logical-expr rule
Simplifies equality check of subexpressions by using gofmt function
This commit is contained in:
SalvadorC
2018-10-03 20:56:57 +02:00
committed by Minko Gechev
parent e9013628d7
commit da63d0a965
3 changed files with 21 additions and 40 deletions

View File

@@ -1,10 +1,7 @@
package rule package rule
import ( import (
"bytes"
"fmt"
"go/ast" "go/ast"
"go/printer"
"go/token" "go/token"
"go/types" "go/types"
@@ -18,7 +15,7 @@ type AtomicRule struct{}
func (r *AtomicRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { func (r *AtomicRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
var failures []lint.Failure var failures []lint.Failure
walker := atomic{ walker := atomic{
file: file, pkgTypesInfo: file.Pkg.TypesInfo,
onFailure: func(failure lint.Failure) { onFailure: func(failure lint.Failure) {
failures = append(failures, failure) failures = append(failures, failure)
}, },
@@ -35,8 +32,8 @@ func (r *AtomicRule) Name() string {
} }
type atomic struct { type atomic struct {
file *lint.File pkgTypesInfo *types.Info
onFailure func(lint.Failure) onFailure func(lint.Failure)
} }
func (w atomic) Visit(node ast.Node) ast.Visitor { func (w atomic) Visit(node ast.Node) ast.Visitor {
@@ -46,10 +43,10 @@ func (w atomic) Visit(node ast.Node) ast.Visitor {
} }
if len(n.Lhs) != len(n.Rhs) { if len(n.Lhs) != len(n.Rhs) {
return w return nil // skip assignment sub-tree
} }
if len(n.Lhs) == 1 && n.Tok == token.DEFINE { if len(n.Lhs) == 1 && n.Tok == token.DEFINE {
return w return nil // skip assignment sub-tree
} }
for i, right := range n.Rhs { for i, right := range n.Rhs {
@@ -62,8 +59,8 @@ func (w atomic) Visit(node ast.Node) ast.Visitor {
continue continue
} }
pkgIdent, _ := sel.X.(*ast.Ident) pkgIdent, _ := sel.X.(*ast.Ident)
if w.file.Pkg.TypesInfo != nil { if w.pkgTypesInfo != nil {
pkgName, ok := w.file.Pkg.TypesInfo.Uses[pkgIdent].(*types.PkgName) pkgName, ok := w.pkgTypesInfo.Uses[pkgIdent].(*types.PkgName)
if !ok || pkgName.Imported().Path() != "sync/atomic" { if !ok || pkgName.Imported().Path() != "sync/atomic" {
continue continue
} }
@@ -79,15 +76,15 @@ func (w atomic) Visit(node ast.Node) ast.Visitor {
broken := false broken := false
if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND { if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND {
broken = w.gofmt(left) == w.gofmt(uarg.X) broken = gofmt(left) == gofmt(uarg.X)
} else if star, ok := left.(*ast.StarExpr); ok { } else if star, ok := left.(*ast.StarExpr); ok {
broken = w.gofmt(star.X) == w.gofmt(arg) broken = gofmt(star.X) == gofmt(arg)
} }
if broken { if broken {
w.onFailure(lint.Failure{ w.onFailure(lint.Failure{
Confidence: 1, Confidence: 1,
Failure: fmt.Sprintf("direct assignment to atomic value"), Failure: "direct assignment to atomic value",
Node: n, Node: n,
}) })
} }
@@ -95,11 +92,3 @@ func (w atomic) Visit(node ast.Node) ast.Visitor {
} }
return w return w
} }
// gofmt returns a string representation of the expression.
func (w atomic) gofmt(x ast.Expr) string {
buf := bytes.Buffer{}
fs := token.NewFileSet()
printer.Fprint(&buf, fs, x)
return buf.String()
}

View File

@@ -1,11 +1,8 @@
package rule package rule
import ( import (
"bytes"
"fmt"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
"go/ast" "go/ast"
"go/format"
"go/token" "go/token"
) )
@@ -43,7 +40,7 @@ func (w *lintConstantLogicalExpr) Visit(node ast.Node) ast.Visitor {
return w return w
} }
if !w.areEqual(n.X, n.Y) { if gofmt(n.X) != gofmt(n.Y) { // check if subexpressions are the same
return w return w
} }
@@ -81,21 +78,6 @@ func (w *lintConstantLogicalExpr) isInequalityOperator(t token.Token) bool {
return false return false
} }
func (w lintConstantLogicalExpr) areEqual(x, y ast.Expr) bool {
fset := token.NewFileSet()
var buf1 bytes.Buffer
if err := format.Node(&buf1, fset, x); err != nil {
return false // keep going in case of error
}
var buf2 bytes.Buffer
if err := format.Node(&buf2, fset, y); err != nil {
return false // keep going in case of error
}
return fmt.Sprintf("%s", buf1.Bytes()) == fmt.Sprintf("%s", buf2.Bytes())
}
func (w lintConstantLogicalExpr) newFailure(node ast.Node, msg string) { func (w lintConstantLogicalExpr) newFailure(node ast.Node, msg string) {
w.onFailure(lint.Failure{ w.onFailure(lint.Failure{
Confidence: 1, Confidence: 1,

View File

@@ -1,8 +1,10 @@
package rule package rule
import ( import (
"bytes"
"fmt" "fmt"
"go/ast" "go/ast"
"go/printer"
"go/token" "go/token"
"go/types" "go/types"
"regexp" "regexp"
@@ -179,3 +181,11 @@ func isExprABooleanLit(n ast.Node) (lexeme string, ok bool) {
return oper.Name, (oper.Name == trueName || oper.Name == falseName) return oper.Name, (oper.Name == trueName || oper.Name == falseName)
} }
// gofmt returns a string representation of the expression.
func gofmt(x ast.Expr) string {
buf := bytes.Buffer{}
fs := token.NewFileSet()
printer.Fprint(&buf, fs, x)
return buf.String()
}