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.*/ +}