aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeddy Wing2023-05-21 14:26:03 +0200
committerTeddy Wing2023-05-21 14:26:03 +0200
commitcd02ebfb98de7c6cb7a48c1a802233c727c8e8a0 (patch)
tree702e3c931669ecb3ad985dfd7da440a111ed0744
parent2fba3d707aee35914734808c3db2ac3b0cb74c95 (diff)
downloadgodefererr-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.go29
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 {