Skip to content

Commit

Permalink
feat: ignore context.TODO and context.Background
Browse files Browse the repository at this point in the history
  • Loading branch information
Crocmagnon committed Jan 14, 2025
1 parent 52f7fb5 commit 326edc3
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 22 deletions.
69 changes: 48 additions & 21 deletions pkg/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"go/ast"
"go/printer"
"go/token"
"go/types"
"slices"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
Expand Down Expand Up @@ -169,13 +169,14 @@ func findNestedContext(pass *analysis.Pass, node ast.Node, stmts []ast.Stmt) *as
continue
}

// Ignore [context.Background] & [context.TODO].
if isContextFunction(assignStmt.Rhs[0], "Background", "TODO") {
continue
}

// allow assignment to non-pointer children of values defined within the loop
if lhs := getRootIdent(pass, assignStmt.Lhs[0]); lhs != nil {
if obj := pass.TypesInfo.ObjectOf(lhs); obj != nil {
if checkObjectScopeWithinNode(obj.Parent(), node) {
continue // definition is within the loop
}
}
if isWithinLoop(assignStmt.Lhs[0], node, pass) {
continue
}

return assignStmt
Expand All @@ -184,16 +185,51 @@ func findNestedContext(pass *analysis.Pass, node ast.Node, stmts []ast.Stmt) *as
return nil
}

func checkObjectScopeWithinNode(scope *types.Scope, node ast.Node) bool {
if scope == nil {
// render returns the pretty-print of the given node
func render(fset *token.FileSet, x interface{}) ([]byte, error) {
var buf bytes.Buffer
if err := printer.Fprint(&buf, fset, x); err != nil {
return nil, fmt.Errorf("printing node: %w", err)
}
return buf.Bytes(), nil
}

func isContextFunction(exp ast.Expr, fnName ...string) bool {
call, ok := exp.(*ast.CallExpr)
if !ok {
return false
}

selector, ok := call.Fun.(*ast.SelectorExpr)
if !ok {
return false
}

ident, ok := selector.X.(*ast.Ident)
if !ok {
return false
}

return ident.Name == "context" && slices.Contains(fnName, selector.Sel.Name)
}

func isWithinLoop(exp ast.Expr, node ast.Node, pass *analysis.Pass) bool {
lhs := getRootIdent(pass, exp)
if lhs == nil {
return false
}

if scope.Pos() >= node.Pos() && scope.End() <= node.End() {
return true
obj := pass.TypesInfo.ObjectOf(lhs)
if obj == nil {
return false
}

scope := obj.Parent()
if scope == nil {
return false
}

return false
return scope.Pos() >= node.Pos() && scope.End() <= node.End()
}

func getRootIdent(pass *analysis.Pass, node ast.Node) *ast.Ident {
Expand All @@ -213,12 +249,3 @@ func getRootIdent(pass *analysis.Pass, node ast.Node) *ast.Ident {
}
}
}

// render returns the pretty-print of the given node
func render(fset *token.FileSet, x interface{}) ([]byte, error) {
var buf bytes.Buffer
if err := printer.Fprint(&buf, fset, x); err != nil {
return nil, fmt.Errorf("printing node: %w", err)
}
return buf.Bytes(), nil
}
23 changes: 22 additions & 1 deletion testdata/src/example.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package src

import "context"
import (
"context"
"testing"
)

func example() {
ctx := context.Background()
Expand Down Expand Up @@ -228,3 +231,21 @@ func okMiddleware2(ctx context.Context) func(ctx context.Context) error {
func doSomethingWithCtx(ctx context.Context) error {
return nil
}

func testCasesInit(t *testing.T) {
cases := []struct {
ctx context.Context
}{
{},
{
ctx: context.WithValue(context.Background(), "key", "value"),
},
}
for _, tc := range cases {
t.Run("some test", func(t *testing.T) {
if tc.ctx == nil {
tc.ctx = context.Background()
}
})
}
}

0 comments on commit 326edc3

Please # to comment.