uber-go / mock

GoMock is a mocking framework for the Go programming language.
Apache License 2.0
1.81k stars 103 forks source link

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

Open TomerSalton opened 1 month ago

TomerSalton commented 1 month ago

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](https://github.com/uber-go/mock/blob/893ee9cb6b098575f0bad39eaf4d02eeec917633/mockgen/mockgen.go#L751) ```go 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 } ```