aboutsummaryrefslogtreecommitdiffstats
path: root/defererr.go
diff options
context:
space:
mode:
Diffstat (limited to 'defererr.go')
-rw-r--r--defererr.go214
1 files changed, 112 insertions, 102 deletions
diff --git a/defererr.go b/defererr.go
index a4e6c8d..f7e1e49 100644
--- a/defererr.go
+++ b/defererr.go
@@ -82,108 +82,8 @@ func run(pass *analysis.Pass) (interface{}, error) {
return true
}
- ast.Inspect(
- funcLit.Body,
- func(node ast.Node) bool {
- assignStmt, ok := node.(*ast.AssignStmt)
- if !ok {
- return true
- }
-
- if assignStmt.Tok == token.DEFINE {
- return true
- }
-
- fmt.Printf("assignStmt: %#v\n", assignStmt)
-
- // TODO: Get type of Lhs, check if "error"
- // If "error", then ensure error return is declared in signature
-
- deferAssignsError := false
- for _, variable := range assignStmt.Lhs {
- ident, ok := variable.(*ast.Ident)
- if !ok {
- continue
- }
-
- obj := pass.TypesInfo.Defs[ident]
-
- valueSpec, ok := ident.Obj.Decl.(*ast.ValueSpec)
- if !ok {
- continue
- }
-
- fmt.Printf("variable: %#v\n", ident)
- fmt.Printf("variable.obj: %#v\n", ident.Obj)
- fmt.Printf("variable.obj.type: %#v\n", ident.Obj.Type)
- fmt.Printf("variable.obj.valuespec: %#v\n", valueSpec)
- fmt.Printf("variable.obj.valuespec.type: %#v\n", valueSpec.Type)
- fmt.Printf("obj: %#v\n", obj)
-
- t := pass.TypesInfo.Types[variable]
- fmt.Printf("type: %#v\n", t)
- fmt.Printf("type.type: %#v\n", t.Type)
-
- named, ok := t.Type.(*types.Named)
- if !ok {
- continue
- }
-
- fmt.Printf("type.type.obj: %#v\n", named.Obj())
- fmt.Printf("type.type.obj: %#v\n", named.Obj().Name())
-
- if named.Obj().Name() == "error" {
- deferAssignsError = true
-
- isErrorNameInReturnSignature := false
-
- for _, errorReturnIdent := range errorReturnField.Names {
- if ident.Name == errorReturnIdent.Name {
- // Report if no matches
- isErrorNameInReturnSignature = true
- }
- }
-
- // 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 {
- pass.Reportf(
- errorReturnField.Pos(),
- "return signature should be '(err error)'", // TODO: Use name from ident.Name
- // errorReturnField,
- )
-
- break
- }
- }
- }
-
- if !deferAssignsError {
- return true
- }
-
- // TODO: Check that funcDecl declares error in signature (check before ast.Inspect on function body, report here)
-
- // isErrorNameInReturnSignature := false
- //
- // for _, errorReturnIdent := range errorReturnField.Names {
- // if ident.Name == errorReturnIdent.Name {
- // // Report if no matches
- // isErrorNameInReturnSignature = true
- // }
- // }
- //
- // if !isErrorNameInReturnSignature {
- // pass.Reportf(
- // errorReturnField.Pos(),
- // "return signature should be '(err error)' (TODO)",
- // errorReturnField,
- // )
- // }
-
- return true
- },
- )
+ // TODO: funcall
+ checkErrorAssignedInDefer(pass, funcLit, errorReturnField)
return true
},
@@ -221,3 +121,113 @@ func run(pass *analysis.Pass) (interface{}, error) {
return nil, nil
}
+
+// TODO: doc
+func checkErrorAssignedInDefer(
+ pass *analysis.Pass,
+ deferFuncLit *ast.FuncLit,
+ errorReturnField *ast.Field,
+) {
+ ast.Inspect(
+ deferFuncLit.Body,
+ func(node ast.Node) bool {
+ assignStmt, ok := node.(*ast.AssignStmt)
+ if !ok {
+ return true
+ }
+
+ if assignStmt.Tok == token.DEFINE {
+ return true
+ }
+
+ fmt.Printf("assignStmt: %#v\n", assignStmt)
+
+ // TODO: Get type of Lhs, check if "error"
+ // If "error", then ensure error return is declared in signature
+
+ deferAssignsError := false
+ for _, variable := range assignStmt.Lhs {
+ ident, ok := variable.(*ast.Ident)
+ if !ok {
+ continue
+ }
+
+ obj := pass.TypesInfo.Defs[ident]
+
+ valueSpec, ok := ident.Obj.Decl.(*ast.ValueSpec)
+ if !ok {
+ continue
+ }
+
+ fmt.Printf("variable: %#v\n", ident)
+ fmt.Printf("variable.obj: %#v\n", ident.Obj)
+ fmt.Printf("variable.obj.type: %#v\n", ident.Obj.Type)
+ fmt.Printf("variable.obj.valuespec: %#v\n", valueSpec)
+ fmt.Printf("variable.obj.valuespec.type: %#v\n", valueSpec.Type)
+ fmt.Printf("obj: %#v\n", obj)
+
+ t := pass.TypesInfo.Types[variable]
+ fmt.Printf("type: %#v\n", t)
+ fmt.Printf("type.type: %#v\n", t.Type)
+
+ named, ok := t.Type.(*types.Named)
+ if !ok {
+ continue
+ }
+
+ fmt.Printf("type.type.obj: %#v\n", named.Obj())
+ fmt.Printf("type.type.obj: %#v\n", named.Obj().Name())
+
+ if named.Obj().Name() == "error" {
+ deferAssignsError = true
+
+ isErrorNameInReturnSignature := false
+
+ for _, errorReturnIdent := range errorReturnField.Names {
+ if ident.Name == errorReturnIdent.Name {
+ // Report if no matches
+ isErrorNameInReturnSignature = true
+ }
+ }
+
+ // 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 {
+ pass.Reportf(
+ errorReturnField.Pos(),
+ "return signature should be '(err error)'", // TODO: Use name from ident.Name
+ // errorReturnField,
+ )
+
+ break
+ }
+ }
+ }
+
+ if !deferAssignsError {
+ return true
+ }
+
+ // TODO: Check that funcDecl declares error in signature (check before ast.Inspect on function body, report here)
+
+ // isErrorNameInReturnSignature := false
+ //
+ // for _, errorReturnIdent := range errorReturnField.Names {
+ // if ident.Name == errorReturnIdent.Name {
+ // // Report if no matches
+ // isErrorNameInReturnSignature = true
+ // }
+ // }
+ //
+ // if !isErrorNameInReturnSignature {
+ // pass.Reportf(
+ // errorReturnField.Pos(),
+ // "return signature should be '(err error)' (TODO)",
+ // errorReturnField,
+ // )
+ // }
+
+ return true
+ },
+ )
+}