Compare commits

..

11 commits

Author SHA1 Message Date
Venkatesh Kotwade
c5973f5097
Merge c2c0e62d59 into 0d2c4019d4 2024-08-25 20:11:40 +00:00
Venkatesh Kotwade
c2c0e62d59 feat: also added support for multiple contexts 2024-08-26 01:41:16 +05:30
Venkatesh Kotwade
387c533fad added one more case 2024-08-26 01:35:09 +05:30
Venkatesh Kotwade
89a1841d57 refactor: use multi case 2024-08-26 01:29:37 +05:30
Venkatesh Kotwade
71bde6a5f6 use node instead of block 2024-08-26 01:28:11 +05:30
Venkatesh Kotwade
07aa8cc6a2 refactor: Update getReportMessage function to handle unsupported nested context types 2024-08-25 23:32:30 +05:30
Venkatesh Kotwade
b46089e786 feat: Improve detection of nested contexts in function literals 2024-08-25 23:32:30 +05:30
Venkatesh Kotwade
0f9412c2ac feat: Add detection for nested contexts in function literals 2024-08-25 23:32:30 +05:30
0d2c4019d4 update go.mod to 1.22
Some checks are pending
Go / build (1.22, macos-latest) (push) Waiting to run
Go / build (1.22, ubuntu-latest) (push) Waiting to run
Go / build (1.22, windows-latest) (push) Waiting to run
Go / build (1.23, macos-latest) (push) Waiting to run
Go / build (1.23, ubuntu-latest) (push) Waiting to run
Go / build (1.23, windows-latest) (push) Waiting to run
golangci-lint / lint (1.21) (push) Waiting to run
golangci-lint / lint (1.22) (push) Waiting to run
2024-08-25 18:15:22 +02:00
77afd24616 cd: always run all test jobs 2024-08-25 16:00:22 +02:00
2e1ec44b79 drop support for go 1.21, and test against released go 1.23 2024-08-25 15:59:59 +02:00
4 changed files with 30 additions and 17 deletions

View file

@ -14,8 +14,9 @@ permissions:
jobs:
build:
strategy:
fail-fast: false
matrix:
go: ['1.21', '1.22', '1.23.0-rc.2']
go: ['1.22', '1.23']
os: [macos-latest, windows-latest, ubuntu-latest]
name: build
runs-on: ${{ matrix.os }}

2
go.mod
View file

@ -1,6 +1,6 @@
module github.com/Crocmagnon/fatcontext
go 1.21
go 1.22.6
require golang.org/x/tools v0.23.0

View file

@ -38,7 +38,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
return
}
assignStmt := findNestedContext(pass, body, body.List)
assignStmt := findNestedContext(pass, node, body.List)
if assignStmt == nil {
return
}
@ -78,9 +78,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
func getReportMessage(node ast.Node) string {
switch node.(type) {
case *ast.ForStmt:
return "nested context in loop"
case *ast.RangeStmt:
case *ast.ForStmt, *ast.RangeStmt:
return "nested context in loop"
case *ast.FuncLit:
return "nested context in function literal"
@ -108,46 +106,46 @@ func getBody(node ast.Node) (*ast.BlockStmt, error) {
return nil, errUnknown
}
func findNestedContext(pass *analysis.Pass, block *ast.BlockStmt, stmts []ast.Stmt) *ast.AssignStmt {
func findNestedContext(pass *analysis.Pass, node ast.Node, stmts []ast.Stmt) *ast.AssignStmt {
for _, stmt := range stmts {
// Recurse if necessary
if inner, ok := stmt.(*ast.BlockStmt); ok {
found := findNestedContext(pass, inner, inner.List)
found := findNestedContext(pass, node, inner.List)
if found != nil {
return found
}
}
if inner, ok := stmt.(*ast.IfStmt); ok {
found := findNestedContext(pass, inner.Body, inner.Body.List)
found := findNestedContext(pass, node, inner.Body.List)
if found != nil {
return found
}
}
if inner, ok := stmt.(*ast.SwitchStmt); ok {
found := findNestedContext(pass, inner.Body, inner.Body.List)
found := findNestedContext(pass, node, inner.Body.List)
if found != nil {
return found
}
}
if inner, ok := stmt.(*ast.CaseClause); ok {
found := findNestedContext(pass, block, inner.Body)
found := findNestedContext(pass, node, inner.Body)
if found != nil {
return found
}
}
if inner, ok := stmt.(*ast.SelectStmt); ok {
found := findNestedContext(pass, inner.Body, inner.Body.List)
found := findNestedContext(pass, node, inner.Body.List)
if found != nil {
return found
}
}
if inner, ok := stmt.(*ast.CommClause); ok {
found := findNestedContext(pass, block, inner.Body)
found := findNestedContext(pass, node, inner.Body)
if found != nil {
return found
}
@ -169,13 +167,13 @@ func findNestedContext(pass *analysis.Pass, block *ast.BlockStmt, stmts []ast.St
}
if assignStmt.Tok == token.DEFINE {
break
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 checkObjectScopeWithinBlock(obj.Parent(), block) {
if checkObjectScopeWithinNode(obj.Parent(), node) {
continue // definition is within the loop
}
}
@ -187,12 +185,12 @@ func findNestedContext(pass *analysis.Pass, block *ast.BlockStmt, stmts []ast.St
return nil
}
func checkObjectScopeWithinBlock(scope *types.Scope, block *ast.BlockStmt) bool {
func checkObjectScopeWithinNode(scope *types.Scope, node ast.Node) bool {
if scope == nil {
return false
}
if scope.Pos() >= block.Pos() && scope.End() <= block.End() {
if scope.Pos() >= node.Pos() && scope.End() <= node.End() {
return true
}

View file

@ -65,6 +65,20 @@ func example() {
ctx = wrapContext(ctx) // want "nested context in function literal"
}
// this is fine because the context is created in the loop
for {
if ctx := context.Background(); doSomething() != nil {
ctx = wrapContext(ctx)
}
}
for {
ctx2 := context.Background()
ctx = wrapContext(ctx) // want "nested context in loop"
if doSomething() != nil {
ctx2 = wrapContext(ctx2)
}
}
}
func wrapContext(ctx context.Context) context.Context {