Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

feat: support embedded generic interfaces #669

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion mockgen/generic_go118.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package main

import (
"fmt"
"go/ast"
"strings"

Expand All @@ -24,7 +25,7 @@ func getTypeSpecTypeParams(ts *ast.TypeSpec) []*ast.Field {
return ts.TypeParams.List
}

func (p *fileParser) parseGenericType(pkg string, typ ast.Expr, tps map[string]bool) (model.Type, error) {
func (p *fileParser) parseGenericType(pkg string, typ ast.Expr, tps map[string]model.Type) (model.Type, error) {
switch v := typ.(type) {
case *ast.IndexExpr:
m, err := p.parseType(pkg, v.X, tps)
Expand Down Expand Up @@ -86,3 +87,30 @@ func getIdentTypeParams(decl interface{}) string {
sb.WriteString("]")
return sb.String()
}

func (p *fileParser) parseGenericMethod(field *ast.Field, it *namedInterface, iface *model.Interface, pkg string, tps map[string]model.Type) ([]*model.Method, error) {
var indices []ast.Expr
var typ ast.Expr
switch v := field.Type.(type) {
case *ast.IndexExpr:
indices = []ast.Expr{v.Index}
typ = v.X
case *ast.IndexListExpr:
indices = v.Indices
typ = v.X
default:
return nil, fmt.Errorf("don't know how to mock method of type %T", field.Type)
}

nf := &ast.Field{
Doc: field.Comment,
Names: field.Names,
Type: typ,
Tag: field.Tag,
Comment: field.Comment,
}

it.embeddedInstTypeParams = indices

return p.parseMethod(nf, it, iface, pkg, tps)
}
7 changes: 6 additions & 1 deletion mockgen/generic_notgo118.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package main

import (
"fmt"
"go/ast"

"github.com/golang/mock/mockgen/model"
Expand All @@ -27,10 +28,14 @@ func getTypeSpecTypeParams(ts *ast.TypeSpec) []*ast.Field {
return nil
}

func (p *fileParser) parseGenericType(pkg string, typ ast.Expr, tps map[string]bool) (model.Type, error) {
func (p *fileParser) parseGenericType(pkg string, typ ast.Expr, tps map[string]model.Type) (model.Type, error) {
return nil, nil
}

func getIdentTypeParams(decl interface{}) string {
return ""
}

func (p *fileParser) parseGenericMethod(field *ast.Field, it *namedInterface, iface *model.Interface, pkg string, tps map[string]model.Type) ([]*model.Method, error) {
return nil, fmt.Errorf("don't know how to mock method of type %T", field.Type)
}
49 changes: 49 additions & 0 deletions mockgen/internal/tests/generics/external.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package generics

import (
"context"

"github.com/golang/mock/mockgen/internal/tests/generics/other"
"golang.org/x/exp/constraints"
)
Expand All @@ -19,3 +21,50 @@ type ExternalConstraint[I constraints.Integer, F constraints.Float] interface {
Nine(Iface[I])
Ten(*I)
}

type EmbeddingIface[T constraints.Integer, R constraints.Float] interface {
other.Twenty[T, StructType, R, other.Five]
TwentyTwo[StructType]
other.TwentyThree[TwentyTwo[R], TwentyTwo[T]]
TwentyFour[other.StructType]
Foo() error
ExternalConstraint[T, R]
}

type TwentyOne[T any] interface {
TwentyOne() T
}

type TwentyFour[T other.StructType] interface {
TwentyFour() T
}

type Clonable[T any] interface {
Clone() T
}

type Finder[T Clonable[T]] interface {
Find(ctx context.Context) ([]T, error)
}

type UpdateNotifier[T any] interface {
NotifyC(ctx context.Context) <-chan []T

Refresh(ctx context.Context)
}

type EmbeddedW[W StructType] interface {
EmbeddedY[W]
}

type EmbeddedX[X StructType] interface {
EmbeddedY[X]
}

type EmbeddedY[Y StructType] interface {
EmbeddedZ[Y]
}

type EmbeddedZ[Z any] interface {
EmbeddedZ(Z)
}
5 changes: 5 additions & 0 deletions mockgen/internal/tests/generics/generics.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Bar[T any, R any] interface {
Seventeen() (*Foo[other.Three, other.Four], error)
Eighteen() (Iface[*other.Five], error)
Nineteen() AliasType
other.Twenty[any, any, any, *other.Four]
}

type Foo[T any, R any] struct{}
Expand All @@ -38,3 +39,7 @@ type StructType struct{}
type StructType2 struct{}

type AliasType Baz[other.Three]

type TwentyTwo[T any] interface {
TwentyTwo() T
}
10 changes: 10 additions & 0 deletions mockgen/internal/tests/generics/other/other.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@ type Three struct{}
type Four struct{}

type Five interface{}

type Twenty[R, S, T any, Z any] interface {
Twenty(S, R) (T, Z)
}

type TwentyThree[U, V any] interface {
TwentyThree(U, V) StructType
}

type StructType struct{}
12 changes: 12 additions & 0 deletions mockgen/internal/tests/generics/source/assert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package source

import (
"testing"

"github.com/golang/mock/mockgen/internal/tests/generics"
)

func TestAssert(t *testing.T) {
var x MockEmbeddingIface[int, float64]
var _ generics.EmbeddingIface[int, float64] = &x
}
Loading