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:
parent
cdb82683b1
commit
fb5bbe72e7
@ -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
|
||||
|
16
testdata/unconditional-recursion.go
vendored
16
testdata/unconditional-recursion.go
vendored
@ -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/
|
||||
}()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user