Skip to content

Commit

Permalink
add support for generics for source mode (golang#640)
Browse files Browse the repository at this point in the history
Updates: golang#621
  • Loading branch information
codyoss authored May 12, 2022
1 parent d8fb947 commit 73266f9
Show file tree
Hide file tree
Showing 15 changed files with 929 additions and 81 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,16 @@ jobs:
./ci/test.sh
./ci/check_panic_handling.sh
- name: Run Go tests
- name: Run Go tests all
if: ${{ startsWith(matrix.go-version, '1.18') }}
run: |
for i in $(find $PWD -name go.mod); do
pushd $(dirname $i)
go test ./...
popd
done
- name: Run Go tests some
if: ${{ startsWith(matrix.go-version, '1.18') == false }}
run: |
go test ./...
88 changes: 88 additions & 0 deletions mockgen/generic_go118.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build go1.18
// +build go1.18

package main

import (
"go/ast"
"strings"

"github.com/golang/mock/mockgen/model"
)

func getTypeSpecTypeParams(ts *ast.TypeSpec) []*ast.Field {
if ts == nil || ts.TypeParams == nil {
return nil
}
return ts.TypeParams.List
}

func (p *fileParser) parseGenericType(pkg string, typ ast.Expr, tps map[string]bool) (model.Type, error) {
switch v := typ.(type) {
case *ast.IndexExpr:
m, err := p.parseType(pkg, v.X, tps)
if err != nil {
return nil, err
}
nm, ok := m.(*model.NamedType)
if !ok {
return m, nil
}
t, err := p.parseType(pkg, v.Index, tps)
if err != nil {
return nil, err
}
nm.TypeParams = &model.TypeParametersType{TypeParameters: []model.Type{t}}
return m, nil
case *ast.IndexListExpr:
m, err := p.parseType(pkg, v.X, tps)
if err != nil {
return nil, err
}
nm, ok := m.(*model.NamedType)
if !ok {
return m, nil
}
var ts []model.Type
for _, expr := range v.Indices {
t, err := p.parseType(pkg, expr, tps)
if err != nil {
return nil, err
}
ts = append(ts, t)
}
nm.TypeParams = &model.TypeParametersType{TypeParameters: ts}
return m, nil
}
return nil, nil
}

func getIdentTypeParams(decl interface{}) string {
if decl == nil {
return ""
}
ts, ok := decl.(*ast.TypeSpec)
if !ok {
return ""
}
if ts.TypeParams == nil || len(ts.TypeParams.List) == 0 {
return ""
}
var sb strings.Builder
sb.WriteString("[")
for i, v := range ts.TypeParams.List {
if i != 0 {
sb.WriteString(", ")
}
sb.WriteString(v.Names[0].Name)
}
sb.WriteString("]")
return sb.String()
}
36 changes: 36 additions & 0 deletions mockgen/generic_notgo118.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build !go1.18
// +build !go1.18

package main

import (
"go/ast"

"github.com/golang/mock/mockgen/model"
)

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) {
return nil, nil
}

func getIdentTypeParams(decl interface{}) string {
return ""
}
21 changes: 21 additions & 0 deletions mockgen/internal/tests/generics/external.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package generics

import (
"github.com/golang/mock/mockgen/internal/tests/generics/other"
"golang.org/x/exp/constraints"
)

//go:generate mockgen --source=external.go --destination=source/mock_external_test.go --package source

type ExternalConstraint[I constraints.Integer, F constraints.Float] interface {
One(string) string
Two(I) string
Three(I) F
Four(I) Foo[I, F]
Five(I) Baz[F]
Six(I) *Baz[F]
Seven(I) other.One[I]
Eight(F) other.Two[I, F]
Nine(Iface[I])
Ten(*I)
}
40 changes: 40 additions & 0 deletions mockgen/internal/tests/generics/generics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package generics

import "github.com/golang/mock/mockgen/internal/tests/generics/other"

//go:generate mockgen --source=generics.go --destination=source/mock_generics_test.go --package source
////go:generate mockgen --destination=reflect/mock_test.go --package reflect . Bar,Bar2

type Bar[T any, R any] interface {
One(string) string
Two(T) string
Three(T) R
Four(T) Foo[T, R]
Five(T) Baz[T]
Six(T) *Baz[T]
Seven(T) other.One[T]
Eight(T) other.Two[T, R]
Nine(Iface[T])
Ten(*T)
Eleven() (*other.One[T], error)
Twelve() (*other.Two[T, R], error)
Thirteen() (Baz[StructType], error)
Fourteen() (*Foo[StructType, StructType2], error)
Fifteen() (Iface[StructType], error)
Sixteen() (Baz[other.Three], error)
Seventeen() (*Foo[other.Three, other.Four], error)
Eighteen() (Iface[*other.Five], error)
Nineteen() AliasType
}

type Foo[T any, R any] struct{}

type Baz[T any] struct{}

type Iface[T any] interface{}

type StructType struct{}

type StructType2 struct{}

type AliasType Baz[other.Three]
10 changes: 10 additions & 0 deletions mockgen/internal/tests/generics/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module github.com/golang/mock/mockgen/internal/tests/generics

go 1.18

require (
github.com/golang/mock v1.6.0
golang.org/x/exp v0.0.0-20220428152302-39d4317da171
)

replace github.com/golang/mock => ../../../..
26 changes: 26 additions & 0 deletions mockgen/internal/tests/generics/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20220428152302-39d4317da171 h1:TfdoLivD44QwvssI9Sv1xwa5DcL5XQr4au4sZ2F2NV4=
golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
11 changes: 11 additions & 0 deletions mockgen/internal/tests/generics/other/other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package other

type One[T any] struct{}

type Two[T any, R any] struct{}

type Three struct{}

type Four struct{}

type Five interface{}
Loading

0 comments on commit 73266f9

Please sign in to comment.