From 046e10da6483d05a0b16bea75baf8effa57a056d Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Thu, 18 May 2023 22:21:21 +0200 Subject: Ideas for walking functions first instead of `defer`s first I was having a hard time figuring out how to get the function where a `defer` occurs from the defer, so I decided to look at all functions first instead, and find out if they contain `defer`s. --- defererr.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 13 deletions(-) (limited to 'defererr.go') diff --git a/defererr.go b/defererr.go index d512cbf..fafb42e 100644 --- a/defererr.go +++ b/defererr.go @@ -24,33 +24,76 @@ func run(pass *analysis.Pass) (interface{}, error) { ast.Inspect( file, func(node ast.Node) bool { - deferStmt, ok := node.(*ast.DeferStmt) + funcType, ok := node.(*ast.FuncType) if !ok { return true } - // Look for a function literal after the `defer` statement. - funcLit, ok := deferStmt.Call.Fun.(*ast.FuncLit) - if !ok { + if funcType.Results == nil { return true } - funcScope := pass.TypesInfo.Scopes[funcLit.Type] + funcReturnsError := false + for _, returnVal := range funcType.Results.List { + fmt.Printf("returnVal: %#v\n", returnVal.Type) - // Try to find the function where the defer is defined. Note, defer can be defined in an inner block. - funcType, ok := funcScope.Parent().(*ast.FuncType) - if !ok { + returnIdent, ok := returnVal.Type.(*ast.Ident) + if !ok { return true + } + + if returnIdent.Name == "error" { + funcReturnsError = true + } } - fmt.Printf("func: %#v\n", funcType) - if funcLit.Type.Results == nil { + // Can we do the same for non-error types? + // for _, returnVal := range funcType.Results.List { + // } + + if !funcReturnsError { return true } - for _, returnVal := range funcLit.Type.Results.List { - fmt.Printf("returnVal: %#v\n", returnVal) - } + ast.Inspect( + funcType, + 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 + + return true + }, + ) + + // // Look for a function literal after the `defer` statement. + // funcLit, ok := deferStmt.Call.Fun.(*ast.FuncLit) + // if !ok { + // return true + // } + // + // funcScope := pass.TypesInfo.Scopes[funcLit.Type] + // + // // Try to find the function where the defer is defined. Note, defer can be defined in an inner block. + // funcType, ok := funcScope.Parent().(*ast.FuncType) + // if !ok { + // return true + // } + // fmt.Printf("func: %#v\n", funcType) + // + // if funcLit.Type.Results == nil { + // return true + // } + // + // for _, returnVal := range funcLit.Type.Results.List { + // fmt.Printf("returnVal: %#v\n", returnVal) + // } return true }, -- cgit v1.2.3