mirror of
https://github.com/mgechev/revive.git
synced 2025-11-29 22:28:23 +02:00
refactor: replaces calls to astutils.PickNodes with calls to astutils.SeekNode when possible (#1482)
This commit is contained in:
@@ -152,6 +152,49 @@ func (p picker) Visit(node ast.Node) ast.Visitor {
|
||||
return p
|
||||
}
|
||||
|
||||
// SeekNode yields the first node selected by the given selector function in the AST subtree with root n.
|
||||
// The function returns nil if no matching node is found in the subtree.
|
||||
func SeekNode[T ast.Node](n ast.Node, selector func(n ast.Node) bool) T {
|
||||
var result T
|
||||
|
||||
if n == nil {
|
||||
return result
|
||||
}
|
||||
|
||||
if selector == nil {
|
||||
return result
|
||||
}
|
||||
|
||||
onSelect := func(n ast.Node) {
|
||||
result, _ = n.(T)
|
||||
}
|
||||
|
||||
p := &seeker{selector: selector, onSelect: onSelect, found: false}
|
||||
ast.Walk(p, n)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
type seeker struct {
|
||||
selector func(n ast.Node) bool
|
||||
onSelect func(n ast.Node)
|
||||
found bool
|
||||
}
|
||||
|
||||
func (s *seeker) Visit(node ast.Node) ast.Visitor {
|
||||
if s.found {
|
||||
return nil // stop visiting subtree
|
||||
}
|
||||
|
||||
if s.selector(node) {
|
||||
s.onSelect(node)
|
||||
s.found = true
|
||||
return nil // skip visiting node children
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
var gofmtConfig = &printer.Config{Tabwidth: 8}
|
||||
|
||||
// GoFmt returns a string representation of an AST subtree.
|
||||
|
||||
@@ -78,9 +78,8 @@ func (w conditionVisitor) Visit(node ast.Node) ast.Visitor {
|
||||
return w.idents[ident.Name] == struct{}{}
|
||||
}
|
||||
|
||||
uses := astutils.PickNodes(ifStmt.Cond, findUsesOfIdents)
|
||||
|
||||
if len(uses) < 1 {
|
||||
uses := astutils.SeekNode[*ast.Ident](ifStmt.Cond, findUsesOfIdents)
|
||||
if uses == nil {
|
||||
return w
|
||||
}
|
||||
|
||||
@@ -88,7 +87,7 @@ func (w conditionVisitor) Visit(node ast.Node) ast.Visitor {
|
||||
Confidence: 1,
|
||||
Node: w.fd.Type.Params,
|
||||
Category: lint.FailureCategoryBadPractice,
|
||||
Failure: fmt.Sprintf("parameter '%s' seems to be a control flag, avoid control coupling", uses[0]),
|
||||
Failure: fmt.Sprintf("parameter '%s' seems to be a control flag, avoid control coupling", uses.Name),
|
||||
})
|
||||
|
||||
return nil
|
||||
|
||||
@@ -156,12 +156,12 @@ func (w *lintIfChainIdenticalBranches) Visit(node ast.Node) ast.Visitor {
|
||||
// isComplexCondition returns true if the given expression is "complex", false otherwise.
|
||||
// An expression is considered complex if it has a function call.
|
||||
func (*lintIfChainIdenticalBranches) isComplexCondition(expr ast.Expr) bool {
|
||||
calls := astutils.PickNodes(expr, func(n ast.Node) bool {
|
||||
call := astutils.SeekNode[*ast.CallExpr](expr, func(n ast.Node) bool {
|
||||
_, ok := n.(*ast.CallExpr)
|
||||
return ok
|
||||
})
|
||||
|
||||
return len(calls) > 0
|
||||
return call != nil
|
||||
}
|
||||
|
||||
// identicalBranches yields pairs of (line numbers) of identical branches from the given branches.
|
||||
|
||||
@@ -35,7 +35,7 @@ func (r *ModifiesValRecRule) Apply(file *lint.File, _ lint.Arguments) []lint.Fai
|
||||
continue // receiver is not modified
|
||||
}
|
||||
|
||||
methodReturnsReceiver := len(r.findReturnReceiverStatements(receiverName, funcDecl.Body)) > 0
|
||||
methodReturnsReceiver := r.seekReturnReceiverStatement(receiverName, funcDecl.Body) != nil
|
||||
if methodReturnsReceiver {
|
||||
continue // modification seems legit (see issue #1066)
|
||||
}
|
||||
@@ -79,7 +79,7 @@ func (*ModifiesValRecRule) getNameFromExpr(ie ast.Expr) string {
|
||||
return ident.Name
|
||||
}
|
||||
|
||||
func (r *ModifiesValRecRule) findReturnReceiverStatements(receiverName string, target ast.Node) []ast.Node {
|
||||
func (r *ModifiesValRecRule) seekReturnReceiverStatement(receiverName string, target ast.Node) ast.Node {
|
||||
finder := func(n ast.Node) bool {
|
||||
// look for returns with the receiver as value
|
||||
returnStatement, ok := n.(*ast.ReturnStmt)
|
||||
@@ -117,7 +117,7 @@ func (r *ModifiesValRecRule) findReturnReceiverStatements(receiverName string, t
|
||||
return false
|
||||
}
|
||||
|
||||
return astutils.PickNodes(target, finder)
|
||||
return astutils.SeekNode[ast.Node](target, finder)
|
||||
}
|
||||
|
||||
func (r *ModifiesValRecRule) mustSkip(receiver *ast.Field, pkg *lint.Package) bool {
|
||||
|
||||
@@ -64,14 +64,14 @@ func (w lintOptimizeOperandsOrderExpr) Visit(node ast.Node) ast.Visitor {
|
||||
}
|
||||
|
||||
// check if the left sub-expression contains a function call
|
||||
nodes := astutils.PickNodes(binExpr.X, isCaller)
|
||||
if len(nodes) < 1 {
|
||||
call := astutils.SeekNode[*ast.CallExpr](binExpr.X, isCaller)
|
||||
if call == nil {
|
||||
return w
|
||||
}
|
||||
|
||||
// check if the right sub-expression does not contain a function call
|
||||
nodes = astutils.PickNodes(binExpr.Y, isCaller)
|
||||
if len(nodes) > 0 {
|
||||
call = astutils.SeekNode[*ast.CallExpr](binExpr.Y, isCaller)
|
||||
if call != nil {
|
||||
return w
|
||||
}
|
||||
|
||||
|
||||
@@ -198,5 +198,5 @@ func (*lintUnconditionalRecursionRule) hasControlExit(node ast.Node) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return len(astutils.PickNodes(node, isExit)) != 0
|
||||
return astutils.SeekNode[ast.Node](node, isExit) != nil
|
||||
}
|
||||
|
||||
@@ -83,9 +83,8 @@ func (r *UnusedReceiverRule) Apply(file *lint.File, _ lint.Arguments) []lint.Fai
|
||||
|
||||
return isAnID && ident.Obj == recID.Obj
|
||||
}
|
||||
receiverUses := astutils.PickNodes(funcDecl.Body, selectReceiverUses)
|
||||
|
||||
if len(receiverUses) > 0 {
|
||||
receiverUse := astutils.SeekNode[ast.Node](funcDecl.Body, selectReceiverUses)
|
||||
if receiverUse != nil {
|
||||
continue // the receiver is referenced in the func body
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user