1
0
mirror of https://github.com/mgechev/revive.git synced 2025-01-24 03:47:45 +02:00

fix: literal calls case (#909)

This commit is contained in:
Marcin Federowicz 2023-09-30 10:18:17 +02:00 committed by GitHub
parent cdb82683b1
commit fb5bbe72e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 10 deletions

View File

@ -45,8 +45,9 @@ type funcStatus struct {
}
type lintUnconditionalRecursionRule struct {
onFailure func(lint.Failure)
currentFunc *funcStatus
onFailure func(lint.Failure)
currentFunc *funcStatus
inGoStatement bool
}
// Visit will traverse the file AST.
@ -68,9 +69,13 @@ func (w lintUnconditionalRecursionRule) Visit(node ast.Node) ast.Visitor {
default:
rec = n.Recv.List[0].Names[0]
}
w.currentFunc = &funcStatus{&funcDesc{rec, n.Name}, false}
case *ast.CallExpr:
// check if call arguments has a recursive call
for _, arg := range n.Args {
ast.Walk(w, arg)
}
var funcID *ast.Ident
var selector *ast.Ident
switch c := n.Fun.(type) {
@ -84,6 +89,9 @@ func (w lintUnconditionalRecursionRule) Visit(node ast.Node) ast.Visitor {
return nil
}
funcID = c.Sel
case *ast.FuncLit:
ast.Walk(w, c.Body) // analyze the body of the function literal
return nil
default:
return w
}
@ -93,11 +101,12 @@ func (w lintUnconditionalRecursionRule) Visit(node ast.Node) ast.Visitor {
w.currentFunc.funcDesc.equal(&funcDesc{selector, funcID}) {
w.onFailure(lint.Failure{
Category: "logic",
Confidence: 1,
Confidence: 0.8,
Node: n,
Failure: "unconditional recursive call",
})
}
return nil
case *ast.IfStmt:
w.updateFuncStatus(n.Body)
w.updateFuncStatus(n.Else)
@ -115,16 +124,21 @@ func (w lintUnconditionalRecursionRule) Visit(node ast.Node) ast.Visitor {
w.updateFuncStatus(n.Body)
return nil
case *ast.GoStmt:
for _, a := range n.Call.Args {
ast.Walk(w, a) // check if arguments have a recursive call
}
return nil // recursive async call is not an issue
w.inGoStatement = true
ast.Walk(w, n.Call)
w.inGoStatement = false
return nil
case *ast.ForStmt:
if n.Cond != nil {
return nil
}
// unconditional loop
return w
case *ast.FuncLit:
if w.inGoStatement {
return w
}
return nil // literal call (closure) is not necessarily an issue
}
return w

View File

@ -134,8 +134,8 @@ func ur10() {
ur10()
}
func ur11() {
go ur11()
func ur11() { // this pattern produces "infinite" number of goroutines
go ur11() // MATCH /unconditional recursive call/
}
func ur12() {
@ -187,3 +187,15 @@ func (*fooType) BarFunc() {
func (_ *fooType) BazFunc() {
BazFunc()
}
// Tests for #902
func falsePositiveFuncLiteral() {
_ = foo(func() {
falsePositiveFuncLiteral()
})
}
func nr902() {
go func() {
nr902() // MATCH /unconditional recursive call/
}()
}