add support for generics for source mode (#640)

Updates: #621
This commit is contained in:
Cody Oss 2022-05-11 21:06:13 -06:00 коммит произвёл GitHub
Родитель d8fb94763b
Коммит 73266f9366
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
15 изменённых файлов: 929 добавлений и 81 удалений

8
.github/workflows/test.yaml поставляемый
Просмотреть файл

@ -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
mockgen/generic_go118.go Normal file
Просмотреть файл

@ -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()
}

Просмотреть файл

@ -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 ""
}

Просмотреть файл

@ -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)
}

Просмотреть файл

@ -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]

Просмотреть файл

@ -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 => ../../../..

Просмотреть файл

@ -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=

Просмотреть файл

@ -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{}

Просмотреть файл

@ -0,0 +1,173 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: external.go
// Package source is a generated GoMock package.
package source
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
generics "github.com/golang/mock/mockgen/internal/tests/generics"
other "github.com/golang/mock/mockgen/internal/tests/generics/other"
constraints "golang.org/x/exp/constraints"
)
// MockExternalConstraint is a mock of ExternalConstraint interface.
type MockExternalConstraint[I constraints.Integer, F constraints.Float] struct {
ctrl *gomock.Controller
recorder *MockExternalConstraintMockRecorder[I, F]
}
// MockExternalConstraintMockRecorder is the mock recorder for MockExternalConstraint.
type MockExternalConstraintMockRecorder[I constraints.Integer, F constraints.Float] struct {
mock *MockExternalConstraint[I, F]
}
// NewMockExternalConstraint creates a new mock instance.
func NewMockExternalConstraint[I constraints.Integer, F constraints.Float](ctrl *gomock.Controller) *MockExternalConstraint[I, F] {
mock := &MockExternalConstraint[I, F]{ctrl: ctrl}
mock.recorder = &MockExternalConstraintMockRecorder[I, F]{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockExternalConstraint[I, F]) EXPECT() *MockExternalConstraintMockRecorder[I, F] {
return m.recorder
}
// Eight mocks base method.
func (m *MockExternalConstraint[I, F]) Eight(arg0 F) other.Two[I, F] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Eight", arg0)
ret0, _ := ret[0].(other.Two[I, F])
return ret0
}
// Eight indicates an expected call of Eight.
func (mr *MockExternalConstraintMockRecorder[I, F]) Eight(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Eight", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Eight), arg0)
}
// Five mocks base method.
func (m *MockExternalConstraint[I, F]) Five(arg0 I) generics.Baz[F] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Five", arg0)
ret0, _ := ret[0].(generics.Baz[F])
return ret0
}
// Five indicates an expected call of Five.
func (mr *MockExternalConstraintMockRecorder[I, F]) Five(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Five", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Five), arg0)
}
// Four mocks base method.
func (m *MockExternalConstraint[I, F]) Four(arg0 I) generics.Foo[I, F] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Four", arg0)
ret0, _ := ret[0].(generics.Foo[I, F])
return ret0
}
// Four indicates an expected call of Four.
func (mr *MockExternalConstraintMockRecorder[I, F]) Four(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Four", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Four), arg0)
}
// Nine mocks base method.
func (m *MockExternalConstraint[I, F]) Nine(arg0 generics.Iface[I]) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Nine", arg0)
}
// Nine indicates an expected call of Nine.
func (mr *MockExternalConstraintMockRecorder[I, F]) Nine(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Nine", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Nine), arg0)
}
// One mocks base method.
func (m *MockExternalConstraint[I, F]) One(arg0 string) string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "One", arg0)
ret0, _ := ret[0].(string)
return ret0
}
// One indicates an expected call of One.
func (mr *MockExternalConstraintMockRecorder[I, F]) One(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "One", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).One), arg0)
}
// Seven mocks base method.
func (m *MockExternalConstraint[I, F]) Seven(arg0 I) other.One[I] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Seven", arg0)
ret0, _ := ret[0].(other.One[I])
return ret0
}
// Seven indicates an expected call of Seven.
func (mr *MockExternalConstraintMockRecorder[I, F]) Seven(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Seven", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Seven), arg0)
}
// Six mocks base method.
func (m *MockExternalConstraint[I, F]) Six(arg0 I) *generics.Baz[F] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Six", arg0)
ret0, _ := ret[0].(*generics.Baz[F])
return ret0
}
// Six indicates an expected call of Six.
func (mr *MockExternalConstraintMockRecorder[I, F]) Six(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Six", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Six), arg0)
}
// Ten mocks base method.
func (m *MockExternalConstraint[I, F]) Ten(arg0 *I) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Ten", arg0)
}
// Ten indicates an expected call of Ten.
func (mr *MockExternalConstraintMockRecorder[I, F]) Ten(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ten", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Ten), arg0)
}
// Three mocks base method.
func (m *MockExternalConstraint[I, F]) Three(arg0 I) F {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Three", arg0)
ret0, _ := ret[0].(F)
return ret0
}
// Three indicates an expected call of Three.
func (mr *MockExternalConstraintMockRecorder[I, F]) Three(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Three", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Three), arg0)
}
// Two mocks base method.
func (m *MockExternalConstraint[I, F]) Two(arg0 I) string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Two", arg0)
ret0, _ := ret[0].(string)
return ret0
}
// Two indicates an expected call of Two.
func (mr *MockExternalConstraintMockRecorder[I, F]) Two(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Two", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Two), arg0)
}

Просмотреть файл

@ -0,0 +1,329 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: generics.go
// Package source is a generated GoMock package.
package source
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
generics "github.com/golang/mock/mockgen/internal/tests/generics"
other "github.com/golang/mock/mockgen/internal/tests/generics/other"
)
// MockBar is a mock of Bar interface.
type MockBar[T any, R any] struct {
ctrl *gomock.Controller
recorder *MockBarMockRecorder[T, R]
}
// MockBarMockRecorder is the mock recorder for MockBar.
type MockBarMockRecorder[T any, R any] struct {
mock *MockBar[T, R]
}
// NewMockBar creates a new mock instance.
func NewMockBar[T any, R any](ctrl *gomock.Controller) *MockBar[T, R] {
mock := &MockBar[T, R]{ctrl: ctrl}
mock.recorder = &MockBarMockRecorder[T, R]{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockBar[T, R]) EXPECT() *MockBarMockRecorder[T, R] {
return m.recorder
}
// Eight mocks base method.
func (m *MockBar[T, R]) Eight(arg0 T) other.Two[T, R] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Eight", arg0)
ret0, _ := ret[0].(other.Two[T, R])
return ret0
}
// Eight indicates an expected call of Eight.
func (mr *MockBarMockRecorder[T, R]) Eight(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Eight", reflect.TypeOf((*MockBar[T, R])(nil).Eight), arg0)
}
// Eighteen mocks base method.
func (m *MockBar[T, R]) Eighteen() (generics.Iface[*other.Five], error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Eighteen")
ret0, _ := ret[0].(generics.Iface[*other.Five])
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Eighteen indicates an expected call of Eighteen.
func (mr *MockBarMockRecorder[T, R]) Eighteen() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Eighteen", reflect.TypeOf((*MockBar[T, R])(nil).Eighteen))
}
// Eleven mocks base method.
func (m *MockBar[T, R]) Eleven() (*other.One[T], error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Eleven")
ret0, _ := ret[0].(*other.One[T])
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Eleven indicates an expected call of Eleven.
func (mr *MockBarMockRecorder[T, R]) Eleven() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Eleven", reflect.TypeOf((*MockBar[T, R])(nil).Eleven))
}
// Fifteen mocks base method.
func (m *MockBar[T, R]) Fifteen() (generics.Iface[generics.StructType], error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Fifteen")
ret0, _ := ret[0].(generics.Iface[generics.StructType])
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Fifteen indicates an expected call of Fifteen.
func (mr *MockBarMockRecorder[T, R]) Fifteen() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fifteen", reflect.TypeOf((*MockBar[T, R])(nil).Fifteen))
}
// Five mocks base method.
func (m *MockBar[T, R]) Five(arg0 T) generics.Baz[T] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Five", arg0)
ret0, _ := ret[0].(generics.Baz[T])
return ret0
}
// Five indicates an expected call of Five.
func (mr *MockBarMockRecorder[T, R]) Five(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Five", reflect.TypeOf((*MockBar[T, R])(nil).Five), arg0)
}
// Four mocks base method.
func (m *MockBar[T, R]) Four(arg0 T) generics.Foo[T, R] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Four", arg0)
ret0, _ := ret[0].(generics.Foo[T, R])
return ret0
}
// Four indicates an expected call of Four.
func (mr *MockBarMockRecorder[T, R]) Four(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Four", reflect.TypeOf((*MockBar[T, R])(nil).Four), arg0)
}
// Fourteen mocks base method.
func (m *MockBar[T, R]) Fourteen() (*generics.Foo[generics.StructType, generics.StructType2], error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Fourteen")
ret0, _ := ret[0].(*generics.Foo[generics.StructType, generics.StructType2])
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Fourteen indicates an expected call of Fourteen.
func (mr *MockBarMockRecorder[T, R]) Fourteen() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fourteen", reflect.TypeOf((*MockBar[T, R])(nil).Fourteen))
}
// Nine mocks base method.
func (m *MockBar[T, R]) Nine(arg0 generics.Iface[T]) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Nine", arg0)
}
// Nine indicates an expected call of Nine.
func (mr *MockBarMockRecorder[T, R]) Nine(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Nine", reflect.TypeOf((*MockBar[T, R])(nil).Nine), arg0)
}
// Nineteen mocks base method.
func (m *MockBar[T, R]) Nineteen() generics.AliasType {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Nineteen")
ret0, _ := ret[0].(generics.AliasType)
return ret0
}
// Nineteen indicates an expected call of Nineteen.
func (mr *MockBarMockRecorder[T, R]) Nineteen() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Nineteen", reflect.TypeOf((*MockBar[T, R])(nil).Nineteen))
}
// One mocks base method.
func (m *MockBar[T, R]) One(arg0 string) string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "One", arg0)
ret0, _ := ret[0].(string)
return ret0
}
// One indicates an expected call of One.
func (mr *MockBarMockRecorder[T, R]) One(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "One", reflect.TypeOf((*MockBar[T, R])(nil).One), arg0)
}
// Seven mocks base method.
func (m *MockBar[T, R]) Seven(arg0 T) other.One[T] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Seven", arg0)
ret0, _ := ret[0].(other.One[T])
return ret0
}
// Seven indicates an expected call of Seven.
func (mr *MockBarMockRecorder[T, R]) Seven(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Seven", reflect.TypeOf((*MockBar[T, R])(nil).Seven), arg0)
}
// Seventeen mocks base method.
func (m *MockBar[T, R]) Seventeen() (*generics.Foo[other.Three, other.Four], error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Seventeen")
ret0, _ := ret[0].(*generics.Foo[other.Three, other.Four])
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Seventeen indicates an expected call of Seventeen.
func (mr *MockBarMockRecorder[T, R]) Seventeen() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Seventeen", reflect.TypeOf((*MockBar[T, R])(nil).Seventeen))
}
// Six mocks base method.
func (m *MockBar[T, R]) Six(arg0 T) *generics.Baz[T] {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Six", arg0)
ret0, _ := ret[0].(*generics.Baz[T])
return ret0
}
// Six indicates an expected call of Six.
func (mr *MockBarMockRecorder[T, R]) Six(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Six", reflect.TypeOf((*MockBar[T, R])(nil).Six), arg0)
}
// Sixteen mocks base method.
func (m *MockBar[T, R]) Sixteen() (generics.Baz[other.Three], error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Sixteen")
ret0, _ := ret[0].(generics.Baz[other.Three])
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Sixteen indicates an expected call of Sixteen.
func (mr *MockBarMockRecorder[T, R]) Sixteen() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sixteen", reflect.TypeOf((*MockBar[T, R])(nil).Sixteen))
}
// Ten mocks base method.
func (m *MockBar[T, R]) Ten(arg0 *T) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Ten", arg0)
}
// Ten indicates an expected call of Ten.
func (mr *MockBarMockRecorder[T, R]) Ten(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ten", reflect.TypeOf((*MockBar[T, R])(nil).Ten), arg0)
}
// Thirteen mocks base method.
func (m *MockBar[T, R]) Thirteen() (generics.Baz[generics.StructType], error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Thirteen")
ret0, _ := ret[0].(generics.Baz[generics.StructType])
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Thirteen indicates an expected call of Thirteen.
func (mr *MockBarMockRecorder[T, R]) Thirteen() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Thirteen", reflect.TypeOf((*MockBar[T, R])(nil).Thirteen))
}
// Three mocks base method.
func (m *MockBar[T, R]) Three(arg0 T) R {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Three", arg0)
ret0, _ := ret[0].(R)
return ret0
}
// Three indicates an expected call of Three.
func (mr *MockBarMockRecorder[T, R]) Three(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Three", reflect.TypeOf((*MockBar[T, R])(nil).Three), arg0)
}
// Twelve mocks base method.
func (m *MockBar[T, R]) Twelve() (*other.Two[T, R], error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Twelve")
ret0, _ := ret[0].(*other.Two[T, R])
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Twelve indicates an expected call of Twelve.
func (mr *MockBarMockRecorder[T, R]) Twelve() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Twelve", reflect.TypeOf((*MockBar[T, R])(nil).Twelve))
}
// Two mocks base method.
func (m *MockBar[T, R]) Two(arg0 T) string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Two", arg0)
ret0, _ := ret[0].(string)
return ret0
}
// Two indicates an expected call of Two.
func (mr *MockBarMockRecorder[T, R]) Two(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Two", reflect.TypeOf((*MockBar[T, R])(nil).Two), arg0)
}
// MockIface is a mock of Iface interface.
type MockIface[T any] struct {
ctrl *gomock.Controller
recorder *MockIfaceMockRecorder[T]
}
// MockIfaceMockRecorder is the mock recorder for MockIface.
type MockIfaceMockRecorder[T any] struct {
mock *MockIface[T]
}
// NewMockIface creates a new mock instance.
func NewMockIface[T any](ctrl *gomock.Controller) *MockIface[T] {
mock := &MockIface[T]{ctrl: ctrl}
mock.recorder = &MockIfaceMockRecorder[T]{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockIface[T]) EXPECT() *MockIfaceMockRecorder[T] {
return m.recorder
}

Просмотреть файл

@ -371,32 +371,58 @@ func (g *generator) mockName(typeName string) string {
return "Mock" + typeName
}
// formattedTypeParams returns a long and short form of type param info used for
// printing. If analyzing a interface with type param [I any, O any] the result
// will be:
// "[I any, O any]", "[I, O]"
func (g *generator) formattedTypeParams(it *model.Interface, pkgOverride string) (string, string) {
if len(it.TypeParams) == 0 {
return "", ""
}
var long, short strings.Builder
long.WriteString("[")
short.WriteString("[")
for i, v := range it.TypeParams {
if i != 0 {
long.WriteString(", ")
short.WriteString(", ")
}
long.WriteString(v.Name)
short.WriteString(v.Name)
long.WriteString(fmt.Sprintf(" %s", v.Type.String(g.packageMap, pkgOverride)))
}
long.WriteString("]")
short.WriteString("]")
return long.String(), short.String()
}
func (g *generator) GenerateMockInterface(intf *model.Interface, outputPackagePath string) error {
mockType := g.mockName(intf.Name)
longTp, shortTp := g.formattedTypeParams(intf, outputPackagePath)
g.p("")
g.p("// %v is a mock of %v interface.", mockType, intf.Name)
g.p("type %v struct {", mockType)
g.p("type %v%v struct {", mockType, longTp)
g.in()
g.p("ctrl *gomock.Controller")
g.p("recorder *%vMockRecorder", mockType)
g.p("recorder *%vMockRecorder%v", mockType, shortTp)
g.out()
g.p("}")
g.p("")
g.p("// %vMockRecorder is the mock recorder for %v.", mockType, mockType)
g.p("type %vMockRecorder struct {", mockType)
g.p("type %vMockRecorder%v struct {", mockType, longTp)
g.in()
g.p("mock *%v", mockType)
g.p("mock *%v%v", mockType, shortTp)
g.out()
g.p("}")
g.p("")
g.p("// New%v creates a new mock instance.", mockType)
g.p("func New%v(ctrl *gomock.Controller) *%v {", mockType, mockType)
g.p("func New%v%v(ctrl *gomock.Controller) *%v%v {", mockType, longTp, mockType, shortTp)
g.in()
g.p("mock := &%v{ctrl: ctrl}", mockType)
g.p("mock.recorder = &%vMockRecorder{mock}", mockType)
g.p("mock := &%v%v{ctrl: ctrl}", mockType, shortTp)
g.p("mock.recorder = &%vMockRecorder%v{mock}", mockType, shortTp)
g.p("return mock")
g.out()
g.p("}")
@ -404,13 +430,13 @@ func (g *generator) GenerateMockInterface(intf *model.Interface, outputPackagePa
// XXX: possible name collision here if someone has EXPECT in their interface.
g.p("// EXPECT returns an object that allows the caller to indicate expected use.")
g.p("func (m *%v) EXPECT() *%vMockRecorder {", mockType, mockType)
g.p("func (m *%v%v) EXPECT() *%vMockRecorder%v {", mockType, shortTp, mockType, shortTp)
g.in()
g.p("return m.recorder")
g.out()
g.p("}")
g.GenerateMockMethods(mockType, intf, outputPackagePath)
g.GenerateMockMethods(mockType, intf, outputPackagePath, shortTp)
return nil
}
@ -421,13 +447,13 @@ func (b byMethodName) Len() int { return len(b) }
func (b byMethodName) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
func (b byMethodName) Less(i, j int) bool { return b[i].Name < b[j].Name }
func (g *generator) GenerateMockMethods(mockType string, intf *model.Interface, pkgOverride string) {
func (g *generator) GenerateMockMethods(mockType string, intf *model.Interface, pkgOverride, shortTp string) {
sort.Sort(byMethodName(intf.Methods))
for _, m := range intf.Methods {
g.p("")
_ = g.GenerateMockMethod(mockType, m, pkgOverride)
_ = g.GenerateMockMethod(mockType, m, pkgOverride, shortTp)
g.p("")
_ = g.GenerateMockRecorderMethod(mockType, m)
_ = g.GenerateMockRecorderMethod(mockType, m, shortTp)
}
}
@ -446,7 +472,7 @@ func makeArgString(argNames, argTypes []string) string {
// GenerateMockMethod generates a mock method implementation.
// If non-empty, pkgOverride is the package in which unqualified types reside.
func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOverride string) error {
func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOverride, shortTp string) error {
argNames := g.getArgNames(m)
argTypes := g.getArgTypes(m, pkgOverride)
argString := makeArgString(argNames, argTypes)
@ -467,7 +493,7 @@ func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOver
idRecv := ia.allocateIdentifier("m")
g.p("// %v mocks base method.", m.Name)
g.p("func (%v *%v) %v(%v)%v {", idRecv, mockType, m.Name, argString, retString)
g.p("func (%v *%v%v) %v(%v)%v {", idRecv, mockType, shortTp, m.Name, argString, retString)
g.in()
g.p("%s.ctrl.T.Helper()", idRecv)
@ -511,7 +537,7 @@ func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOver
return nil
}
func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method) error {
func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method, shortTp string) error {
argNames := g.getArgNames(m)
var argString string
@ -535,7 +561,7 @@ func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method)
idRecv := ia.allocateIdentifier("mr")
g.p("// %v indicates an expected call of %v.", m.Name, m.Name)
g.p("func (%s *%vMockRecorder) %v(%v) *gomock.Call {", idRecv, mockType, m.Name, argString)
g.p("func (%s *%vMockRecorder%v) %v(%v) *gomock.Call {", idRecv, mockType, shortTp, m.Name, argString)
g.in()
g.p("%s.mock.ctrl.T.Helper()", idRecv)
@ -558,7 +584,7 @@ func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method)
callArgs = ", " + idVarArgs + "..."
}
}
g.p(`return %s.mock.ctrl.RecordCallWithMethodType(%s.mock, "%s", reflect.TypeOf((*%s)(nil).%s)%s)`, idRecv, idRecv, m.Name, mockType, m.Name, callArgs)
g.p(`return %s.mock.ctrl.RecordCallWithMethodType(%s.mock, "%s", reflect.TypeOf((*%s%s)(nil).%s)%s)`, idRecv, idRecv, m.Name, mockType, shortTp, m.Name, callArgs)
g.out()
g.p("}")

Просмотреть файл

@ -47,14 +47,18 @@ func (pkg *Package) Imports() map[string]bool {
im := make(map[string]bool)
for _, intf := range pkg.Interfaces {
intf.addImports(im)
for _, tp := range intf.TypeParams {
tp.Type.addImports(im)
}
}
return im
}
// Interface is a Go interface.
type Interface struct {
Name string
Methods []*Method
Name string
Methods []*Method
TypeParams []*Parameter
}
// Print writes the interface name and its methods.
@ -259,26 +263,28 @@ func (mt *MapType) addImports(im map[string]bool) {
// NamedType is an exported type in a package.
type NamedType struct {
Package string // may be empty
Type string
Package string // may be empty
Type string
TypeParams *TypeParametersType
}
func (nt *NamedType) String(pm map[string]string, pkgOverride string) string {
if pkgOverride == nt.Package {
return nt.Type
return nt.Type + nt.TypeParams.String(pm, pkgOverride)
}
prefix := pm[nt.Package]
if prefix != "" {
return prefix + "." + nt.Type
return prefix + "." + nt.Type + nt.TypeParams.String(pm, pkgOverride)
}
return nt.Type
return nt.Type + nt.TypeParams.String(pm, pkgOverride)
}
func (nt *NamedType) addImports(im map[string]bool) {
if nt.Package != "" {
im[nt.Package] = true
}
nt.TypeParams.addImports(im)
}
// PointerType is a pointer to another type.
@ -297,6 +303,36 @@ type PredeclaredType string
func (pt PredeclaredType) String(map[string]string, string) string { return string(pt) }
func (pt PredeclaredType) addImports(map[string]bool) {}
// TypeParametersType contains type paramters for a NamedType.
type TypeParametersType struct {
TypeParameters []Type
}
func (tp *TypeParametersType) String(pm map[string]string, pkgOverride string) string {
if tp == nil || len(tp.TypeParameters) == 0 {
return ""
}
var sb strings.Builder
sb.WriteString("[")
for i, v := range tp.TypeParameters {
if i != 0 {
sb.WriteString(", ")
}
sb.WriteString(v.String(pm, pkgOverride))
}
sb.WriteString("]")
return sb.String()
}
func (tp *TypeParametersType) addImports(im map[string]bool) {
if tp == nil {
return
}
for _, v := range tp.TypeParameters {
v.addImports(im)
}
}
// The following code is intended to be called by the program generated by ../reflect.go.
// InterfaceFromInterfaceType returns a pointer to an interface for the

Просмотреть файл

@ -62,8 +62,8 @@ func sourceMode(source string) (*model.Package, error) {
p := &fileParser{
fileSet: fs,
imports: make(map[string]importedPackage),
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
auxInterfaces: make(map[string]map[string]*ast.InterfaceType),
importedInterfaces: newInterfaceCache(),
auxInterfaces: newInterfaceCache(),
srcDir: srcDir,
}
@ -127,15 +127,48 @@ func (d duplicateImport) Error() string {
func (d duplicateImport) Path() string { log.Fatal(d.Error()); return "" }
func (d duplicateImport) Parser() *fileParser { log.Fatal(d.Error()); return nil }
type interfaceCache struct {
m map[string]map[string]*namedInterface
}
func newInterfaceCache() *interfaceCache {
return &interfaceCache{
m: make(map[string]map[string]*namedInterface),
}
}
func (i *interfaceCache) Set(pkg, name string, it *namedInterface) {
if _, ok := i.m[pkg]; !ok {
i.m[pkg] = make(map[string]*namedInterface)
}
i.m[pkg][name] = it
}
func (i *interfaceCache) Get(pkg, name string) *namedInterface {
if _, ok := i.m[pkg]; !ok {
return nil
}
return i.m[pkg][name]
}
func (i *interfaceCache) GetASTIface(pkg, name string) *ast.InterfaceType {
if _, ok := i.m[pkg]; !ok {
return nil
}
it, ok := i.m[pkg][name]
if !ok {
return nil
}
return it.it
}
type fileParser struct {
fileSet *token.FileSet
imports map[string]importedPackage // package name => imported package
importedInterfaces map[string]map[string]*ast.InterfaceType // package (or "") => name => interface
auxFiles []*ast.File
auxInterfaces map[string]map[string]*ast.InterfaceType // package (or "") => name => interface
srcDir string
imports map[string]importedPackage // package name => imported package
importedInterfaces *interfaceCache
auxFiles []*ast.File
auxInterfaces *interfaceCache
srcDir string
}
func (p *fileParser) errorf(pos token.Pos, format string, args ...interface{}) error {
@ -168,11 +201,8 @@ func (p *fileParser) parseAuxFiles(auxFiles string) error {
}
func (p *fileParser) addAuxInterfacesFromFile(pkg string, file *ast.File) {
if _, ok := p.auxInterfaces[pkg]; !ok {
p.auxInterfaces[pkg] = make(map[string]*ast.InterfaceType)
}
for ni := range iterInterfaces(file) {
p.auxInterfaces[pkg][ni.name.Name] = ni.it
p.auxInterfaces.Set(pkg, ni.name.Name, ni)
}
}
@ -199,7 +229,7 @@ func (p *fileParser) parseFile(importPath string, file *ast.File) (*model.Packag
var is []*model.Interface
for ni := range iterInterfaces(file) {
i, err := p.parseInterface(ni.name.String(), importPath, ni.it)
i, err := p.parseInterface(ni.name.String(), importPath, ni)
if err != nil {
return nil, err
}
@ -219,8 +249,8 @@ func (p *fileParser) parsePackage(path string) (*fileParser, error) {
newP := &fileParser{
fileSet: token.NewFileSet(),
imports: make(map[string]importedPackage),
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
auxInterfaces: make(map[string]map[string]*ast.InterfaceType),
importedInterfaces: newInterfaceCache(),
auxInterfaces: newInterfaceCache(),
srcDir: p.srcDir,
}
@ -233,11 +263,8 @@ func (p *fileParser) parsePackage(path string) (*fileParser, error) {
for _, pkg := range pkgs {
file := ast.MergePackageFiles(pkg, ast.FilterFuncDuplicates|ast.FilterUnassociatedComments|ast.FilterImportDuplicates)
if _, ok := newP.importedInterfaces[path]; !ok {
newP.importedInterfaces[path] = make(map[string]*ast.InterfaceType)
}
for ni := range iterInterfaces(file) {
newP.importedInterfaces[path][ni.name.Name] = ni.it
newP.importedInterfaces.Set(path, ni.name.Name, ni)
}
imports, _ := importsOfFile(file)
for pkgName, pkgI := range imports {
@ -247,9 +274,20 @@ func (p *fileParser) parsePackage(path string) (*fileParser, error) {
return newP, nil
}
func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*model.Interface, error) {
func (p *fileParser) parseInterface(name, pkg string, it *namedInterface) (*model.Interface, error) {
iface := &model.Interface{Name: name}
for _, field := range it.Methods.List {
tps := make(map[string]bool)
tp, err := p.parseFieldList(pkg, it.typeParams, tps)
if err != nil {
return nil, fmt.Errorf("unable to parse interface type parameters: %v", name)
}
iface.TypeParams = tp
for _, v := range tp {
tps[v.Name] = true
}
for _, field := range it.it.Methods.List {
switch v := field.Type.(type) {
case *ast.FuncType:
if nn := len(field.Names); nn != 1 {
@ -259,16 +297,16 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
Name: field.Names[0].String(),
}
var err error
m.In, m.Variadic, m.Out, err = p.parseFunc(pkg, v)
m.In, m.Variadic, m.Out, err = p.parseFunc(pkg, v, tps)
if err != nil {
return nil, err
}
iface.AddMethod(m)
case *ast.Ident:
// Embedded interface in this package.
embeddedIfaceType := p.auxInterfaces[pkg][v.String()]
embeddedIfaceType := p.auxInterfaces.Get(pkg, v.String())
if embeddedIfaceType == nil {
embeddedIfaceType = p.importedInterfaces[pkg][v.String()]
embeddedIfaceType = p.importedInterfaces.Get(pkg, v.String())
}
var embeddedIface *model.Interface
@ -288,7 +326,7 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
return nil, p.errorf(v.Pos(), "could not parse package %s: %v", pkg, err)
}
if embeddedIfaceType = ip.importedInterfaces[pkg][v.String()]; embeddedIfaceType == nil {
if embeddedIfaceType = ip.importedInterfaces.Get(pkg, v.String()); embeddedIfaceType == nil {
return nil, p.errorf(v.Pos(), "unknown embedded interface %s.%s", pkg, v.String())
}
@ -312,7 +350,7 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
var embeddedIface *model.Interface
var err error
embeddedIfaceType := p.auxInterfaces[filePkg][sel]
embeddedIfaceType := p.auxInterfaces.Get(filePkg, sel)
if embeddedIfaceType != nil {
embeddedIface, err = p.parseInterface(sel, filePkg, embeddedIfaceType)
if err != nil {
@ -332,7 +370,7 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
parser: parser,
}
}
if embeddedIfaceType = parser.importedInterfaces[path][sel]; embeddedIfaceType == nil {
if embeddedIfaceType = parser.importedInterfaces.Get(path, sel); embeddedIfaceType == nil {
return nil, p.errorf(v.Pos(), "unknown embedded interface %s.%s", path, sel)
}
embeddedIface, err = parser.parseInterface(sel, path, embeddedIfaceType)
@ -352,26 +390,26 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
return iface, nil
}
func (p *fileParser) parseFunc(pkg string, f *ast.FuncType) (inParam []*model.Parameter, variadic *model.Parameter, outParam []*model.Parameter, err error) {
func (p *fileParser) parseFunc(pkg string, f *ast.FuncType, tps map[string]bool) (inParam []*model.Parameter, variadic *model.Parameter, outParam []*model.Parameter, err error) {
if f.Params != nil {
regParams := f.Params.List
if isVariadic(f) {
n := len(regParams)
varParams := regParams[n-1:]
regParams = regParams[:n-1]
vp, err := p.parseFieldList(pkg, varParams)
vp, err := p.parseFieldList(pkg, varParams, tps)
if err != nil {
return nil, nil, nil, p.errorf(varParams[0].Pos(), "failed parsing variadic argument: %v", err)
}
variadic = vp[0]
}
inParam, err = p.parseFieldList(pkg, regParams)
inParam, err = p.parseFieldList(pkg, regParams, tps)
if err != nil {
return nil, nil, nil, p.errorf(f.Pos(), "failed parsing arguments: %v", err)
}
}
if f.Results != nil {
outParam, err = p.parseFieldList(pkg, f.Results.List)
outParam, err = p.parseFieldList(pkg, f.Results.List, tps)
if err != nil {
return nil, nil, nil, p.errorf(f.Pos(), "failed parsing returns: %v", err)
}
@ -379,7 +417,7 @@ func (p *fileParser) parseFunc(pkg string, f *ast.FuncType) (inParam []*model.Pa
return
}
func (p *fileParser) parseFieldList(pkg string, fields []*ast.Field) ([]*model.Parameter, error) {
func (p *fileParser) parseFieldList(pkg string, fields []*ast.Field, tps map[string]bool) ([]*model.Parameter, error) {
nf := 0
for _, f := range fields {
nn := len(f.Names)
@ -394,7 +432,7 @@ func (p *fileParser) parseFieldList(pkg string, fields []*ast.Field) ([]*model.P
ps := make([]*model.Parameter, nf)
i := 0 // destination index
for _, f := range fields {
t, err := p.parseType(pkg, f.Type)
t, err := p.parseType(pkg, f.Type, tps)
if err != nil {
return nil, err
}
@ -413,7 +451,7 @@ func (p *fileParser) parseFieldList(pkg string, fields []*ast.Field) ([]*model.P
return ps, nil
}
func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
func (p *fileParser) parseType(pkg string, typ ast.Expr, tps map[string]bool) (model.Type, error) {
switch v := typ.(type) {
case *ast.ArrayType:
ln := -1
@ -427,13 +465,13 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
return nil, p.errorf(v.Len.Pos(), "bad array size: %v", err)
}
}
t, err := p.parseType(pkg, v.Elt)
t, err := p.parseType(pkg, v.Elt, tps)
if err != nil {
return nil, err
}
return &model.ArrayType{Len: ln, Type: t}, nil
case *ast.ChanType:
t, err := p.parseType(pkg, v.Value)
t, err := p.parseType(pkg, v.Value, tps)
if err != nil {
return nil, err
}
@ -447,15 +485,15 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
return &model.ChanType{Dir: dir, Type: t}, nil
case *ast.Ellipsis:
// assume we're parsing a variadic argument
return p.parseType(pkg, v.Elt)
return p.parseType(pkg, v.Elt, tps)
case *ast.FuncType:
in, variadic, out, err := p.parseFunc(pkg, v)
in, variadic, out, err := p.parseFunc(pkg, v, tps)
if err != nil {
return nil, err
}
return &model.FuncType{In: in, Out: out, Variadic: variadic}, nil
case *ast.Ident:
if v.IsExported() {
if v.IsExported() && !tps[v.Name] {
// `pkg` may be an aliased imported pkg
// if so, patch the import w/ the fully qualified import
maybeImportedPkg, ok := p.imports[pkg]
@ -474,11 +512,11 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
}
return model.PredeclaredType("interface{}"), nil
case *ast.MapType:
key, err := p.parseType(pkg, v.Key)
key, err := p.parseType(pkg, v.Key, tps)
if err != nil {
return nil, err
}
value, err := p.parseType(pkg, v.Value)
value, err := p.parseType(pkg, v.Value, tps)
if err != nil {
return nil, err
}
@ -491,7 +529,7 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
}
return &model.NamedType{Package: pkg.Path(), Type: v.Sel.String()}, nil
case *ast.StarExpr:
t, err := p.parseType(pkg, v.X)
t, err := p.parseType(pkg, v.X, tps)
if err != nil {
return nil, err
}
@ -502,7 +540,16 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
}
return model.PredeclaredType("struct{}"), nil
case *ast.ParenExpr:
return p.parseType(pkg, v.X)
return p.parseType(pkg, v.X, tps)
default:
mt, err := p.parseGenericType(pkg, typ, tps)
if err != nil {
return nil, err
}
if mt == nil {
break
}
return mt, nil
}
return nil, fmt.Errorf("don't know how to parse type %T", typ)
@ -610,13 +657,14 @@ func importsOfFile(file *ast.File) (normalImports map[string]importedPackage, do
}
type namedInterface struct {
name *ast.Ident
it *ast.InterfaceType
name *ast.Ident
it *ast.InterfaceType
typeParams []*ast.Field
}
// Create an iterator over all interfaces in file.
func iterInterfaces(file *ast.File) <-chan namedInterface {
ch := make(chan namedInterface)
func iterInterfaces(file *ast.File) <-chan *namedInterface {
ch := make(chan *namedInterface)
go func() {
for _, decl := range file.Decls {
gd, ok := decl.(*ast.GenDecl)
@ -633,7 +681,7 @@ func iterInterfaces(file *ast.File) <-chan namedInterface {
continue
}
ch <- namedInterface{ts.Name, it}
ch <- &namedInterface{ts.Name, it, getTypeSpecTypeParams(ts)}
}
}
close(ch)

Просмотреть файл

@ -1,7 +1,6 @@
package main
import (
"go/ast"
"go/parser"
"go/token"
"testing"
@ -17,7 +16,7 @@ func TestFileParser_ParseFile(t *testing.T) {
p := fileParser{
fileSet: fs,
imports: make(map[string]importedPackage),
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
importedInterfaces: newInterfaceCache(),
}
pkg, err := p.parseFile("", file)
@ -48,7 +47,7 @@ func TestFileParser_ParsePackage(t *testing.T) {
p := fileParser{
fileSet: fs,
imports: make(map[string]importedPackage),
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
importedInterfaces: newInterfaceCache(),
}
newP, err := p.parsePackage("github.com/golang/mock/mockgen/internal/tests/custom_package_name/greeter")
@ -126,8 +125,8 @@ func TestParseArrayWithConstLength(t *testing.T) {
p := fileParser{
fileSet: fs,
imports: make(map[string]importedPackage),
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
auxInterfaces: make(map[string]map[string]*ast.InterfaceType),
importedInterfaces: newInterfaceCache(),
auxInterfaces: newInterfaceCache(),
srcDir: srcDir,
}

Просмотреть файл

@ -1,4 +1,4 @@
// Copyright 2019 Google LLC
// 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.
@ -28,5 +28,4 @@ func printModuleVersion() {
"GO111MODULE=on when running 'go get' in order to use specific " +
"version of the binary.")
}
}