Add a lint check for functions which return errors but the error type isn't the last type in the return list.
Signed-off-by: David Symonds <dsymonds@golang.org>
diff --git a/lint.go b/lint.go
index eb27062..77188e0 100644
--- a/lint.go
+++ b/lint.go
@@ -88,6 +88,7 @@
f.lintReceiverNames()
f.lintIncDec()
f.lintMake()
+ f.lintErrorReturn()
return f.problems
}
@@ -937,6 +938,30 @@
})
}
+// lintErrorReturn examines function declarations that return an error.
+// It complains if the error isn't the last parameter.
+func (f *file) lintErrorReturn() {
+ f.walk(func(n ast.Node) bool {
+ fn, ok := n.(*ast.FuncDecl)
+ if !ok || fn.Type.Results == nil {
+ return true
+ }
+ ret := fn.Type.Results.List
+ if len(ret) <= 1 {
+ return true
+ }
+ // An error return parameter should be the last parameter.
+ // Flag any error parameters found before the last.
+ for _, r := range ret[:len(ret)-1] {
+ if isIdent(r.Type, "error") {
+ f.errorf(fn, 0.9, "", "error should be the last type when returning multiple items")
+ break // only flag one
+ }
+ }
+ return true
+ })
+}
+
func receiverType(fn *ast.FuncDecl) string {
switch e := fn.Recv.List[0].Type.(type) {
case *ast.Ident:
diff --git a/testdata/error-return.go b/testdata/error-return.go
new file mode 100644
index 0000000..bc8bf00
--- /dev/null
+++ b/testdata/error-return.go
@@ -0,0 +1,43 @@
+// Test for returning errors.
+
+// Package foo ...
+package foo
+
+// Returns nothing
+func f() { // ok
+}
+
+// Check for a single error return
+func g() error { // ok
+ return nil
+}
+
+// Check for a single other return type
+func h() int { // ok
+ return 0
+}
+
+// Check for multiple return but error at end.
+func i() (int, error) { // ok
+ return 0, nil
+}
+
+// Check for multiple return but error at end with named variables.
+func i() (x int, err error) { // ok
+ return 0, nil
+}
+
+// Check for error in the wrong location on 2 types
+func j() (error, int) { // MATCH /error should be the last type/
+ return nil, 0
+}
+
+// Check for error in the wrong location for > 2 types
+func k() (int, error, int) { // MATCH /error should be the last type/
+ return 0, nil, 0
+}
+
+// Check for error in the wrong location with named variables.
+func l() (x int, err error, y int) { // MATCH /error should be the last type/
+ return 0, nil, 0
+}