go/packages/packagestest: allow expectations to have *regexp.Regexp and interface{} parameters

Change-Id: I86312ae2f30ba04290e9b7a001e0284439f4bfe6
Reviewed-on: https://go-review.googlesource.com/c/151346
Run-TryBot: Ian Cottrell <iancottrell@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/go/packages/packagestest/expect.go b/go/packages/packagestest/expect.go
index 3566388..14e1fc0 100644
--- a/go/packages/packagestest/expect.go
+++ b/go/packages/packagestest/expect.go
@@ -48,8 +48,10 @@
 //   expect.Comment : passed the Comment instance being evaluated.
 //   string : can be supplied either a string literal or an identifier.
 //   int : can only be supplied an integer literal.
+//   *regexp.Regexp : can only be supplied a regular expression literal
 //   token.Pos : has a file position calculated as described below.
 //   token.Position : has a file position calculated as described below.
+//   interface{} : will be passed any value
 //
 // Position calculation
 //
@@ -173,6 +175,7 @@
 	positionType   = reflect.TypeOf(token.Position{})
 	rangeType      = reflect.TypeOf(Range{})
 	fsetType       = reflect.TypeOf((*token.FileSet)(nil))
+	regexType      = reflect.TypeOf((*regexp.Regexp)(nil))
 )
 
 // converter converts from a marker's argument parsed from the comment to
@@ -238,6 +241,17 @@
 				return reflect.Value{}, nil, fmt.Errorf("cannot convert %v to string", arg)
 			}
 		}, nil
+
+	case pt == regexType:
+		return func(n *expect.Note, args []interface{}) (reflect.Value, []interface{}, error) {
+			arg := args[0]
+			args = args[1:]
+			if _, ok := arg.(*regexp.Regexp); !ok {
+				return reflect.Value{}, nil, fmt.Errorf("cannot convert %v to *regexp.Regexp", arg)
+			}
+			return reflect.ValueOf(arg), args, nil
+		}, nil
+
 	case pt.Kind() == reflect.String:
 		return func(n *expect.Note, args []interface{}) (reflect.Value, []interface{}, error) {
 			arg := args[0]
@@ -290,7 +304,12 @@
 			return result, args, nil
 		}, nil
 	default:
-		return nil, fmt.Errorf("param has invalid type %v", pt)
+		if pt.Kind() == reflect.Interface && pt.NumMethod() == 0 {
+			return func(n *expect.Note, args []interface{}) (reflect.Value, []interface{}, error) {
+				return reflect.ValueOf(args[0]), args[1:], nil
+			}, nil
+		}
+		return nil, fmt.Errorf("param has unexpected type %v (kind %v)", pt, pt.Kind())
 	}
 }