Repository: golang/mock
Pull request #362 (2019-12-20 10:08:28)

Add Mockgen Version Flag
Add -version flag that shows a version provided by Go modules.

This strategy works well for module aware invocations of `go get` and `go
run` (which means using GO111MODULE=on).

If we ever plan to distribute built binaries, it is necessary to amend
the strategy with build flags.

GOPATH mode versioning is unsupported.


Patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..0adcf53
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,28 @@
+---
+name: Bug report
+about: Report a bug in gomock
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Actual behavior** A clear and concise description of what the bug is.
+
+**Expected behavior** A clear and concise description of what you expected to
+happen.
+
+**To Reproduce** Steps to reproduce the behavior
+
+1.  ...
+2.  ...
+
+**Additional Information**
+
+-   gomock mode (reflect or source):
+-   gomock version or git ref:
+-   golang version:
+
+**Triage Notes for the Maintainers**
+
+<!-- 🎉🎉🎉 Thank you for an opening an issue !!! 🎉🎉🎉 We are doing our best to get to this. -->
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..fa61e43
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: true
+#contact_links:
+#  - name: GitHub Community Forum
+#    url: https://github.community/
+#    about: Please ask and answer questions here.
+#  - name: GitHub Security Bug Bounty
+#    url: https://bounty.github.com/
+#    about: Please report security vulnerabilities here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..5e4f441
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,17 @@
+---
+name: Feature request
+about: Propose a new feature for gomock
+title: ''
+labels: 'type: feature request'
+assignees: ''
+
+---
+
+*Requested feature* A clear description of the desired feature and an example of
+how it would be used.
+
+*Why the feature is needed* A clear description of how this feature is not
+served by existing functionality in gomock.
+
+*(Optional) Proposed solution* A clear description of a proposed method for
+adding this feature to gomock.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..d4bd263
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,31 @@
+<!-- 🎉🎉🎉 Thank you for the PR!!! 🎉🎉🎉 -->
+
+
+Fixes #<issue number>. _in case of a bug fix, this should point to a bug and any other related issue(s)_
+
+**Description**
+
+<!-- Describe your changes here- ideally you can get that description straight from
+your descriptive commit message(s)! -->
+
+**Submitter Checklist**
+
+These are the criteria that every PR should meet, please check them off as you
+review them:
+
+- [ ] Includes tests
+
+**Reviewer Notes**
+
+- [ ] The code flow looks good.
+- [ ] Tests added.
+
+
+**Release Notes**
+
+Describe any changes here so maintainer can include it in the release notes, or delete this block.
+
+```
+Examples of user facing changes:
+- Improved API for custom matchers
+```
diff --git a/.gitignore b/.gitignore
index b62f268..e1919a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ mockgen/mockgen
 
 # Editors
 .vscode
+.idea
diff --git a/.goreleaser.yml b/.goreleaser.yml
index e3cdc39..edf9277 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -37,6 +37,6 @@ changelog:
   sort: asc
   filters:
     exclude:
-    - '^docs:'
-    - '^test:'
-    - 'README'
+      - '^docs:'
+      - '^test:'
+      - 'README'
diff --git a/README.md b/README.md
index 3fd60db..950694e 100644
--- a/README.md
+++ b/README.md
@@ -8,14 +8,17 @@ contexts too.
 Installation
 ------------
 
-Once you have [installed Go][golang-install], install the `mockgen` tool:
+Once you have [installed Go][golang-install], install the `mockgen` tool.
+
+To get the latest released version use:
 
 ```bash
-go get github.com/golang/mock/mockgen
+GO111MODULE=on go get github.com/golang/mock/mockgen@latest
 ```
 
-_Note: It is recommended to have `GO111MODULE=on` to ensure the correct
-dependencies are used._
+If you use `mockgen` in your CI pipeline, it may be more appropriate to fixate
+on a specific mockgen version.
+
 
 Documentation
 -------------
@@ -87,6 +90,12 @@ It supports the following flags:
     mock name (mock factory method and mock recorder will be named after the mock).
     If one of the interfaces has no custom name specified, then default naming
     convention will be used.
+    
+* `-self_package`: The full package import path for the generated code. The purpose 
+    of this flag is to prevent import cycles in the generated code by trying to include 
+    its own package. This can happen if the mock's package is set to one of its 
+    inputs (usually the main one) and the output is stdio so mockgen cannot detect the 
+    final output package. Setting this flag will then tell mockgen which import to exclude.
 
 * `-copyright_file`: Copyright file used to add copyright header to the resulting source code.
 
diff --git a/ci/check_go_generate.sh b/ci/check_go_generate.sh
index a0212e2..d906bd5 100755
--- a/ci/check_go_generate.sh
+++ b/ci/check_go_generate.sh
@@ -9,6 +9,7 @@
 
 set -euo pipefail
 
+BASE_DIR="$PWD"
 TEMP_DIR=$( mktemp -d )
 function cleanup() {
     rm -rf "${TEMP_DIR}"
@@ -16,8 +17,9 @@ function cleanup() {
 trap cleanup EXIT
 
 cp -r . "${TEMP_DIR}/"
+cd $TEMP_DIR
 go generate ./...
-if ! diff -r . "${TEMP_DIR}"; then
+if ! diff -r . "${BASE_DIR}"; then
     echo
     echo "The generated files aren't up to date."
     echo "Update them with the 'go generate ./...' command."
diff --git a/gomock/call.go b/gomock/call.go
index 7bdeab9..7345f65 100644
--- a/gomock/call.go
+++ b/gomock/call.go
@@ -295,7 +295,7 @@ func (c *Call) String() string {
 func (c *Call) matches(args []interface{}) error {
 	if !c.methodType.IsVariadic() {
 		if len(args) != len(c.args) {
-			return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
+			return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: %d",
 				c.origin, len(args), len(c.args))
 		}
 
@@ -307,22 +307,22 @@ func (c *Call) matches(args []interface{}) error {
 				}
 
 				return fmt.Errorf(
-					"Expected call at %s doesn't match the argument at index %d.\nGot: %v\nWant: %v",
+					"expected call at %s doesn't match the argument at index %d.\nGot: %v\nWant: %v",
 					c.origin, i, got, m,
 				)
 			}
 		}
 	} else {
 		if len(c.args) < c.methodType.NumIn()-1 {
-			return fmt.Errorf("Expected call at %s has the wrong number of matchers. Got: %d, want: %d",
+			return fmt.Errorf("expected call at %s has the wrong number of matchers. Got: %d, want: %d",
 				c.origin, len(c.args), c.methodType.NumIn()-1)
 		}
 		if len(c.args) != c.methodType.NumIn() && len(args) != len(c.args) {
-			return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: %d",
+			return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: %d",
 				c.origin, len(args), len(c.args))
 		}
 		if len(args) < len(c.args)-1 {
-			return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d",
+			return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d",
 				c.origin, len(args), len(c.args)-1)
 		}
 
@@ -330,7 +330,7 @@ func (c *Call) matches(args []interface{}) error {
 			if i < c.methodType.NumIn()-1 {
 				// Non-variadic args
 				if !m.Matches(args[i]) {
-					return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
+					return fmt.Errorf("expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
 						c.origin, strconv.Itoa(i), args[i], m)
 				}
 				continue
@@ -403,7 +403,7 @@ func (c *Call) dropPrereqs() (preReqs []*Call) {
 	return
 }
 
-func (c *Call) call(args []interface{}) []func([]interface{}) []interface{} {
+func (c *Call) call() []func([]interface{}) []interface{} {
 	c.numCalls++
 	return c.actions
 }
diff --git a/gomock/callset.go b/gomock/callset.go
index c44a8a5..b046b52 100644
--- a/gomock/callset.go
+++ b/gomock/callset.go
@@ -72,7 +72,7 @@ func (cs callSet) FindMatch(receiver interface{}, method string, args []interfac
 	for _, call := range expected {
 		err := call.matches(args)
 		if err != nil {
-			fmt.Fprintf(&callsErrors, "\n%v", err)
+			_, _ = fmt.Fprintf(&callsErrors, "\n%v", err)
 		} else {
 			return call, nil
 		}
@@ -83,12 +83,12 @@ func (cs callSet) FindMatch(receiver interface{}, method string, args []interfac
 	exhausted := cs.exhausted[key]
 	for _, call := range exhausted {
 		if err := call.matches(args); err != nil {
-			fmt.Fprintf(&callsErrors, "\n%v", err)
+			_, _ = fmt.Fprintf(&callsErrors, "\n%v", err)
 		}
 	}
 
 	if len(expected)+len(exhausted) == 0 {
-		fmt.Fprintf(&callsErrors, "there are no expected calls of the method %q for that receiver", method)
+		_, _ = fmt.Fprintf(&callsErrors, "there are no expected calls of the method %q for that receiver", method)
 	}
 
 	return nil, fmt.Errorf(callsErrors.String())
diff --git a/gomock/controller.go b/gomock/controller.go
index 75f2350..d7c3c65 100644
--- a/gomock/controller.go
+++ b/gomock/controller.go
@@ -209,7 +209,7 @@ func (ctrl *Controller) Call(receiver interface{}, method string, args ...interf
 			ctrl.expectedCalls.Remove(preReqCall)
 		}
 
-		actions := expected.call(args)
+		actions := expected.call()
 		if expected.exhausted() {
 			ctrl.expectedCalls.Remove(expected)
 		}
diff --git a/gomock/matchers.go b/gomock/matchers.go
index 378c404..7bfc07b 100644
--- a/gomock/matchers.go
+++ b/gomock/matchers.go
@@ -17,6 +17,7 @@ package gomock
 import (
 	"fmt"
 	"reflect"
+	"strings"
 )
 
 // A Matcher is a representation of a class of values.
@@ -88,7 +89,7 @@ func GotFormatterAdapter(s GotFormatter, m Matcher) Matcher {
 
 type anyMatcher struct{}
 
-func (anyMatcher) Matches(x interface{}) bool {
+func (anyMatcher) Matches(interface{}) bool {
 	return true
 }
 
@@ -154,8 +155,51 @@ func (m assignableToTypeOfMatcher) String() string {
 	return "is assignable to " + m.targetType.Name()
 }
 
+type allMatcher struct {
+	matchers []Matcher
+}
+
+func (am allMatcher) Matches(x interface{}) bool {
+	for _, m := range am.matchers {
+		if !m.Matches(x) {
+			return false
+		}
+	}
+	return true
+}
+
+func (am allMatcher) String() string {
+	ss := make([]string, 0, len(am.matchers))
+	for _, matcher := range am.matchers {
+		ss = append(ss, matcher.String())
+	}
+	return strings.Join(ss, "; ")
+}
+
+type lenMatcher struct {
+	i int
+}
+
+func (m lenMatcher) Matches(x interface{}) bool {
+	v := reflect.ValueOf(x)
+	switch v.Kind() {
+	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
+		return v.Len() == m.i
+	default:
+		return false
+	}
+}
+
+func (m lenMatcher) String() string {
+	return fmt.Sprintf("has length %d", m.i)
+}
+
 // Constructors
 
+// All returns a composite Matcher that returns true if and only all of the
+// matchers return true.
+func All(ms ...Matcher) Matcher { return allMatcher{ms} }
+
 // Any returns a matcher that always matches.
 func Any() Matcher { return anyMatcher{} }
 
@@ -166,6 +210,12 @@ func Any() Matcher { return anyMatcher{} }
 //   Eq(5).Matches(4) // returns false
 func Eq(x interface{}) Matcher { return eqMatcher{x} }
 
+// Len returns a matcher that matches on length. This matcher returns false if
+// is compared to a type that is not an array, chan, map, slice, or string.
+func Len(i int) Matcher {
+	return lenMatcher{i}
+}
+
 // Nil returns a matcher that matches if the received value is nil.
 //
 // Example usage:
@@ -194,6 +244,12 @@ func Not(x interface{}) Matcher {
 //   var s fmt.Stringer = &bytes.Buffer{}
 //   AssignableToTypeOf(s).Matches(time.Second) // returns true
 //   AssignableToTypeOf(s).Matches(99) // returns false
+//
+//   var ctx = reflect.TypeOf((*context.Context)).Elem()
+//   AssignableToTypeOf(ctx).Matches(context.Background()) // returns true
 func AssignableToTypeOf(x interface{}) Matcher {
+	if xt, ok := x.(reflect.Type); ok {
+		return assignableToTypeOfMatcher{xt}
+	}
 	return assignableToTypeOfMatcher{reflect.TypeOf(x)}
 }
diff --git a/mockgen/mockgen.go b/mockgen/mockgen.go
index a0d483f..b02aaf4 100644
--- a/mockgen/mockgen.go
+++ b/mockgen/mockgen.go
@@ -53,22 +53,28 @@ var (
 	copyrightFile   = flag.String("copyright_file", "", "Copyright file used to add copyright header")
 
 	debugParser = flag.Bool("debug_parser", false, "Print out parser results only.")
+	version     = flag.Bool("version", false, "Print version.")
 )
 
 func main() {
 	flag.Usage = usage
 	flag.Parse()
 
+	if *version {
+		printVersion()
+		return
+	}
+
 	var pkg *model.Package
 	var err error
 	if *source != "" {
-		pkg, err = parseFile(*source)
+		pkg, err = sourceMode(*source)
 	} else {
 		if flag.NArg() != 2 {
 			usage()
 			log.Fatal("Expected exactly two arguments")
 		}
-		pkg, err = reflect(flag.Arg(0), strings.Split(flag.Arg(1), ","))
+		pkg, err = reflectMode(flag.Arg(0), strings.Split(flag.Arg(1), ","))
 	}
 	if err != nil {
 		log.Fatalf("Loading input failed: %v", err)
@@ -92,11 +98,11 @@ func main() {
 		dst = f
 	}
 
-	packageName := *packageOut
-	if packageName == "" {
+	outputPackageName := *packageOut
+	if outputPackageName == "" {
 		// pkg.Name in reflect mode is the base name of the import path,
 		// which might have characters that are illegal to have in package names.
-		packageName = "mock_" + sanitize(pkg.Name)
+		outputPackageName = "mock_" + sanitize(pkg.Name)
 	}
 
 	// outputPackagePath represents the fully qualified name of the package of
@@ -137,7 +143,7 @@ func main() {
 
 		g.copyrightHeader = string(header)
 	}
-	if err := g.Generate(pkg, packageName, outputPackagePath); err != nil {
+	if err := g.Generate(pkg, outputPackageName, outputPackagePath); err != nil {
 		log.Fatalf("Failed generating mock: %v", err)
 	}
 	if _, err := dst.Write(g.Output()); err != nil {
@@ -158,7 +164,7 @@ func parseMockNames(names string) map[string]string {
 }
 
 func usage() {
-	io.WriteString(os.Stderr, usageText)
+	_, _ = io.WriteString(os.Stderr, usageText)
 	flag.PrintDefaults()
 }
 
@@ -234,8 +240,9 @@ func sanitize(s string) string {
 	return t
 }
 
-func (g *generator) Generate(pkg *model.Package, pkgName string, outputPackagePath string) error {
-	if pkgName != pkg.Name {
+func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPackagePath string) error {
+	if outputPkgName != pkg.Name && *selfPackage == "" {
+		// reset outputPackagePath if it's not passed in through -self_package
 		outputPackagePath = ""
 	}
 
@@ -294,25 +301,30 @@ func (g *generator) Generate(pkg *model.Package, pkgName string, outputPackagePa
 			i++
 		}
 
+		// Avoid importing package if source pkg == output pkg
+		if pth == pkg.PkgPath && outputPkgName == pkg.Name {
+			continue
+		}
+
 		g.packageMap[pth] = pkgName
 		localNames[pkgName] = true
 	}
 
 	if *writePkgComment {
-		g.p("// Package %v is a generated GoMock package.", pkgName)
+		g.p("// Package %v is a generated GoMock package.", outputPkgName)
 	}
-	g.p("package %v", pkgName)
+	g.p("package %v", outputPkgName)
 	g.p("")
 	g.p("import (")
 	g.in()
-	for path, pkg := range g.packageMap {
-		if path == outputPackagePath {
+	for pkgPath, pkgName := range g.packageMap {
+		if pkgPath == outputPackagePath {
 			continue
 		}
-		g.p("%v %q", pkg, path)
+		g.p("%v %q", pkgName, pkgPath)
 	}
-	for _, path := range pkg.DotImports {
-		g.p(". %q", path)
+	for _, pkgPath := range pkg.DotImports {
+		g.p(". %q", pkgPath)
 	}
 	g.out()
 	g.p(")")
@@ -357,9 +369,9 @@ func (g *generator) GenerateMockInterface(intf *model.Interface, outputPackagePa
 	g.p("")
 
 	// TODO: Re-enable this if we can import the interface reliably.
-	//g.p("// Verify that the mock satisfies the interface at compile time.")
-	//g.p("var _ %v = (*%v)(nil)", typeName, mockType)
-	//g.p("")
+	// g.p("// Verify that the mock satisfies the interface at compile time.")
+	// g.p("var _ %v = (*%v)(nil)", typeName, mockType)
+	// g.p("")
 
 	g.p("// New%v creates a new mock instance", mockType)
 	g.p("func New%v(ctrl *gomock.Controller) *%v {", mockType, mockType)
@@ -387,9 +399,9 @@ func (g *generator) GenerateMockInterface(intf *model.Interface, outputPackagePa
 func (g *generator) GenerateMockMethods(mockType string, intf *model.Interface, pkgOverride string) {
 	for _, m := range intf.Methods {
 		g.p("")
-		g.GenerateMockMethod(mockType, m, pkgOverride)
+		_ = g.GenerateMockMethod(mockType, m, pkgOverride)
 		g.p("")
-		g.GenerateMockRecorderMethod(mockType, m)
+		_ = g.GenerateMockRecorderMethod(mockType, m)
 	}
 }
 
@@ -531,7 +543,7 @@ func (g *generator) getArgNames(m *model.Method) []string {
 	argNames := make([]string, len(m.In))
 	for i, p := range m.In {
 		name := p.Name
-		if name == "" {
+		if name == "" || name == "_" {
 			name = fmt.Sprintf("arg%d", i)
 		}
 		argNames[i] = name
diff --git a/mockgen/model/model.go b/mockgen/model/model.go
index b93e062..88783cf 100644
--- a/mockgen/model/model.go
+++ b/mockgen/model/model.go
@@ -29,13 +29,14 @@ const pkgPath = "github.com/golang/mock/mockgen/model"
 // Package is a Go package. It may be a subset.
 type Package struct {
 	Name       string
+	PkgPath    string
 	Interfaces []*Interface
 	DotImports []string
 }
 
 // Print writes the package name and its exported interfaces.
 func (pkg *Package) Print(w io.Writer) {
-	fmt.Fprintf(w, "package %s\n", pkg.Name)
+	_, _ = fmt.Fprintf(w, "package %s\n", pkg.Name)
 	for _, intf := range pkg.Interfaces {
 		intf.Print(w)
 	}
@@ -58,7 +59,7 @@ type Interface struct {
 
 // Print writes the interface name and its methods.
 func (intf *Interface) Print(w io.Writer) {
-	fmt.Fprintf(w, "interface %s\n", intf.Name)
+	_, _ = fmt.Fprintf(w, "interface %s\n", intf.Name)
 	for _, m := range intf.Methods {
 		m.Print(w)
 	}
@@ -79,19 +80,19 @@ type Method struct {
 
 // Print writes the method name and its signature.
 func (m *Method) Print(w io.Writer) {
-	fmt.Fprintf(w, "  - method %s\n", m.Name)
+	_, _ = fmt.Fprintf(w, "  - method %s\n", m.Name)
 	if len(m.In) > 0 {
-		fmt.Fprintf(w, "    in:\n")
+		_, _ = fmt.Fprintf(w, "    in:\n")
 		for _, p := range m.In {
 			p.Print(w)
 		}
 	}
 	if m.Variadic != nil {
-		fmt.Fprintf(w, "    ...:\n")
+		_, _ = fmt.Fprintf(w, "    ...:\n")
 		m.Variadic.Print(w)
 	}
 	if len(m.Out) > 0 {
-		fmt.Fprintf(w, "    out:\n")
+		_, _ = fmt.Fprintf(w, "    out:\n")
 		for _, p := range m.Out {
 			p.Print(w)
 		}
@@ -122,7 +123,7 @@ func (p *Parameter) Print(w io.Writer) {
 	if n == "" {
 		n = `""`
 	}
-	fmt.Fprintf(w, "    - %v: %v\n", n, p.Type.String(nil, ""))
+	_, _ = fmt.Fprintf(w, "    - %v: %v\n", n, p.Type.String(nil, ""))
 }
 
 // Type is a Go type.
@@ -264,6 +265,7 @@ func (nt *NamedType) String(pm map[string]string, pkgOverride string) string {
 
 	return nt.Type
 }
+
 func (nt *NamedType) addImports(im map[string]bool) {
 	if nt.Package != "" {
 		im[nt.Package] = true
@@ -283,8 +285,8 @@ func (pt *PointerType) addImports(im map[string]bool) { pt.Type.addImports(im) }
 // PredeclaredType is a predeclared type such as "int".
 type PredeclaredType string
 
-func (pt PredeclaredType) String(pm map[string]string, pkgOverride string) string { return string(pt) }
-func (pt PredeclaredType) addImports(im map[string]bool)                          {}
+func (pt PredeclaredType) String(map[string]string, string) string { return string(pt) }
+func (pt PredeclaredType) addImports(map[string]bool)              {}
 
 // The following code is intended to be called by the program generated by ../reflect.go.
 
diff --git a/mockgen/parse.go b/mockgen/parse.go
index 1fe16c5..e35d16f 100644
--- a/mockgen/parse.go
+++ b/mockgen/parse.go
@@ -41,7 +41,8 @@ var (
 
 // TODO: simplify error reporting
 
-func parseFile(source string) (*model.Package, error) {
+// sourceMode generates mocks via source file.
+func sourceMode(source string) (*model.Package, error) {
 	srcDir, err := filepath.Abs(filepath.Dir(source))
 	if err != nil {
 		return nil, fmt.Errorf("failed getting source directory: %v", err)
@@ -101,8 +102,8 @@ func parseFile(source string) (*model.Package, error) {
 	if err != nil {
 		return nil, err
 	}
-	for path := range dotImports {
-		pkg.DotImports = append(pkg.DotImports, path)
+	for pkgPath := range dotImports {
+		pkg.DotImports = append(pkg.DotImports, pkgPath)
 	}
 	return pkg, nil
 }
@@ -161,18 +162,18 @@ func (p *fileParser) addAuxInterfacesFromFile(pkg string, file *ast.File) {
 func (p *fileParser) parseFile(importPath string, file *ast.File) (*model.Package, error) {
 	allImports, dotImports := importsOfFile(file)
 	// Don't stomp imports provided by -imports. Those should take precedence.
-	for pkg, path := range allImports {
+	for pkg, pkgPath := range allImports {
 		if _, ok := p.imports[pkg]; !ok {
-			p.imports[pkg] = path
+			p.imports[pkg] = pkgPath
 		}
 	}
 	// Add imports from auxiliary files, which might be needed for embedded interfaces.
 	// Don't stomp any other imports.
 	for _, f := range p.auxFiles {
 		auxImports, _ := importsOfFile(f)
-		for pkg, path := range auxImports {
+		for pkg, pkgPath := range auxImports {
 			if _, ok := p.imports[pkg]; !ok {
-				p.imports[pkg] = path
+				p.imports[pkg] = pkgPath
 			}
 		}
 	}
@@ -187,6 +188,7 @@ func (p *fileParser) parseFile(importPath string, file *ast.File) (*model.Packag
 	}
 	return &model.Package{
 		Name:       file.Name.String(),
+		PkgPath:    importPath,
 		Interfaces: is,
 		DotImports: dotImports,
 	}, nil
diff --git a/mockgen/reflect.go b/mockgen/reflect.go
index d4c7b7f..47f95ef 100644
--- a/mockgen/reflect.go
+++ b/mockgen/reflect.go
@@ -27,6 +27,7 @@ import (
 	"os/exec"
 	"path/filepath"
 	"runtime"
+	"strings"
 	"text/template"
 
 	"github.com/golang/mock/mockgen/model"
@@ -116,7 +117,7 @@ func runInDir(program []byte, dir string) (*model.Package, error) {
 	cmdArgs := []string{}
 	cmdArgs = append(cmdArgs, "build")
 	if *buildFlags != "" {
-		cmdArgs = append(cmdArgs, *buildFlags)
+		cmdArgs = append(cmdArgs, strings.Split(*buildFlags, " ")...)
 	}
 	cmdArgs = append(cmdArgs, "-o", progBinary, progSource)
 
@@ -131,7 +132,8 @@ func runInDir(program []byte, dir string) (*model.Package, error) {
 	return run(filepath.Join(tmpDir, progBinary))
 }
 
-func reflect(importPath string, symbols []string) (*model.Package, error) {
+// reflectMode generates mocks via reflection on an interface.
+func reflectMode(importPath string, symbols []string) (*model.Package, error) {
 	// TODO: sanity check arguments
 
 	if *execOnly != "" {
@@ -144,7 +146,7 @@ func reflect(importPath string, symbols []string) (*model.Package, error) {
 	}
 
 	if *progOnly {
-		os.Stdout.Write(program)
+		_, _ = os.Stdout.Write(program)
 		os.Exit(0)
 	}
 
diff --git a/mockgen/version.1.11.go b/mockgen/version.1.11.go
new file mode 100644
index 0000000..e47183d
--- /dev/null
+++ b/mockgen/version.1.11.go
@@ -0,0 +1,26 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !go1.12
+
+package main
+
+import (
+	"log"
+)
+
+func printVersion() {
+	log.Printf("No version information is available for Mockgen compiled with " +
+		"version 1.11")
+}
diff --git a/mockgen/version.1.12.go b/mockgen/version.1.12.go
new file mode 100644
index 0000000..3cc2ad8
--- /dev/null
+++ b/mockgen/version.1.12.go
@@ -0,0 +1,35 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// +build go1.12
+
+package main
+
+import (
+	"fmt"
+	"log"
+	"runtime/debug"
+)
+
+func printVersion() {
+	if bi, exists := debug.ReadBuildInfo(); exists {
+		fmt.Println(bi.Main.Version)
+	} else {
+		log.Printf("No version information found. Make sure to use " +
+			"GO111MODULE=on when running 'go get' in order to use specific " +
+			"version of the binary.")
+	}
+
+}


Test patch:
diff --git a/gomock/controller_test.go b/gomock/controller_test.go
index c0d42c8..c22908b 100644
--- a/gomock/controller_test.go
+++ b/gomock/controller_test.go
@@ -426,7 +426,7 @@ func TestMaxTimes1(t *testing.T) {
 	ctrl.Call(subject, "FooMethod", "argument")
 	ctrl.Finish()
 
-	//It fails if there are more
+	// It fails if there are more
 	reporter, ctrl := createFixtures(t)
 	subject = new(Subject)
 	ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
@@ -757,7 +757,7 @@ func TestVariadicNoMatch(t *testing.T) {
 	ctrl.RecordCall(s, "VariadicMethod", 0)
 	rep.assertFatal(func() {
 		ctrl.Call(s, "VariadicMethod", 1)
-	}, "Expected call at", "doesn't match the argument at index 0",
+	}, "expected call at", "doesn't match the argument at index 0",
 		"Got: 1\nWant: is equal to 0")
 	ctrl.Call(s, "VariadicMethod", 0)
 	ctrl.Finish()
diff --git a/gomock/matchers_test.go b/gomock/matchers_test.go
index 8bb87f7..ebddf0c 100644
--- a/gomock/matchers_test.go
+++ b/gomock/matchers_test.go
@@ -17,7 +17,9 @@
 package gomock_test
 
 import (
+	"context"
 	"errors"
+	"reflect"
 	"testing"
 
 	"github.com/golang/mock/gomock"
@@ -26,29 +28,36 @@ import (
 
 func TestMatchers(t *testing.T) {
 	type e interface{}
-	type testCase struct {
+	tests := []struct {
+		name    string
 		matcher gomock.Matcher
 		yes, no []e
-	}
-	tests := []testCase{
-		{gomock.Any(), []e{3, nil, "foo"}, nil},
-		{gomock.Eq(4), []e{4}, []e{3, "blah", nil, int64(4)}},
-		{gomock.Nil(),
+	}{
+		{"test Any", gomock.Any(), []e{3, nil, "foo"}, nil},
+		{"test All", gomock.Eq(4), []e{4}, []e{3, "blah", nil, int64(4)}},
+		{"test Nil", gomock.Nil(),
 			[]e{nil, (error)(nil), (chan bool)(nil), (*int)(nil)},
 			[]e{"", 0, make(chan bool), errors.New("err"), new(int)}},
-		{gomock.Not(gomock.Eq(4)), []e{3, "blah", nil, int64(4)}, []e{4}},
-	}
-	for i, test := range tests {
-		for _, x := range test.yes {
-			if !test.matcher.Matches(x) {
-				t.Errorf(`test %d: "%v %s" should be true.`, i, x, test.matcher)
+		{"test Not", gomock.Not(gomock.Eq(4)), []e{3, "blah", nil, int64(4)}, []e{4}},
+		{"test All", gomock.All(gomock.Any(), gomock.Eq(4)), []e{4}, []e{3, "blah", nil, int64(4)}},
+		{"test Len", gomock.Len(2),
+			[]e{[]int{1, 2}, "ab", map[string]int{"a": 0, "b": 1}, [2]string{"a", "b"}},
+			[]e{[]int{1}, "a", 42, 42.0, false, [1]string{"a"}},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			for _, x := range tt.yes {
+				if !tt.matcher.Matches(x) {
+					t.Errorf(`"%v %s": got false, want true.`, x, tt.matcher)
+				}
 			}
-		}
-		for _, x := range test.no {
-			if test.matcher.Matches(x) {
-				t.Errorf(`test %d: "%v %s" should be false.`, i, x, test.matcher)
+			for _, x := range tt.no {
+				if tt.matcher.Matches(x) {
+					t.Errorf(`"%v %s": got true, want false.`, x, tt.matcher)
+				}
 			}
-		}
+		})
 	}
 }
 
@@ -116,4 +125,14 @@ func TestAssignableToTypeOfMatcher(t *testing.T) {
 	if match := gomock.AssignableToTypeOf(&Dog{}).Matches(&Dog{Breed: "pug", Name: "Fido"}); !match {
 		t.Errorf(`AssignableToTypeOf(&Dog{}) should match &Dog{Breed: "pug", Name: "Fido"}`)
 	}
+
+	ctxInterface := reflect.TypeOf((*context.Context)(nil)).Elem()
+	if match := gomock.AssignableToTypeOf(ctxInterface).Matches(context.Background()); !match {
+		t.Errorf(`AssignableToTypeOf(context.Context) should not match context.Background()`)
+	}
+
+	ctxWithValue := context.WithValue(context.Background(), "key", "val")
+	if match := gomock.AssignableToTypeOf(ctxInterface).Matches(ctxWithValue); !match {
+		t.Errorf(`AssignableToTypeOf(context.Context) should not match ctxWithValue`)
+	}
 }
diff --git a/mockgen/internal/tests/performance/big_interface/big_interface.go b/mockgen/internal/tests/performance/big_interface/big_interface.go
new file mode 100644
index 0000000..2497d79
--- /dev/null
+++ b/mockgen/internal/tests/performance/big_interface/big_interface.go
@@ -0,0 +1,66 @@
+package big_interface
+
+type Bar struct{}
+
+type BigInterface interface {
+	Foo1(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo2(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo3(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo4(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo5(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo6(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo7(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo8(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo9(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo10(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo11(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo12(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo13(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo14(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo15(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo16(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo17(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo18(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo19(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo20(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo21(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo22(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo23(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo24(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo25(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo26(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo27(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo28(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo29(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo30(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo31(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo32(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo33(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo34(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo35(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo36(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo37(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo38(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo39(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo40(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo41(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo42(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo43(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo44(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo45(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo46(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo47(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo48(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo49(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo50(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo51(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo52(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo53(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo54(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo55(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo56(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo57(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo58(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo59(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+	Foo60(bool, bool, bool, bool, bool, bool, bool, bool) Bar
+}
diff --git a/mockgen/internal/tests/self_package/mock.go b/mockgen/internal/tests/self_package/mock.go
new file mode 100644
index 0000000..f1ecbe7
--- /dev/null
+++ b/mockgen/internal/tests/self_package/mock.go
@@ -0,0 +1,47 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/golang/mock/mockgen/internal/tests/self_package (interfaces: Methods)
+
+// Package core is a generated GoMock package.
+package core
+
+import (
+	gomock "github.com/golang/mock/gomock"
+	reflect "reflect"
+)
+
+// MockMethods is a mock of Methods interface
+type MockMethods struct {
+	ctrl     *gomock.Controller
+	recorder *MockMethodsMockRecorder
+}
+
+// MockMethodsMockRecorder is the mock recorder for MockMethods
+type MockMethodsMockRecorder struct {
+	mock *MockMethods
+}
+
+// NewMockMethods creates a new mock instance
+func NewMockMethods(ctrl *gomock.Controller) *MockMethods {
+	mock := &MockMethods{ctrl: ctrl}
+	mock.recorder = &MockMethodsMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use
+func (m *MockMethods) EXPECT() *MockMethodsMockRecorder {
+	return m.recorder
+}
+
+// getInfo mocks base method
+func (m *MockMethods) getInfo() Info {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "getInfo")
+	ret0, _ := ret[0].(Info)
+	return ret0
+}
+
+// getInfo indicates an expected call of getInfo
+func (mr *MockMethodsMockRecorder) getInfo() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "getInfo", reflect.TypeOf((*MockMethods)(nil).getInfo))
+}
diff --git a/mockgen/internal/tests/self_package/types.go b/mockgen/internal/tests/self_package/types.go
new file mode 100644
index 0000000..af1a87f
--- /dev/null
+++ b/mockgen/internal/tests/self_package/types.go
@@ -0,0 +1,10 @@
+//go:generate mockgen -package core -self_package github.com/golang/mock/mockgen/internal/tests/self_package -destination mock.go github.com/golang/mock/mockgen/internal/tests/self_package Methods
+package core
+
+type Info struct {
+	name string
+}
+
+type Methods interface {
+	getInfo() Info
+}
diff --git a/mockgen/mockgen_test.go b/mockgen/mockgen_test.go
index 573cc2b..1c139d7 100644
--- a/mockgen/mockgen_test.go
+++ b/mockgen/mockgen_test.go
@@ -2,6 +2,7 @@ package main
 
 import (
 	"fmt"
+	"reflect"
 	"regexp"
 	"strings"
 	"testing"
@@ -267,3 +268,69 @@ func findMethod(t *testing.T, identifier, methodName string, lines []string) int
 	t.Fatalf("unable to find 'func (m %s) %s'", identifier, methodName)
 	panic("unreachable")
 }
+
+func TestGetArgNames(t *testing.T) {
+	for _, testCase := range []struct {
+		name     string
+		method   *model.Method
+		expected []string
+	}{
+		{
+			name: "NamedArg",
+			method: &model.Method{
+				In: []*model.Parameter{
+					{
+						Name: "firstArg",
+						Type: &model.NamedType{Type: "int"},
+					},
+					{
+						Name: "secondArg",
+						Type: &model.NamedType{Type: "string"},
+					},
+				},
+			},
+			expected: []string{"firstArg", "secondArg"},
+		},
+		{
+			name: "NotNamedArg",
+			method: &model.Method{
+				In: []*model.Parameter{
+					{
+						Name: "",
+						Type: &model.NamedType{Type: "int"},
+					},
+					{
+						Name: "",
+						Type: &model.NamedType{Type: "string"},
+					},
+				},
+			},
+			expected: []string{"arg0", "arg1"},
+		},
+		{
+			name: "MixedNameArg",
+			method: &model.Method{
+				In: []*model.Parameter{
+					{
+						Name: "firstArg",
+						Type: &model.NamedType{Type: "int"},
+					},
+					{
+						Name: "_",
+						Type: &model.NamedType{Type: "string"},
+					},
+				},
+			},
+			expected: []string{"firstArg", "arg1"},
+		},
+	} {
+		t.Run(testCase.name, func(t *testing.T) {
+			g := generator{}
+
+			result := g.getArgNames(testCase.method)
+			if !reflect.DeepEqual(result, testCase.expected) {
+				t.Fatalf("expected %s, got %s", result, testCase.expected)
+			}
+		})
+	}
+}
diff --git a/mockgen/parse_test.go b/mockgen/parse_test.go
index f18399c..dab22fa 100644
--- a/mockgen/parse_test.go
+++ b/mockgen/parse_test.go
@@ -106,3 +106,10 @@ func checkGreeterImports(t *testing.T, imports map[string]string) {
 		t.Errorf("Expected import not to have key \"v1\"")
 	}
 }
+
+func Benchmark_parseFile(b *testing.B) {
+	source := "internal/tests/performance/big_interface/big_interface.go"
+	for n := 0; n < b.N; n++ {
+		sourceMode(source)
+	}
+}