mirror of
				https://github.com/mgechev/revive.git
				synced 2025-10-30 23:37:49 +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