From cd02ebfb98de7c6cb7a48c1a802233c727c8e8a0 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sun, 21 May 2023 14:26:03 +0200 Subject: 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. --- defererr.go | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'defererr.go') 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 { -- cgit v1.2.3