From 30bf101a9f8e8a2dbc2f2be34e2ef06464036b08 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Thu, 25 May 2023 19:54:25 +0200 Subject: checkFunctions: Move function body `ast.Inspect` to named function Clean up the rest of `checkFunctions`. --- defererr.go | 63 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 31 deletions(-) (limited to 'defererr.go') diff --git a/defererr.go b/defererr.go index 96c5569..c835131 100644 --- a/defererr.go +++ b/defererr.go @@ -2,7 +2,6 @@ package defererr import ( - "fmt" "go/ast" "go/token" "go/types" @@ -100,39 +99,13 @@ func checkFunctions(pass *analysis.Pass, node ast.Node) { fState := newFunctionState() - // Is it possible to generalise this to other types, and look for - // anything set in `defer` with the same type as a result in the - // return signature? - - // TODO: Move to checkDeferFunc() - // Should we make this an ast.Visitor to store some state for `return` checking? - ast.Inspect( + checkFunctionBody( + pass, funcDecl.Body, - func(node ast.Node) bool { - // fmt.Printf("node: %#v\n", node) - deferStmt, ok := node.(*ast.DeferStmt) - if !ok { - return true - } - - fmt.Printf("defer: %#v\n", deferStmt) - - // TODO: Find out if defer uses assigns an error variable without declaring it - - funcLit, ok := deferStmt.Call.Fun.(*ast.FuncLit) - if !ok { - return true - } - - // TODO: funcall - checkErrorAssignedInDefer(pass, funcLit, errorReturnField, fState) - - return true - }, + errorReturnField, + fState, ) - fmt.Printf("fState: %#v\n", fState) - // Stop if the `defer` closure does not assign to an error // variable. if !fState.deferAssignsError() { @@ -146,6 +119,34 @@ func checkFunctions(pass *analysis.Pass, node ast.Node) { ) } +// TODO: doc +func checkFunctionBody( + pass *analysis.Pass, + funcBody *ast.BlockStmt, + errorReturnField *ast.Field, + fState *functionState, +) { + ast.Inspect( + funcBody, + func(node ast.Node) bool { + deferStmt, ok := node.(*ast.DeferStmt) + if !ok { + return true + } + + // Get a function closure run by `defer`. + funcLit, ok := deferStmt.Call.Fun.(*ast.FuncLit) + if !ok { + return true + } + + checkErrorAssignedInDefer(pass, funcLit, errorReturnField, fState) + + return true + }, + ) +} + // TODO: doc func checkFunctionReturns( pass *analysis.Pass, -- cgit v1.2.3