Add check for argument position of context variable.
diff --git a/lint.go b/lint.go
index 8dc4ae5..59fea7c 100644
--- a/lint.go
+++ b/lint.go
@@ -187,6 +187,7 @@
f.lintUnexportedReturn()
f.lintTimeNames()
f.lintContextKeyTypes()
+ f.lintContextArgs()
}
type link string
@@ -1436,6 +1437,27 @@
}
}
+// lintContextArgs examines function declarations that contain an
+// argument with a type of context.Context
+// It complains if that argument isn't the first parameter.
+func (f *file) lintContextArgs() {
+ f.walk(func(n ast.Node) bool {
+ fn, ok := n.(*ast.FuncDecl)
+ if !ok || len(fn.Type.Params.List) <= 1 {
+ return true
+ }
+ // A context.Context should be the first parameter of a function.
+ // Flag any that show up after the first.
+ for _, arg := range fn.Type.Params.List[1:] {
+ if isPkgDot(arg.Type, "context", "Context") {
+ f.errorf(fn, 0.9, link("https://golang.org/pkg/context/"), category("arg-order"), "context.Context should be the first parameter of a function")
+ break // only flag one
+ }
+ }
+ return true
+ })
+}
+
// receiverType returns the named type of the method receiver, sans "*",
// or "invalid-type" if fn.Recv is ill formed.
func receiverType(fn *ast.FuncDecl) string {
diff --git a/testdata/context.go b/testdata/context.go
new file mode 100644
index 0000000..501c69b
--- /dev/null
+++ b/testdata/context.go
@@ -0,0 +1,24 @@
+// Test that context.Context is the first arg to a function.
+
+// Package foo ...
+package foo
+
+import (
+ "context"
+)
+
+// A proper context.Context location
+func x(ctx context.Context) { // ok
+}
+
+// A proper context.Context location
+func x(ctx context.Context, s string) { // ok
+}
+
+// An invalid context.Context location
+func y(s string, ctx context.Context) { // MATCH /context.Context should be the first parameter.*/
+}
+
+// An invalid context.Context location with more than 2 args
+func y(s string, r int, ctx context.Context, x int) { // MATCH /context.Context should be the first parameter.*/
+}