Repository: golang/mock
Pull request #83 (2017-06-23 23:33:12)

Fix arg name conflicts
### Description

- Bugfix: mock method arg names no longer conflict with generated identifiers like `_m`, `_mr`, `_s`, etc...
  - The original implementation generates code that doesn't compile when using the "source" generation method with an arg name like `_m` or `_mr`.
  - The new implementation changes the names of generated identifiers when necessary (by appending `"_%d"` counter) to avoid conflicts with the arg names.
- Using the original method arg names instead of `arg0`, `arg1`, etc (if available in case of the "source" gen method) when generating the mock recorder methods. This can be very helpful while writing tests with an editor that gives hints about method signatures. At the same time it makes easier to read the generated mock sources.
- Specifying the type only once for consecutive args of the same type. E.g.: Instead of `s1 string, s2 string` it will be `s1, s2 string`.

### Example

**Original (buggy) implementation**

```go
// Register mocks base method
func (_m *MockMyInterface) Register(firstName string, lastName string, age int) {
	_m.ctrl.Call(_m, "Register", firstName, lastName, age)
}

// Register indicates an expected call of Register
func (_mr *MockMyInterfaceMockRecorder) Register(arg0, arg1, arg2 interface{}) *gomock.Call {
	return _mr.mock.ctrl.RecordCall(_mr.mock, "Register", arg0, arg1, arg2)
}

// BrakesOriginalImplementation mocks base method
func (_m *MockMyInterface) BrakesOriginalImplementation(_m int, _mr int, m int, mr int, varargs int, _s ...int) {
	_s := []interface{}{_m, _mr, m, mr, varargs}
	for _, _x := range _s {
		_s = append(_s, _x)
	}
	_m.ctrl.Call(_m, "BrakesOriginalImplementation", _s...)
}

// BrakesOriginalImplementation indicates an expected call of BrakesOriginalImplementation
func (_mr *MockMyInterfaceMockRecorder) BrakesOriginalImplementation(arg0, arg1, arg2, arg3, arg4 interface{}, arg5 ...interface{}) *gomock.Call {
	_s := append([]interface{}{arg0, arg1, arg2, arg3, arg4}, arg5...)
	return _mr.mock.ctrl.RecordCall(_mr.mock, "BrakesOriginalImplementation", _s...)
}
```

**New implementation**

```go
// Register mocks base method
func (m *MockMyInterface) Register(firstName, lastName string, age int) {
	m.ctrl.Call(m, "Register", firstName, lastName, age)
}

// Register indicates an expected call of Register
func (mr *MockMyInterfaceMockRecorder) Register(firstName, lastName, age interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCall(mr.mock, "Register", firstName, lastName, age)
}

// BrakesOriginalImplementation mocks base method
func (m_2 *MockMyInterface) BrakesOriginalImplementation(_m, _mr, m, mr, varargs int, _s ...int) {
	varargs_2 := []interface{}{_m, _mr, m, mr, varargs}
	for _, a := range _s {
		varargs_2 = append(varargs_2, a)
	}
	m_2.ctrl.Call(m_2, "BrakesOriginalImplementation", varargs_2...)
}

// BrakesOriginalImplementation indicates an expected call of BrakesOriginalImplementation
func (mr_2 *MockMyInterfaceMockRecorder) BrakesOriginalImplementation(_m, _mr, m, mr, varargs interface{}, _s ...interface{}) *gomock.Call {
	varargs_2 := append([]interface{}{_m, _mr, m, mr, varargs}, _s...)
	return mr_2.mock.ctrl.RecordCall(mr_2.mock, "BrakesOriginalImplementation", varargs_2...)
}
```

googlebot: Thanks for your pull request.  It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

:memo: **Please visit <https://cla.developers.google.com/> to sign.**

Once you've signed, please reply here (e.g. `I signed it!`) and we'll verify.  Thanks.

---

- If you've already signed a CLA, it's possible we don't have your GitHub username or you're using a different email address.  Check [your existing CLA data](https://cla.developers.google.com/clas) and verify that your [email is set on your git commits](https://help.github.com/articles/setting-your-email-in-git/).
- If your company signed a CLA, they designated a Point of Contact who decides which employees are authorized to participate. You may need to contact the Point of Contact for your company and ask to be added to the group of authorized contributors. If you don't know who your Point of Contact is, direct the project maintainer to go/cla#troubleshoot.
- In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again.

<!-- need_sender_cla -->
pasztorpisti: I signed it!
googlebot: CLAs look good, thanks!

<!-- ok -->

Patch:
diff --git a/gomock/mock_matcher/mock_matcher.go b/gomock/mock_matcher/mock_matcher.go
index d0bf885..3328ab7 100644
--- a/gomock/mock_matcher/mock_matcher.go
+++ b/gomock/mock_matcher/mock_matcher.go
@@ -27,30 +27,30 @@ func NewMockMatcher(ctrl *gomock.Controller) *MockMatcher {
 }
 
 // EXPECT returns an object that allows the caller to indicate expected use
-func (_m *MockMatcher) EXPECT() *MockMatcherMockRecorder {
-	return _m.recorder
+func (m *MockMatcher) EXPECT() *MockMatcherMockRecorder {
+	return m.recorder
 }
 
 // Matches mocks base method
-func (_m *MockMatcher) Matches(_param0 interface{}) bool {
-	ret := _m.ctrl.Call(_m, "Matches", _param0)
+func (m *MockMatcher) Matches(arg0 interface{}) bool {
+	ret := m.ctrl.Call(m, "Matches", arg0)
 	ret0, _ := ret[0].(bool)
 	return ret0
 }
 
 // Matches indicates an expected call of Matches
-func (_mr *MockMatcherMockRecorder) Matches(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Matches", reflect.TypeOf((*MockMatcher)(nil).Matches), arg0)
+func (mr *MockMatcherMockRecorder) Matches(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Matches", reflect.TypeOf((*MockMatcher)(nil).Matches), arg0)
 }
 
 // String mocks base method
-func (_m *MockMatcher) String() string {
-	ret := _m.ctrl.Call(_m, "String")
+func (m *MockMatcher) String() string {
+	ret := m.ctrl.Call(m, "String")
 	ret0, _ := ret[0].(string)
 	return ret0
 }
 
 // String indicates an expected call of String
-func (_mr *MockMatcherMockRecorder) String() *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "String", reflect.TypeOf((*MockMatcher)(nil).String))
+func (mr *MockMatcherMockRecorder) String() *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "String", reflect.TypeOf((*MockMatcher)(nil).String))
 }
diff --git a/mockgen/mockgen.go b/mockgen/mockgen.go
index 3b08c14..f6f3b05 100644
--- a/mockgen/mockgen.go
+++ b/mockgen/mockgen.go
@@ -293,9 +293,9 @@ func (g *generator) GenerateMockInterface(intf *model.Interface) error {
 
 	// XXX: possible name collision here if someone has EXPECT in their interface.
 	g.p("// EXPECT returns an object that allows the caller to indicate expected use")
-	g.p("func (_m *%v) EXPECT() *%vMockRecorder {", mockType, mockType)
+	g.p("func (m *%v) EXPECT() *%vMockRecorder {", mockType, mockType)
 	g.in()
-	g.p("return _m.recorder")
+	g.p("return m.recorder")
 	g.out()
 	g.p("}")
 
@@ -313,30 +313,25 @@ func (g *generator) GenerateMockMethods(mockType string, intf *model.Interface,
 	}
 }
 
+func makeArgString(argNames, argTypes []string) string {
+	args := make([]string, len(argNames))
+	for i, name := range argNames {
+		// specify the type only once for consecutive args of the same type
+		if i+1 < len(argTypes) && argTypes[i] == argTypes[i+1] {
+			args[i] = name
+		} else {
+			args[i] = name + " " + argTypes[i]
+		}
+	}
+	return strings.Join(args, ", ")
+}
+
 // GenerateMockMethod generates a mock method implementation.
 // If non-empty, pkgOverride is the package in which unqualified types reside.
 func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOverride string) error {
-	args := make([]string, len(m.In))
-	argNames := make([]string, len(m.In))
-	for i, p := range m.In {
-		name := p.Name
-		if name == "" {
-			name = fmt.Sprintf("_param%d", i)
-		}
-		ts := p.Type.String(g.packageMap, pkgOverride)
-		args[i] = name + " " + ts
-		argNames[i] = name
-	}
-	if m.Variadic != nil {
-		name := m.Variadic.Name
-		if name == "" {
-			name = fmt.Sprintf("_param%d", len(m.In))
-		}
-		ts := m.Variadic.Type.String(g.packageMap, pkgOverride)
-		args = append(args, name+" ..."+ts)
-		argNames = append(argNames, name)
-	}
-	argString := strings.Join(args, ", ")
+	argNames := g.getArgNames(m)
+	argTypes := g.getArgTypes(m, pkgOverride)
+	argString := makeArgString(argNames, argTypes)
 
 	rets := make([]string, len(m.Out))
 	for i, p := range m.Out {
@@ -350,37 +345,44 @@ func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOver
 		retString = " " + retString
 	}
 
+	ia := newIdentifierAllocator(argNames)
+	idRecv := ia.allocateIdentifier("m")
+
 	g.p("// %v mocks base method", m.Name)
-	g.p("func (_m *%v) %v(%v)%v {", mockType, m.Name, argString, retString)
+	g.p("func (%v *%v) %v(%v)%v {", idRecv, mockType, m.Name, argString, retString)
 	g.in()
 
-	callArgs := strings.Join(argNames, ", ")
-	if callArgs != "" {
-		callArgs = ", " + callArgs
-	}
-	if m.Variadic != nil {
+	var callArgs string
+	if m.Variadic == nil {
+		if len(argNames) > 0 {
+			callArgs = ", " + strings.Join(argNames, ", ")
+		}
+	} else {
 		// Non-trivial. The generated code must build a []interface{},
 		// but the variadic argument may be any type.
-		g.p("_s := []interface{}{%s}", strings.Join(argNames[:len(argNames)-1], ", "))
-		g.p("for _, _x := range %s {", argNames[len(argNames)-1])
+		idVarArgs := ia.allocateIdentifier("varargs")
+		idVArg := ia.allocateIdentifier("a")
+		g.p("%s := []interface{}{%s}", idVarArgs, strings.Join(argNames[:len(argNames)-1], ", "))
+		g.p("for _, %s := range %s {", idVArg, argNames[len(argNames)-1])
 		g.in()
-		g.p("_s = append(_s, _x)")
+		g.p("%s = append(%s, %s)", idVarArgs, idVarArgs, idVArg)
 		g.out()
 		g.p("}")
-		callArgs = ", _s..."
+		callArgs = ", " + idVarArgs + "..."
 	}
 	if len(m.Out) == 0 {
-		g.p(`_m.ctrl.Call(_m, "%v"%v)`, m.Name, callArgs)
+		g.p(`%v.ctrl.Call(%v, %q%v)`, idRecv, idRecv, m.Name, callArgs)
 	} else {
-		g.p(`ret := _m.ctrl.Call(_m, "%v"%v)`, m.Name, callArgs)
+		idRet := ia.allocateIdentifier("ret")
+		g.p(`%v := %v.ctrl.Call(%v, %q%v)`, idRet, idRecv, idRecv, m.Name, callArgs)
 
 		// Go does not allow "naked" type assertions on nil values, so we use the two-value form here.
 		// The value of that is either (x.(T), true) or (Z, false), where Z is the zero value for T.
 		// Happily, this coincides with the semantics we want here.
 		retNames := make([]string, len(rets))
 		for i, t := range rets {
-			retNames[i] = fmt.Sprintf("ret%d", i)
-			g.p("%s, _ := ret[%d].(%s)", retNames[i], i, t)
+			retNames[i] = ia.allocateIdentifier(fmt.Sprintf("ret%d", i))
+			g.p("%s, _ := %s[%d].(%s)", retNames[i], idRet, i, t)
 		}
 		g.p("return " + strings.Join(retNames, ", "))
 	}
@@ -391,47 +393,109 @@ func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOver
 }
 
 func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method) error {
-	nargs := len(m.In)
-	args := make([]string, nargs)
-	for i := 0; i < nargs; i++ {
-		args[i] = "arg" + strconv.Itoa(i)
+	argNames := g.getArgNames(m)
+
+	var argString string
+	if m.Variadic == nil {
+		argString = strings.Join(argNames, ", ")
+	} else {
+		argString = strings.Join(argNames[:len(argNames)-1], ", ")
 	}
-	argString := strings.Join(args, ", ")
-	if nargs > 0 {
+	if argString != "" {
 		argString += " interface{}"
 	}
+
 	if m.Variadic != nil {
-		if nargs > 0 {
+		if argString != "" {
 			argString += ", "
 		}
-		argString += fmt.Sprintf("arg%d ...interface{}", nargs)
+		argString += fmt.Sprintf("%s ...interface{}", argNames[len(argNames)-1])
 	}
 
+	ia := newIdentifierAllocator(argNames)
+	idRecv := ia.allocateIdentifier("mr")
+
 	g.p("// %v indicates an expected call of %v", m.Name, m.Name)
-	g.p("func (_mr *%vMockRecorder) %v(%v) *gomock.Call {", mockType, m.Name, argString)
+	g.p("func (%s *%vMockRecorder) %v(%v) *gomock.Call {", idRecv, mockType, m.Name, argString)
 	g.in()
 
-	callArgs := strings.Join(args, ", ")
-	if nargs > 0 {
-		callArgs = ", " + callArgs
-	}
-	if m.Variadic != nil {
-		if nargs == 0 {
+	var callArgs string
+	if m.Variadic == nil {
+		if len(argNames) > 0 {
+			callArgs = ", " + strings.Join(argNames, ", ")
+		}
+	} else {
+		if len(argNames) == 1 {
 			// Easy: just use ... to push the arguments through.
-			callArgs = ", arg0..."
+			callArgs = ", " + argNames[0] + "..."
 		} else {
 			// Hard: create a temporary slice.
-			g.p("_s := append([]interface{}{%s}, arg%d...)", strings.Join(args, ", "), nargs)
-			callArgs = ", _s..."
+			idVarArgs := ia.allocateIdentifier("varargs")
+			g.p("%s := append([]interface{}{%s}, %s...)",
+				idVarArgs,
+				strings.Join(argNames[:len(argNames)-1], ", "),
+				argNames[len(argNames)-1])
+			callArgs = ", " + idVarArgs + "..."
 		}
 	}
-	g.p(`return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "%s", reflect.TypeOf((*%s)(nil).%s)%s)`, m.Name, mockType, m.Name, callArgs)
+	g.p(`return %s.mock.ctrl.RecordCallWithMethodType(%s.mock, "%s", reflect.TypeOf((*%s)(nil).%s)%s)`, idRecv, idRecv, m.Name, mockType, m.Name, callArgs)
 
 	g.out()
 	g.p("}")
 	return nil
 }
 
+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 == "" {
+			name = fmt.Sprintf("arg%d", i)
+		}
+		argNames[i] = name
+	}
+	if m.Variadic != nil {
+		name := m.Variadic.Name
+		if name == "" {
+			name = fmt.Sprintf("arg%d", len(m.In))
+		}
+		argNames = append(argNames, name)
+	}
+	return argNames
+}
+
+func (g *generator) getArgTypes(m *model.Method, pkgOverride string) []string {
+	argTypes := make([]string, len(m.In))
+	for i, p := range m.In {
+		argTypes[i] = p.Type.String(g.packageMap, pkgOverride)
+	}
+	if m.Variadic != nil {
+		argTypes = append(argTypes, "..."+m.Variadic.Type.String(g.packageMap, pkgOverride))
+	}
+	return argTypes
+}
+
+type identifierAllocator map[string]struct{}
+
+func newIdentifierAllocator(taken []string) identifierAllocator {
+	a := make(identifierAllocator, len(taken))
+	for _, s := range taken {
+		a[s] = struct{}{}
+	}
+	return a
+}
+
+func (o identifierAllocator) allocateIdentifier(want string) string {
+	id := want
+	for i := 2; ; i++ {
+		if _, ok := o[id]; !ok {
+			o[id] = struct{}{}
+			return id
+		}
+		id = want + "_" + strconv.Itoa(i)
+	}
+}
+
 // Output returns the generator's output, formatted in the standard Go style.
 func (g *generator) Output() []byte {
 	src, err := format.Source(g.buf.Bytes())
diff --git a/sample/mock_user/mock_user.go b/sample/mock_user/mock_user.go
index 59602ef..df8254b 100644
--- a/sample/mock_user/mock_user.go
+++ b/sample/mock_user/mock_user.go
@@ -38,250 +38,250 @@ func NewMockIndex(ctrl *gomock.Controller) *MockIndex {
 }
 
 // EXPECT returns an object that allows the caller to indicate expected use
-func (_m *MockIndex) EXPECT() *MockIndexMockRecorder {
-	return _m.recorder
+func (m *MockIndex) EXPECT() *MockIndexMockRecorder {
+	return m.recorder
 }
 
 // Anon mocks base method
-func (_m *MockIndex) Anon(_param0 string) {
-	_m.ctrl.Call(_m, "Anon", _param0)
+func (m *MockIndex) Anon(arg0 string) {
+	m.ctrl.Call(m, "Anon", arg0)
 }
 
 // Anon indicates an expected call of Anon
-func (_mr *MockIndexMockRecorder) Anon(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Anon", reflect.TypeOf((*MockIndex)(nil).Anon), arg0)
+func (mr *MockIndexMockRecorder) Anon(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Anon", reflect.TypeOf((*MockIndex)(nil).Anon), arg0)
 }
 
 // Chan mocks base method
-func (_m *MockIndex) Chan(_param0 chan int, _param1 chan<- hash.Hash) {
-	_m.ctrl.Call(_m, "Chan", _param0, _param1)
+func (m *MockIndex) Chan(arg0 chan int, arg1 chan<- hash.Hash) {
+	m.ctrl.Call(m, "Chan", arg0, arg1)
 }
 
 // Chan indicates an expected call of Chan
-func (_mr *MockIndexMockRecorder) Chan(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Chan", reflect.TypeOf((*MockIndex)(nil).Chan), arg0, arg1)
+func (mr *MockIndexMockRecorder) Chan(arg0, arg1 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Chan", reflect.TypeOf((*MockIndex)(nil).Chan), arg0, arg1)
 }
 
 // ConcreteRet mocks base method
-func (_m *MockIndex) ConcreteRet() chan<- bool {
-	ret := _m.ctrl.Call(_m, "ConcreteRet")
+func (m *MockIndex) ConcreteRet() chan<- bool {
+	ret := m.ctrl.Call(m, "ConcreteRet")
 	ret0, _ := ret[0].(chan<- bool)
 	return ret0
 }
 
 // ConcreteRet indicates an expected call of ConcreteRet
-func (_mr *MockIndexMockRecorder) ConcreteRet() *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "ConcreteRet", reflect.TypeOf((*MockIndex)(nil).ConcreteRet))
+func (mr *MockIndexMockRecorder) ConcreteRet() *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConcreteRet", reflect.TypeOf((*MockIndex)(nil).ConcreteRet))
 }
 
 // Ellip mocks base method
-func (_m *MockIndex) Ellip(_param0 string, _param1 ...interface{}) {
-	_s := []interface{}{_param0}
-	for _, _x := range _param1 {
-		_s = append(_s, _x)
+func (m *MockIndex) Ellip(arg0 string, arg1 ...interface{}) {
+	varargs := []interface{}{arg0}
+	for _, a := range arg1 {
+		varargs = append(varargs, a)
 	}
-	_m.ctrl.Call(_m, "Ellip", _s...)
+	m.ctrl.Call(m, "Ellip", varargs...)
 }
 
 // Ellip indicates an expected call of Ellip
-func (_mr *MockIndexMockRecorder) Ellip(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
-	_s := append([]interface{}{arg0}, arg1...)
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Ellip", reflect.TypeOf((*MockIndex)(nil).Ellip), _s...)
+func (mr *MockIndexMockRecorder) Ellip(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+	varargs := append([]interface{}{arg0}, arg1...)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ellip", reflect.TypeOf((*MockIndex)(nil).Ellip), varargs...)
 }
 
 // EllipOnly mocks base method
-func (_m *MockIndex) EllipOnly(_param0 ...string) {
-	_s := []interface{}{}
-	for _, _x := range _param0 {
-		_s = append(_s, _x)
+func (m *MockIndex) EllipOnly(arg0 ...string) {
+	varargs := []interface{}{}
+	for _, a := range arg0 {
+		varargs = append(varargs, a)
 	}
-	_m.ctrl.Call(_m, "EllipOnly", _s...)
+	m.ctrl.Call(m, "EllipOnly", varargs...)
 }
 
 // EllipOnly indicates an expected call of EllipOnly
-func (_mr *MockIndexMockRecorder) EllipOnly(arg0 ...interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "EllipOnly", reflect.TypeOf((*MockIndex)(nil).EllipOnly), arg0...)
+func (mr *MockIndexMockRecorder) EllipOnly(arg0 ...interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EllipOnly", reflect.TypeOf((*MockIndex)(nil).EllipOnly), arg0...)
 }
 
 // ForeignFour mocks base method
-func (_m *MockIndex) ForeignFour(_param0 imp4.Imp4) {
-	_m.ctrl.Call(_m, "ForeignFour", _param0)
+func (m *MockIndex) ForeignFour(arg0 imp4.Imp4) {
+	m.ctrl.Call(m, "ForeignFour", arg0)
 }
 
 // ForeignFour indicates an expected call of ForeignFour
-func (_mr *MockIndexMockRecorder) ForeignFour(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "ForeignFour", reflect.TypeOf((*MockIndex)(nil).ForeignFour), arg0)
+func (mr *MockIndexMockRecorder) ForeignFour(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForeignFour", reflect.TypeOf((*MockIndex)(nil).ForeignFour), arg0)
 }
 
 // ForeignOne mocks base method
-func (_m *MockIndex) ForeignOne(_param0 imp1.Imp1) {
-	_m.ctrl.Call(_m, "ForeignOne", _param0)
+func (m *MockIndex) ForeignOne(arg0 imp1.Imp1) {
+	m.ctrl.Call(m, "ForeignOne", arg0)
 }
 
 // ForeignOne indicates an expected call of ForeignOne
-func (_mr *MockIndexMockRecorder) ForeignOne(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "ForeignOne", reflect.TypeOf((*MockIndex)(nil).ForeignOne), arg0)
+func (mr *MockIndexMockRecorder) ForeignOne(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForeignOne", reflect.TypeOf((*MockIndex)(nil).ForeignOne), arg0)
 }
 
 // ForeignThree mocks base method
-func (_m *MockIndex) ForeignThree(_param0 imp3.Imp3) {
-	_m.ctrl.Call(_m, "ForeignThree", _param0)
+func (m *MockIndex) ForeignThree(arg0 imp3.Imp3) {
+	m.ctrl.Call(m, "ForeignThree", arg0)
 }
 
 // ForeignThree indicates an expected call of ForeignThree
-func (_mr *MockIndexMockRecorder) ForeignThree(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "ForeignThree", reflect.TypeOf((*MockIndex)(nil).ForeignThree), arg0)
+func (mr *MockIndexMockRecorder) ForeignThree(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForeignThree", reflect.TypeOf((*MockIndex)(nil).ForeignThree), arg0)
 }
 
 // ForeignTwo mocks base method
-func (_m *MockIndex) ForeignTwo(_param0 imp2.Imp2) {
-	_m.ctrl.Call(_m, "ForeignTwo", _param0)
+func (m *MockIndex) ForeignTwo(arg0 imp2.Imp2) {
+	m.ctrl.Call(m, "ForeignTwo", arg0)
 }
 
 // ForeignTwo indicates an expected call of ForeignTwo
-func (_mr *MockIndexMockRecorder) ForeignTwo(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "ForeignTwo", reflect.TypeOf((*MockIndex)(nil).ForeignTwo), arg0)
+func (mr *MockIndexMockRecorder) ForeignTwo(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForeignTwo", reflect.TypeOf((*MockIndex)(nil).ForeignTwo), arg0)
 }
 
 // Func mocks base method
-func (_m *MockIndex) Func(_param0 func(http.Request) (int, bool)) {
-	_m.ctrl.Call(_m, "Func", _param0)
+func (m *MockIndex) Func(arg0 func(http.Request) (int, bool)) {
+	m.ctrl.Call(m, "Func", arg0)
 }
 
 // Func indicates an expected call of Func
-func (_mr *MockIndexMockRecorder) Func(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Func", reflect.TypeOf((*MockIndex)(nil).Func), arg0)
+func (mr *MockIndexMockRecorder) Func(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Func", reflect.TypeOf((*MockIndex)(nil).Func), arg0)
 }
 
 // Get mocks base method
-func (_m *MockIndex) Get(_param0 string) interface{} {
-	ret := _m.ctrl.Call(_m, "Get", _param0)
+func (m *MockIndex) Get(arg0 string) interface{} {
+	ret := m.ctrl.Call(m, "Get", arg0)
 	ret0, _ := ret[0].(interface{})
 	return ret0
 }
 
 // Get indicates an expected call of Get
-func (_mr *MockIndexMockRecorder) Get(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Get", reflect.TypeOf((*MockIndex)(nil).Get), arg0)
+func (mr *MockIndexMockRecorder) Get(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockIndex)(nil).Get), arg0)
 }
 
 // GetTwo mocks base method
-func (_m *MockIndex) GetTwo(_param0 string, _param1 string) (interface{}, interface{}) {
-	ret := _m.ctrl.Call(_m, "GetTwo", _param0, _param1)
+func (m *MockIndex) GetTwo(arg0, arg1 string) (interface{}, interface{}) {
+	ret := m.ctrl.Call(m, "GetTwo", arg0, arg1)
 	ret0, _ := ret[0].(interface{})
 	ret1, _ := ret[1].(interface{})
 	return ret0, ret1
 }
 
 // GetTwo indicates an expected call of GetTwo
-func (_mr *MockIndexMockRecorder) GetTwo(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "GetTwo", reflect.TypeOf((*MockIndex)(nil).GetTwo), arg0, arg1)
+func (mr *MockIndexMockRecorder) GetTwo(arg0, arg1 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTwo", reflect.TypeOf((*MockIndex)(nil).GetTwo), arg0, arg1)
 }
 
 // Map mocks base method
-func (_m *MockIndex) Map(_param0 map[int]hash.Hash) {
-	_m.ctrl.Call(_m, "Map", _param0)
+func (m *MockIndex) Map(arg0 map[int]hash.Hash) {
+	m.ctrl.Call(m, "Map", arg0)
 }
 
 // Map indicates an expected call of Map
-func (_mr *MockIndexMockRecorder) Map(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Map", reflect.TypeOf((*MockIndex)(nil).Map), arg0)
+func (mr *MockIndexMockRecorder) Map(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Map", reflect.TypeOf((*MockIndex)(nil).Map), arg0)
 }
 
 // NillableRet mocks base method
-func (_m *MockIndex) NillableRet() error {
-	ret := _m.ctrl.Call(_m, "NillableRet")
+func (m *MockIndex) NillableRet() error {
+	ret := m.ctrl.Call(m, "NillableRet")
 	ret0, _ := ret[0].(error)
 	return ret0
 }
 
 // NillableRet indicates an expected call of NillableRet
-func (_mr *MockIndexMockRecorder) NillableRet() *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "NillableRet", reflect.TypeOf((*MockIndex)(nil).NillableRet))
+func (mr *MockIndexMockRecorder) NillableRet() *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NillableRet", reflect.TypeOf((*MockIndex)(nil).NillableRet))
 }
 
 // Other mocks base method
-func (_m *MockIndex) Other() hash.Hash {
-	ret := _m.ctrl.Call(_m, "Other")
+func (m *MockIndex) Other() hash.Hash {
+	ret := m.ctrl.Call(m, "Other")
 	ret0, _ := ret[0].(hash.Hash)
 	return ret0
 }
 
 // Other indicates an expected call of Other
-func (_mr *MockIndexMockRecorder) Other() *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Other", reflect.TypeOf((*MockIndex)(nil).Other))
+func (mr *MockIndexMockRecorder) Other() *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Other", reflect.TypeOf((*MockIndex)(nil).Other))
 }
 
 // Ptr mocks base method
-func (_m *MockIndex) Ptr(_param0 *int) {
-	_m.ctrl.Call(_m, "Ptr", _param0)
+func (m *MockIndex) Ptr(arg0 *int) {
+	m.ctrl.Call(m, "Ptr", arg0)
 }
 
 // Ptr indicates an expected call of Ptr
-func (_mr *MockIndexMockRecorder) Ptr(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Ptr", reflect.TypeOf((*MockIndex)(nil).Ptr), arg0)
+func (mr *MockIndexMockRecorder) Ptr(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ptr", reflect.TypeOf((*MockIndex)(nil).Ptr), arg0)
 }
 
 // Put mocks base method
-func (_m *MockIndex) Put(_param0 string, _param1 interface{}) {
-	_m.ctrl.Call(_m, "Put", _param0, _param1)
+func (m *MockIndex) Put(arg0 string, arg1 interface{}) {
+	m.ctrl.Call(m, "Put", arg0, arg1)
 }
 
 // Put indicates an expected call of Put
-func (_mr *MockIndexMockRecorder) Put(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Put", reflect.TypeOf((*MockIndex)(nil).Put), arg0, arg1)
+func (mr *MockIndexMockRecorder) Put(arg0, arg1 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockIndex)(nil).Put), arg0, arg1)
 }
 
 // Slice mocks base method
-func (_m *MockIndex) Slice(_param0 []int, _param1 []byte) [3]int {
-	ret := _m.ctrl.Call(_m, "Slice", _param0, _param1)
+func (m *MockIndex) Slice(arg0 []int, arg1 []byte) [3]int {
+	ret := m.ctrl.Call(m, "Slice", arg0, arg1)
 	ret0, _ := ret[0].([3]int)
 	return ret0
 }
 
 // Slice indicates an expected call of Slice
-func (_mr *MockIndexMockRecorder) Slice(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Slice", reflect.TypeOf((*MockIndex)(nil).Slice), arg0, arg1)
+func (mr *MockIndexMockRecorder) Slice(arg0, arg1 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Slice", reflect.TypeOf((*MockIndex)(nil).Slice), arg0, arg1)
 }
 
 // Struct mocks base method
-func (_m *MockIndex) Struct(_param0 struct{}) {
-	_m.ctrl.Call(_m, "Struct", _param0)
+func (m *MockIndex) Struct(arg0 struct{}) {
+	m.ctrl.Call(m, "Struct", arg0)
 }
 
 // Struct indicates an expected call of Struct
-func (_mr *MockIndexMockRecorder) Struct(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Struct", reflect.TypeOf((*MockIndex)(nil).Struct), arg0)
+func (mr *MockIndexMockRecorder) Struct(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Struct", reflect.TypeOf((*MockIndex)(nil).Struct), arg0)
 }
 
 // StructChan mocks base method
-func (_m *MockIndex) StructChan(_param0 chan struct{}) {
-	_m.ctrl.Call(_m, "StructChan", _param0)
+func (m *MockIndex) StructChan(arg0 chan struct{}) {
+	m.ctrl.Call(m, "StructChan", arg0)
 }
 
 // StructChan indicates an expected call of StructChan
-func (_mr *MockIndexMockRecorder) StructChan(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "StructChan", reflect.TypeOf((*MockIndex)(nil).StructChan), arg0)
+func (mr *MockIndexMockRecorder) StructChan(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StructChan", reflect.TypeOf((*MockIndex)(nil).StructChan), arg0)
 }
 
 // Summary mocks base method
-func (_m *MockIndex) Summary(_param0 *bytes.Buffer, _param1 io.Writer) {
-	_m.ctrl.Call(_m, "Summary", _param0, _param1)
+func (m *MockIndex) Summary(arg0 *bytes.Buffer, arg1 io.Writer) {
+	m.ctrl.Call(m, "Summary", arg0, arg1)
 }
 
 // Summary indicates an expected call of Summary
-func (_mr *MockIndexMockRecorder) Summary(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Summary", reflect.TypeOf((*MockIndex)(nil).Summary), arg0, arg1)
+func (mr *MockIndexMockRecorder) Summary(arg0, arg1 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Summary", reflect.TypeOf((*MockIndex)(nil).Summary), arg0, arg1)
 }
 
 // Templates mocks base method
-func (_m *MockIndex) Templates(_param0 template.CSS, _param1 template0.FuncMap) {
-	_m.ctrl.Call(_m, "Templates", _param0, _param1)
+func (m *MockIndex) Templates(arg0 template.CSS, arg1 template0.FuncMap) {
+	m.ctrl.Call(m, "Templates", arg0, arg1)
 }
 
 // Templates indicates an expected call of Templates
-func (_mr *MockIndexMockRecorder) Templates(arg0, arg1 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "Templates", reflect.TypeOf((*MockIndex)(nil).Templates), arg0, arg1)
+func (mr *MockIndexMockRecorder) Templates(arg0, arg1 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Templates", reflect.TypeOf((*MockIndex)(nil).Templates), arg0, arg1)
 }
 
 // MockEmbed is a mock of Embed interface
@@ -303,50 +303,50 @@ func NewMockEmbed(ctrl *gomock.Controller) *MockEmbed {
 }
 
 // EXPECT returns an object that allows the caller to indicate expected use
-func (_m *MockEmbed) EXPECT() *MockEmbedMockRecorder {
-	return _m.recorder
+func (m *MockEmbed) EXPECT() *MockEmbedMockRecorder {
+	return m.recorder
 }
 
 // EmbeddedMethod mocks base method
-func (_m *MockEmbed) EmbeddedMethod() {
-	_m.ctrl.Call(_m, "EmbeddedMethod")
+func (m *MockEmbed) EmbeddedMethod() {
+	m.ctrl.Call(m, "EmbeddedMethod")
 }
 
 // EmbeddedMethod indicates an expected call of EmbeddedMethod
-func (_mr *MockEmbedMockRecorder) EmbeddedMethod() *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "EmbeddedMethod", reflect.TypeOf((*MockEmbed)(nil).EmbeddedMethod))
+func (mr *MockEmbedMockRecorder) EmbeddedMethod() *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EmbeddedMethod", reflect.TypeOf((*MockEmbed)(nil).EmbeddedMethod))
 }
 
 // ForeignEmbeddedMethod mocks base method
-func (_m *MockEmbed) ForeignEmbeddedMethod() *bufio.Reader {
-	ret := _m.ctrl.Call(_m, "ForeignEmbeddedMethod")
+func (m *MockEmbed) ForeignEmbeddedMethod() *bufio.Reader {
+	ret := m.ctrl.Call(m, "ForeignEmbeddedMethod")
 	ret0, _ := ret[0].(*bufio.Reader)
 	return ret0
 }
 
 // ForeignEmbeddedMethod indicates an expected call of ForeignEmbeddedMethod
-func (_mr *MockEmbedMockRecorder) ForeignEmbeddedMethod() *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "ForeignEmbeddedMethod", reflect.TypeOf((*MockEmbed)(nil).ForeignEmbeddedMethod))
+func (mr *MockEmbedMockRecorder) ForeignEmbeddedMethod() *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ForeignEmbeddedMethod", reflect.TypeOf((*MockEmbed)(nil).ForeignEmbeddedMethod))
 }
 
 // ImplicitPackage mocks base method
-func (_m *MockEmbed) ImplicitPackage(_param0 string, _param1 imp1.ImpT, _param2 []imp1.ImpT, _param3 *imp1.ImpT, _param4 chan imp1.ImpT) {
-	_m.ctrl.Call(_m, "ImplicitPackage", _param0, _param1, _param2, _param3, _param4)
+func (m *MockEmbed) ImplicitPackage(arg0 string, arg1 imp1.ImpT, arg2 []imp1.ImpT, arg3 *imp1.ImpT, arg4 chan imp1.ImpT) {
+	m.ctrl.Call(m, "ImplicitPackage", arg0, arg1, arg2, arg3, arg4)
 }
 
 // ImplicitPackage indicates an expected call of ImplicitPackage
-func (_mr *MockEmbedMockRecorder) ImplicitPackage(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "ImplicitPackage", reflect.TypeOf((*MockEmbed)(nil).ImplicitPackage), arg0, arg1, arg2, arg3, arg4)
+func (mr *MockEmbedMockRecorder) ImplicitPackage(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImplicitPackage", reflect.TypeOf((*MockEmbed)(nil).ImplicitPackage), arg0, arg1, arg2, arg3, arg4)
 }
 
 // RegularMethod mocks base method
-func (_m *MockEmbed) RegularMethod() {
-	_m.ctrl.Call(_m, "RegularMethod")
+func (m *MockEmbed) RegularMethod() {
+	m.ctrl.Call(m, "RegularMethod")
 }
 
 // RegularMethod indicates an expected call of RegularMethod
-func (_mr *MockEmbedMockRecorder) RegularMethod() *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "RegularMethod", reflect.TypeOf((*MockEmbed)(nil).RegularMethod))
+func (mr *MockEmbedMockRecorder) RegularMethod() *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegularMethod", reflect.TypeOf((*MockEmbed)(nil).RegularMethod))
 }
 
 // MockEmbedded is a mock of Embedded interface
@@ -368,16 +368,16 @@ func NewMockEmbedded(ctrl *gomock.Controller) *MockEmbedded {
 }
 
 // EXPECT returns an object that allows the caller to indicate expected use
-func (_m *MockEmbedded) EXPECT() *MockEmbeddedMockRecorder {
-	return _m.recorder
+func (m *MockEmbedded) EXPECT() *MockEmbeddedMockRecorder {
+	return m.recorder
 }
 
 // EmbeddedMethod mocks base method
-func (_m *MockEmbedded) EmbeddedMethod() {
-	_m.ctrl.Call(_m, "EmbeddedMethod")
+func (m *MockEmbedded) EmbeddedMethod() {
+	m.ctrl.Call(m, "EmbeddedMethod")
 }
 
 // EmbeddedMethod indicates an expected call of EmbeddedMethod
-func (_mr *MockEmbeddedMockRecorder) EmbeddedMethod() *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "EmbeddedMethod", reflect.TypeOf((*MockEmbedded)(nil).EmbeddedMethod))
+func (mr *MockEmbeddedMockRecorder) EmbeddedMethod() *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EmbeddedMethod", reflect.TypeOf((*MockEmbedded)(nil).EmbeddedMethod))
 }


Test patch:
diff --git a/mockgen/mockgen_test.go b/mockgen/mockgen_test.go
new file mode 100644
index 0000000..bcb2a97
--- /dev/null
+++ b/mockgen/mockgen_test.go
@@ -0,0 +1,181 @@
+package main
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestMakeArgString(t *testing.T) {
+	testCases := []struct {
+		argNames  []string
+		argTypes  []string
+		argString string
+	}{
+		{
+			argNames:  nil,
+			argTypes:  nil,
+			argString: "",
+		},
+		{
+			argNames:  []string{"arg0"},
+			argTypes:  []string{"int"},
+			argString: "arg0 int",
+		},
+		{
+			argNames:  []string{"arg0", "arg1"},
+			argTypes:  []string{"int", "bool"},
+			argString: "arg0 int, arg1 bool",
+		},
+		{
+			argNames:  []string{"arg0", "arg1"},
+			argTypes:  []string{"int", "int"},
+			argString: "arg0, arg1 int",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2"},
+			argTypes:  []string{"bool", "int", "int"},
+			argString: "arg0 bool, arg1, arg2 int",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2"},
+			argTypes:  []string{"int", "bool", "int"},
+			argString: "arg0 int, arg1 bool, arg2 int",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2"},
+			argTypes:  []string{"int", "int", "bool"},
+			argString: "arg0, arg1 int, arg2 bool",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2"},
+			argTypes:  []string{"int", "int", "int"},
+			argString: "arg0, arg1, arg2 int",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2", "arg3"},
+			argTypes:  []string{"bool", "int", "int", "int"},
+			argString: "arg0 bool, arg1, arg2, arg3 int",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2", "arg3"},
+			argTypes:  []string{"int", "bool", "int", "int"},
+			argString: "arg0 int, arg1 bool, arg2, arg3 int",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2", "arg3"},
+			argTypes:  []string{"int", "int", "bool", "int"},
+			argString: "arg0, arg1 int, arg2 bool, arg3 int",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2", "arg3"},
+			argTypes:  []string{"int", "int", "int", "bool"},
+			argString: "arg0, arg1, arg2 int, arg3 bool",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2", "arg3", "arg4"},
+			argTypes:  []string{"bool", "int", "int", "int", "bool"},
+			argString: "arg0 bool, arg1, arg2, arg3 int, arg4 bool",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2", "arg3", "arg4"},
+			argTypes:  []string{"int", "bool", "int", "int", "bool"},
+			argString: "arg0 int, arg1 bool, arg2, arg3 int, arg4 bool",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2", "arg3", "arg4"},
+			argTypes:  []string{"int", "int", "bool", "int", "bool"},
+			argString: "arg0, arg1 int, arg2 bool, arg3 int, arg4 bool",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2", "arg3", "arg4"},
+			argTypes:  []string{"int", "int", "int", "bool", "bool"},
+			argString: "arg0, arg1, arg2 int, arg3, arg4 bool",
+		},
+		{
+			argNames:  []string{"arg0", "arg1", "arg2", "arg3", "arg4"},
+			argTypes:  []string{"int", "int", "bool", "bool", "int"},
+			argString: "arg0, arg1 int, arg2, arg3 bool, arg4 int",
+		},
+	}
+
+	for i, tc := range testCases {
+		t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
+			s := makeArgString(tc.argNames, tc.argTypes)
+			if s != tc.argString {
+				t.Errorf("result == %q, want %q", s, tc.argString)
+			}
+		})
+	}
+}
+
+func TestNewIdentifierAllocator(t *testing.T) {
+	a := newIdentifierAllocator([]string{"taken1", "taken2"})
+	if len(a) != 2 {
+		t.Fatalf("expected 2 items, got %v", len(a))
+	}
+
+	_, ok := a["taken1"]
+	if !ok {
+		t.Errorf("allocator doesn't contain 'taken1': %#v", a)
+	}
+
+	_, ok = a["taken2"]
+	if !ok {
+		t.Errorf("allocator doesn't contain 'taken2': %#v", a)
+	}
+}
+
+func allocatorContainsIdentifiers(a identifierAllocator, ids []string) bool {
+	if len(a) != len(ids) {
+		return false
+	}
+
+	for _, id := range ids {
+		_, ok := a[id]
+		if !ok {
+			return false
+		}
+	}
+
+	return true
+}
+
+func TestIdentifierAllocator_allocateIdentifier(t *testing.T) {
+	a := newIdentifierAllocator([]string{"taken"})
+
+	t2 := a.allocateIdentifier("taken_2")
+	if t2 != "taken_2" {
+		t.Fatalf("expected 'taken_2', got %q", t2)
+	}
+	expected := []string{"taken", "taken_2"}
+	if !allocatorContainsIdentifiers(a, expected) {
+		t.Fatalf("allocator doesn't contain the expected items - allocator: %#v, expected items: %#v", a, expected)
+	}
+
+	t3 := a.allocateIdentifier("taken")
+	if t3 != "taken_3" {
+		t.Fatalf("expected 'taken_3', got %q", t3)
+	}
+	expected = []string{"taken", "taken_2", "taken_3"}
+	if !allocatorContainsIdentifiers(a, expected) {
+		t.Fatalf("allocator doesn't contain the expected items - allocator: %#v, expected items: %#v", a, expected)
+	}
+
+	t4 := a.allocateIdentifier("taken")
+	if t4 != "taken_4" {
+		t.Fatalf("expected 'taken_4', got %q", t4)
+	}
+	expected = []string{"taken", "taken_2", "taken_3", "taken_4"}
+	if !allocatorContainsIdentifiers(a, expected) {
+		t.Fatalf("allocator doesn't contain the expected items - allocator: %#v, expected items: %#v", a, expected)
+	}
+
+	id := a.allocateIdentifier("id")
+	if id != "id" {
+		t.Fatalf("expected 'id', got %q", id)
+	}
+	expected = []string{"taken", "taken_2", "taken_3", "taken_4", "id"}
+	if !allocatorContainsIdentifiers(a, expected) {
+		t.Fatalf("allocator doesn't contain the expected items - allocator: %#v, expected items: %#v", a, expected)
+	}
+}
diff --git a/mockgen/tests/generated_identifier_conflict/README.md b/mockgen/tests/generated_identifier_conflict/README.md
new file mode 100644
index 0000000..ffb5f9f
--- /dev/null
+++ b/mockgen/tests/generated_identifier_conflict/README.md
@@ -0,0 +1,26 @@
+The generated mock methods use some hardcoded variable/receiver names that can
+have conflicts with the argument names that are defined by the code for which
+the mock is generated when using the source generation method.
+
+Example:
+
+```go
+type Example interface {
+	Method(_m, _mr, m, mr int)
+}
+```
+
+```go
+// Method mocks base method
+func (_m *MockExample) Method(_m int, _mr int, m int, mr int) {
+	_m.ctrl.Call(_m, "Method", _m, _mr, m, mr)
+}
+```
+
+In the above example one of the interface method parameters is called `_m`
+but unfortunately the generated receiver name is also called `_m` so the
+mock code won't compile.
+
+The generator has to make sure that generated identifiers (e.g.: the receiver
+names) are always different from the arg names that might come from external
+sources.
diff --git a/mockgen/tests/generated_identifier_conflict/bugreport.go b/mockgen/tests/generated_identifier_conflict/bugreport.go
new file mode 100644
index 0000000..77af43d
--- /dev/null
+++ b/mockgen/tests/generated_identifier_conflict/bugreport.go
@@ -0,0 +1,16 @@
+//go:generate mockgen -destination bugreport_mock.go -package bugreport -source=bugreport.go
+
+package bugreport
+
+type Example interface {
+	// _m and _mr were used by the buggy code: the '_' prefix was there hoping
+	// that no one will use method argument names starting with '_' reducing
+	// the chance of collision with generated identifiers.
+	// m and mr are used by the bugfixed new code, the '_' prefix has been
+	// removed because the new code generator changes the names of the
+	// generated identifiers in case they would collide with identifiers
+	// coming from argument names.
+	Method(_m, _mr, m, mr int)
+
+	VarargMethod(_s, _x, a, ret int, varargs ...int)
+}
diff --git a/mockgen/tests/generated_identifier_conflict/bugreport_mock.go b/mockgen/tests/generated_identifier_conflict/bugreport_mock.go
new file mode 100644
index 0000000..be6de42
--- /dev/null
+++ b/mockgen/tests/generated_identifier_conflict/bugreport_mock.go
@@ -0,0 +1,57 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: bugreport.go
+
+package bugreport
+
+import (
+	gomock "github.com/golang/mock/gomock"
+	reflect "reflect"
+)
+
+// MockExample is a mock of Example interface
+type MockExample struct {
+	ctrl     *gomock.Controller
+	recorder *MockExampleMockRecorder
+}
+
+// MockExampleMockRecorder is the mock recorder for MockExample
+type MockExampleMockRecorder struct {
+	mock *MockExample
+}
+
+// NewMockExample creates a new mock instance
+func NewMockExample(ctrl *gomock.Controller) *MockExample {
+	mock := &MockExample{ctrl: ctrl}
+	mock.recorder = &MockExampleMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use
+func (m *MockExample) EXPECT() *MockExampleMockRecorder {
+	return m.recorder
+}
+
+// Method mocks base method
+func (m_2 *MockExample) Method(_m, _mr, m, mr int) {
+	m_2.ctrl.Call(m_2, "Method", _m, _mr, m, mr)
+}
+
+// Method indicates an expected call of Method
+func (mr_2 *MockExampleMockRecorder) Method(_m, _mr, m, mr interface{}) *gomock.Call {
+	return mr_2.mock.ctrl.RecordCallWithMethodType(mr_2.mock, "Method", reflect.TypeOf((*MockExample)(nil).Method), _m, _mr, m, mr)
+}
+
+// VarargMethod mocks base method
+func (m *MockExample) VarargMethod(_s, _x, a, ret int, varargs ...int) {
+	varargs_2 := []interface{}{_s, _x, a, ret}
+	for _, a_2 := range varargs {
+		varargs_2 = append(varargs_2, a_2)
+	}
+	m.ctrl.Call(m, "VarargMethod", varargs_2...)
+}
+
+// VarargMethod indicates an expected call of VarargMethod
+func (mr *MockExampleMockRecorder) VarargMethod(_s, _x, a, ret interface{}, varargs ...interface{}) *gomock.Call {
+	varargs_2 := append([]interface{}{_s, _x, a, ret}, varargs...)
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VarargMethod", reflect.TypeOf((*MockExample)(nil).VarargMethod), varargs_2...)
+}
diff --git a/mockgen/tests/generated_identifier_conflict/bugreport_test.go b/mockgen/tests/generated_identifier_conflict/bugreport_test.go
new file mode 100644
index 0000000..3ca9807
--- /dev/null
+++ b/mockgen/tests/generated_identifier_conflict/bugreport_test.go
@@ -0,0 +1,26 @@
+package bugreport
+
+import (
+	"github.com/golang/mock/gomock"
+	"testing"
+)
+
+func TestExample_Method(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	m := NewMockExample(ctrl)
+	m.EXPECT().Method(1, 2, 3, 4)
+
+	m.Method(1, 2, 3, 4)
+
+	ctrl.Finish()
+}
+
+func TestExample_VarargMethod(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	m := NewMockExample(ctrl)
+	m.EXPECT().VarargMethod(1, 2, 3, 4, 6, 7)
+
+	m.VarargMethod(1, 2, 3, 4, 6, 7)
+
+	ctrl.Finish()
+}
diff --git a/mockgen/tests/unexported_method/bugreport_mock.go b/mockgen/tests/unexported_method/bugreport_mock.go
index f1a16d8..a359b2a 100644
--- a/mockgen/tests/unexported_method/bugreport_mock.go
+++ b/mockgen/tests/unexported_method/bugreport_mock.go
@@ -27,18 +27,18 @@ func NewMockExample(ctrl *gomock.Controller) *MockExample {
 }
 
 // EXPECT returns an object that allows the caller to indicate expected use
-func (_m *MockExample) EXPECT() *MockExampleMockRecorder {
-	return _m.recorder
+func (m *MockExample) EXPECT() *MockExampleMockRecorder {
+	return m.recorder
 }
 
 // someMethod mocks base method
-func (_m *MockExample) someMethod(_param0 string) string {
-	ret := _m.ctrl.Call(_m, "someMethod", _param0)
+func (m *MockExample) someMethod(arg0 string) string {
+	ret := m.ctrl.Call(m, "someMethod", arg0)
 	ret0, _ := ret[0].(string)
 	return ret0
 }
 
 // someMethod indicates an expected call of someMethod
-func (_mr *MockExampleMockRecorder) someMethod(arg0 interface{}) *gomock.Call {
-	return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "someMethod", reflect.TypeOf((*MockExample)(nil).someMethod), arg0)
+func (mr *MockExampleMockRecorder) someMethod(arg0 interface{}) *gomock.Call {
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "someMethod", reflect.TypeOf((*MockExample)(nil).someMethod), arg0)
 }