diff options
author | Teddy Wing | 2023-05-18 21:31:58 +0200 |
---|---|---|
committer | Teddy Wing | 2023-05-18 21:31:58 +0200 |
commit | 5fd2ef0221f0737127f524554a872e118b178416 (patch) | |
tree | f7ed26650c98c83f93846177f8da22093bde7144 /defererr.go | |
parent | b8fde7555016618d1a9a4625c24af537e09de103 (diff) | |
download | godefererr-5fd2ef0221f0737127f524554a872e118b178416.tar.bz2 |
Ideas for an analyser for returning errors from defer
Still working out how to traverse the AST to be able to see the objects
I need.
Diffstat (limited to 'defererr.go')
-rw-r--r-- | defererr.go | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/defererr.go b/defererr.go new file mode 100644 index 0000000..d512cbf --- /dev/null +++ b/defererr.go @@ -0,0 +1,61 @@ +// TODO: doc +package defererr + +import ( + "fmt" + "go/ast" + + "golang.org/x/tools/go/analysis" +) + +var Analyzer = &analysis.Analyzer{ + Name: "defererr", + Doc: "reports issues returning errors from defer", + Run: run, +} + +func run(pass *analysis.Pass) (interface{}, error) { + // TODO: Find defer closure + // Does it set error defined in outer scope? + // Does outer scope declare error variable in signature? + // Is err variable returned after closure? + + for _, file := range pass.Files { + ast.Inspect( + file, + func(node ast.Node) bool { + deferStmt, ok := node.(*ast.DeferStmt) + if !ok { + 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 + }, + ) + } + + return nil, nil +} |