diff options
author | Teddy Wing | 2023-05-21 14:26:03 +0200 |
---|---|---|
committer | Teddy Wing | 2023-05-21 14:26:03 +0200 |
commit | cd02ebfb98de7c6cb7a48c1a802233c727c8e8a0 (patch) | |
tree | 702e3c931669ecb3ad985dfd7da440a111ed0744 | |
parent | 2fba3d707aee35914734808c3db2ac3b0cb74c95 (diff) | |
download | godefererr-cd02ebfb98de7c6cb7a48c1a802233c727c8e8a0.tar.bz2 |
Try to store the end position of the first defer closure with error
The idea is to store the end position of the first defer closure that
assigns an error variable from the outer scope. Then, we can check the
`return` statements in the rest of the function after that position to
ensure they use the error variable.
-rw-r--r-- | defererr.go | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/defererr.go b/defererr.go index e25ede7..3e54aba 100644 --- a/defererr.go +++ b/defererr.go @@ -29,6 +29,24 @@ func run(pass *analysis.Pass) (interface{}, error) { return nil, nil } +type functionState struct { + firstErrorDeferEndPos token.Pos +} + +func newFunctionState() *functionState { + return &functionState{ + firstErrorDeferEndPos: -1, + } +} + +func (s *functionState) setFirstErrorDeferEndPos(pos token.Pos) { + if s.firstErrorDeferEndPos != -1 { + return + } + + s.firstErrorDeferEndPos = pos +} + func checkFunctions(pass *analysis.Pass, node ast.Node) { ast.Inspect( node, @@ -74,7 +92,9 @@ func checkFunctions(pass *analysis.Pass, node ast.Node) { // Idea: Set this to the end token.Pos of the first `defer` // closure. Look for `return`s after that in funcDecl.Body and // ensure they include the error variable. - firstErrorDeferEndPos := -1 + // firstErrorDeferEndPos := -1 + + 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 @@ -101,12 +121,14 @@ func checkFunctions(pass *analysis.Pass, node ast.Node) { } // TODO: funcall - checkErrorAssignedInDefer(pass, funcLit, errorReturnField) + checkErrorAssignedInDefer(pass, funcLit, errorReturnField, fState) return true }, ) + fmt.Printf("fState: %#v\n", fState) + // // Look for a function literal after the `defer` statement. // funcLit, ok := deferStmt.Call.Fun.(*ast.FuncLit) // if !ok { @@ -142,6 +164,7 @@ func checkErrorAssignedInDefer( pass *analysis.Pass, deferFuncLit *ast.FuncLit, errorReturnField *ast.Field, + fState *functionState, ) { ast.Inspect( deferFuncLit.Body, @@ -211,6 +234,8 @@ func checkErrorAssignedInDefer( } } + fState.setFirstErrorDeferEndPos(deferFuncLit.Body.Rbrace) + // Maybe don't report the error if it was declared in the closure using a GenDecl? -> We already don't. Should test for these things. if !isErrorNameInReturnSignature { |