Skip to content

Commit

Permalink
Genrics support: rename and comment methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Cruickshank committed Apr 25, 2022
1 parent a129a32 commit aaee69e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
34 changes: 26 additions & 8 deletions pkg/generator.go
Expand Up @@ -103,7 +103,12 @@ func (g *Generator) addImportsFromTuple(ctx context.Context, list *types.Tuple)
}
}

func (g *Generator) addPackageScopedType(ctx context.Context, o *types.TypeName) string {
// getPackageScopedType returns the appropriate string representation for the
// object TypeName. The string may either be the unqualified name (in the case
// the mock will live in the same package as the interface being mocked, e.g.
// `Foo`) or the package pathname (in the case the type lives in a package
// external to the mock, e.g. `packagename.Foo`).
func (g *Generator) getPackageScopedType(ctx context.Context, o *types.TypeName) string {
if o.Pkg() == nil || o.Pkg().Name() == "main" || (!g.KeepTree && g.InPackage && o.Pkg() == g.iface.Pkg) {
return o.Name()
}
Expand Down Expand Up @@ -251,7 +256,17 @@ func (g *Generator) mockName() string {
return g.maybeMakeNameExported(g.iface.Name, g.Exported)
}

func (g *Generator) typeConstraints(ctx context.Context) string {
// getTypeConstraintString returns type constraint string for a given interface.
// For instance, a method using this constraint:
//
// func Foo[T Stringer](s []T) (ret []string) {
//
// }
//
// The constraint returned will be "[T Stringer]"
//
// https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#type-parameters
func (g *Generator) getTypeConstraintString(ctx context.Context) string {
tp := g.iface.NamedType.TypeParams()
if tp == nil || tp.Len() == 0 {
return ""
Expand All @@ -264,7 +279,10 @@ func (g *Generator) typeConstraints(ctx context.Context) string {
return fmt.Sprintf("[%s]", strings.Join(qualifiedParams, ", "))
}

func (g *Generator) typeParams() string {
// getInstantiatedTypeString returns the "instantiated" type names for a given
// constraint list. For instance, if your interface has the constraints
// `[S Stringer, I int, C Comparable]`, this method would return: `[S, I, C]`
func (g *Generator) getInstantiatedTypeString() string {
tp := g.iface.NamedType.TypeParams()
if tp == nil || tp.Len() == 0 {
return ""
Expand Down Expand Up @@ -380,7 +398,7 @@ type namer interface {
func (g *Generator) renderType(ctx context.Context, typ types.Type) string {
switch t := typ.(type) {
case *types.Named:
name := g.addPackageScopedType(ctx, t.Obj())
name := g.getPackageScopedType(ctx, t.Obj())
if t.TypeArgs() == nil || t.TypeArgs().Len() == 0 {
return name
}
Expand All @@ -394,7 +412,7 @@ func (g *Generator) renderType(ctx context.Context, typ types.Type) string {
if t.Constraint() != nil {
return t.Obj().Name()
}
return g.addPackageScopedType(ctx, t.Obj())
return g.getPackageScopedType(ctx, t.Obj())
case *types.Basic:
return t.Name()
case *types.Pointer:
Expand Down Expand Up @@ -584,7 +602,7 @@ func (g *Generator) Generate(ctx context.Context) error {
)

g.printf(
"type %s%s struct {\n\tmock.Mock\n}\n\n", g.mockName(), g.typeConstraints(ctx),
"type %s%s struct {\n\tmock.Mock\n}\n\n", g.mockName(), g.getTypeConstraintString(ctx),
)

if g.WithExpecter {
Expand Down Expand Up @@ -613,7 +631,7 @@ func (g *Generator) Generate(ctx context.Context) error {
)
}
g.printf(
"func (_m *%s%s) %s(%s) ", g.mockName(), g.typeParams(ctx), fname,
"func (_m *%s%s) %s(%s) ", g.mockName(), g.getInstantiatedTypeString(), fname,
strings.Join(params.Params, ", "),
)

Expand Down Expand Up @@ -800,7 +818,7 @@ func %[1]s%[3]s(t testing.TB) *%[2]s%[4]s {
mockName := g.mockName()
constructorName := g.maybeMakeNameExported("new"+g.makeNameExported(mockName), ast.IsExported(mockName))

g.printf(constructor, constructorName, mockName, g.typeConstraints(ctx), g.typeParams())
g.printf(constructor, constructorName, mockName, g.getTypeConstraintString(ctx), g.getInstantiatedTypeString())
}

// generateCalled returns the Mock.Called invocation string and, if necessary, prints the
Expand Down
6 changes: 4 additions & 2 deletions pkg/generator_test.go
Expand Up @@ -1866,12 +1866,13 @@ func (_m *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TG
return r0
}
// NewRequesterGenerics creates a new instance of RequesterGenerics. It also registers a cleanup function to assert the mocks expectations.
// NewRequesterGenerics creates a new instance of RequesterGenerics. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf test.GetInt, TExternalIntf io.Writer, TGenIntf test.GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface {
~int | test.GenericType[int, test.GetInt]
comparable
}](t testing.TB) *RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] {
mock := &RequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
Expand Down Expand Up @@ -1947,12 +1948,13 @@ func (_m *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf
return r0
}
// NewMockRequesterGenerics creates a new instance of MockRequesterGenerics. It also registers a cleanup function to assert the mocks expectations.
// NewMockRequesterGenerics creates a new instance of MockRequesterGenerics. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockRequesterGenerics[TAny interface{}, TComparable comparable, TSigned constraints.Signed, TIntf GetInt, TExternalIntf io.Writer, TGenIntf GetGeneric[TSigned], TInlineType interface{ ~int | ~uint }, TInlineTypeGeneric interface {
~int | GenericType[int, GetInt]
comparable
}](t testing.TB) *MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric] {
mock := &MockRequesterGenerics[TAny, TComparable, TSigned, TIntf, TExternalIntf, TGenIntf, TInlineType, TInlineTypeGeneric]{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
Expand Down

0 comments on commit aaee69e

Please sign in to comment.