uber-go/mock

Conflict of argument name and imported package name results in compilation error

TomerSalton opened this issue · 0 comments

Actual behavior
Given a method of an interface,
if one of the return values is of a type that comes from different package,
and if the name of one of the arguments conflicts with this package name,
then a compilation error happens.

Expected behavior
Such arg names should be sanitized - not only if they're empty ( or _), but also if they conflicts with such package name.

To Reproduce

Define interface

type Client interface {
        // `file` is our package, that is defined outside of the interface's package
	Upload(ctx context.Context, file *file.Handle) (*file.Header, error)
}

Then, when generating, this is what happens:

// Upload mocks base method.
func (m *MockClient) Upload(ctx context.Context, file *file.Handle) (*file.Header, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "Upload", ctx, file)
        // compilation error: go treats `Header` as a property of the argument named file,
        // instead of a struct defined in the `file` package
	ret0, _ := ret[0].(*file.Header)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

Additional Information

I have already crafted a small PR with the following fix.
I will be happy to contribute if you guys find it useful.

fix getArgNames

reference to the current function

func (g *generator) getArgNames(m *model.Method, in bool) []string {
	var params []*model.Parameter

	forbidden := map[string]bool{}
	for _, v := range g.packageMap {
		forbidden[v] = true
	}

	if in {
		params = m.In
	} else {
		params = m.Out
	}
	argNames := make([]string, len(params))
	for i, p := range params {
		argNames[i] = sanitizeName(p.Name, forbidden, i)
	}
	if m.Variadic != nil && in {
		name := sanitizeName(m.Variadic.Name, forbidden, len(params))
		argNames = append(argNames, name)
	}
	return argNames
}

...

func sanitizeName(name string, forbidden map[string]bool, i int) string {
	if name == "" || name == "_" || forbidden[name] {
		return fmt.Sprintf("arg%d", i)
	}
	return name
}