feat: detect potential nested contexts in function declarations

This commit is contained in:
Gabriel Augendre 2025-01-13 15:46:00 +01:00
parent 939d65bc16
commit 5b689092ef
2 changed files with 34 additions and 13 deletions
pkg/analyzer
testdata/src

View file

@ -30,6 +30,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
(*ast.ForStmt)(nil), (*ast.ForStmt)(nil),
(*ast.RangeStmt)(nil), (*ast.RangeStmt)(nil),
(*ast.FuncLit)(nil), (*ast.FuncLit)(nil),
(*ast.FuncDecl)(nil),
} }
inspctr.Preorder(nodeFilter, func(node ast.Node) { inspctr.Preorder(nodeFilter, func(node ast.Node) {
@ -81,25 +82,23 @@ func getReportMessage(node ast.Node) string {
return "nested context in loop" return "nested context in loop"
case *ast.FuncLit: case *ast.FuncLit:
return "nested context in function literal" return "nested context in function literal"
case *ast.FuncDecl:
return "potential nested context in function declaration"
default: default:
return "unsupported nested context type" return "unsupported nested context type"
} }
} }
func getBody(node ast.Node) (*ast.BlockStmt, error) { func getBody(node ast.Node) (*ast.BlockStmt, error) {
forStmt, ok := node.(*ast.ForStmt) switch typedNode := node.(type) {
if ok { case *ast.ForStmt:
return forStmt.Body, nil return typedNode.Body, nil
} case *ast.RangeStmt:
return typedNode.Body, nil
rangeStmt, ok := node.(*ast.RangeStmt) case *ast.FuncLit:
if ok { return typedNode.Body, nil
return rangeStmt.Body, nil case *ast.FuncDecl:
} return typedNode.Body, nil
funcLit, ok := node.(*ast.FuncLit)
if ok {
return funcLit.Body, nil
} }
return nil, errUnknown return nil, errUnknown

View file

@ -249,3 +249,25 @@ func testCasesInit(t *testing.T) {
}) })
} }
} }
type Container struct {
Ctx context.Context
}
func something() func(*Container) {
return func(r *Container) {
ctx := r.Ctx
ctx = context.WithValue(ctx, "key", "val")
r.Ctx = ctx // want "nested context in function literal"
}
}
func other() func(*Container) {
return blah
}
func blah(r *Container) {
ctx := r.Ctx
ctx = context.WithValue(ctx, "key", "val")
r.Ctx = ctx // want "potential nested context in function declaration"
}