Remove golang mock as it has been replaced with uber mock
Signed-off-by: RainbowMango <qdurenhongcai@gmail.com>
This commit is contained in:
parent
7a4d85b925
commit
9a776a7503
1
go.mod
1
go.mod
|
@ -9,7 +9,6 @@ require (
|
|||
github.com/evanphx/json-patch/v5 v5.6.0
|
||||
github.com/go-co-op/gocron v1.30.1
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/kr/pretty v0.3.1
|
||||
|
|
1
go.sum
1
go.sum
|
@ -350,7 +350,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
|||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
|
|
@ -21,9 +21,9 @@ package tools
|
|||
|
||||
import (
|
||||
_ "github.com/gogo/protobuf/protoc-gen-gogo"
|
||||
_ "github.com/golang/mock/mockgen"
|
||||
_ "github.com/onsi/ginkgo/v2/ginkgo"
|
||||
_ "github.com/vektra/mockery/v2"
|
||||
_ "go.uber.org/mock/mockgen"
|
||||
_ "golang.org/x/tools/cmd/goimports"
|
||||
_ "k8s.io/code-generator"
|
||||
)
|
||||
|
|
|
@ -33,7 +33,7 @@ source "${KARMADA_ROOT}"/hack/util.sh
|
|||
echo -n "Preparing: 'mockgen' existence check - "
|
||||
if [ ! $(util::cmd_exist mockgen) ]; then
|
||||
# install from vendor with the pinned version in go.mod file
|
||||
GO111MODULE=on go install "github.com/golang/mock/mockgen"
|
||||
GO111MODULE=on go install "go.uber.org/mock/mockgen"
|
||||
fi
|
||||
|
||||
find_files() {
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: interface.go
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -source=interface.go -destination=testing/mock_interface.go -package=testing FilterPlugin ScorePlugin ScoreExtensions
|
||||
//
|
||||
|
||||
// Package testing is a generated GoMock package.
|
||||
package testing
|
||||
|
@ -8,10 +13,10 @@ import (
|
|||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
|
||||
v1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||
framework "github.com/karmada-io/karmada/pkg/scheduler/framework"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockFramework is a mock of Framework interface.
|
||||
|
@ -46,7 +51,7 @@ func (m *MockFramework) RunFilterPlugins(ctx context.Context, bindingSpec *v1alp
|
|||
}
|
||||
|
||||
// RunFilterPlugins indicates an expected call of RunFilterPlugins.
|
||||
func (mr *MockFrameworkMockRecorder) RunFilterPlugins(ctx, bindingSpec, bindingStatus, cluster interface{}) *gomock.Call {
|
||||
func (mr *MockFrameworkMockRecorder) RunFilterPlugins(ctx, bindingSpec, bindingStatus, cluster any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunFilterPlugins", reflect.TypeOf((*MockFramework)(nil).RunFilterPlugins), ctx, bindingSpec, bindingStatus, cluster)
|
||||
}
|
||||
|
@ -61,7 +66,7 @@ func (m *MockFramework) RunScorePlugins(ctx context.Context, spec *v1alpha2.Reso
|
|||
}
|
||||
|
||||
// RunScorePlugins indicates an expected call of RunScorePlugins.
|
||||
func (mr *MockFrameworkMockRecorder) RunScorePlugins(ctx, spec, clusters interface{}) *gomock.Call {
|
||||
func (mr *MockFrameworkMockRecorder) RunScorePlugins(ctx, spec, clusters any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunScorePlugins", reflect.TypeOf((*MockFramework)(nil).RunScorePlugins), ctx, spec, clusters)
|
||||
}
|
||||
|
@ -135,7 +140,7 @@ func (m *MockFilterPlugin) Filter(ctx context.Context, bindingSpec *v1alpha2.Res
|
|||
}
|
||||
|
||||
// Filter indicates an expected call of Filter.
|
||||
func (mr *MockFilterPluginMockRecorder) Filter(ctx, bindingSpec, bindingStatus, cluster interface{}) *gomock.Call {
|
||||
func (mr *MockFilterPluginMockRecorder) Filter(ctx, bindingSpec, bindingStatus, cluster any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Filter", reflect.TypeOf((*MockFilterPlugin)(nil).Filter), ctx, bindingSpec, bindingStatus, cluster)
|
||||
}
|
||||
|
@ -201,7 +206,7 @@ func (m *MockScorePlugin) Score(ctx context.Context, spec *v1alpha2.ResourceBind
|
|||
}
|
||||
|
||||
// Score indicates an expected call of Score.
|
||||
func (mr *MockScorePluginMockRecorder) Score(ctx, spec, cluster interface{}) *gomock.Call {
|
||||
func (mr *MockScorePluginMockRecorder) Score(ctx, spec, cluster any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Score", reflect.TypeOf((*MockScorePlugin)(nil).Score), ctx, spec, cluster)
|
||||
}
|
||||
|
@ -252,7 +257,7 @@ func (m *MockScoreExtensions) NormalizeScore(ctx context.Context, scores framewo
|
|||
}
|
||||
|
||||
// NormalizeScore indicates an expected call of NormalizeScore.
|
||||
func (mr *MockScoreExtensionsMockRecorder) NormalizeScore(ctx, scores interface{}) *gomock.Call {
|
||||
func (mr *MockScoreExtensionsMockRecorder) NormalizeScore(ctx, scores any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NormalizeScore", reflect.TypeOf((*MockScoreExtensions)(nil).NormalizeScore), ctx, scores)
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
# This is the official list of GoMock authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files.
|
||||
# See the latter for an explanation.
|
||||
|
||||
# Names should be added to this file as
|
||||
# Name or Organization <email address>
|
||||
# The email address is not required for organizations.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Alex Reece <awreece@gmail.com>
|
||||
Google Inc.
|
|
@ -1,37 +0,0 @@
|
|||
# This is the official list of people who can contribute (and typically
|
||||
# have contributed) code to the gomock repository.
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
# lists people. For example, Google employees are listed here
|
||||
# but not in AUTHORS, because Google holds the copyright.
|
||||
#
|
||||
# The submission process automatically checks to make sure
|
||||
# that people submitting code are listed in this file (by email address).
|
||||
#
|
||||
# Names should be added to this file only after verifying that
|
||||
# the individual or the individual's organization has agreed to
|
||||
# the appropriate Contributor License Agreement, found here:
|
||||
#
|
||||
# http://code.google.com/legal/individual-cla-v1.0.html
|
||||
# http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
#
|
||||
# The agreement for individuals can be filled out on the web.
|
||||
#
|
||||
# When adding J Random Contributor's name to this file,
|
||||
# either J's name or J's organization's name should be
|
||||
# added to the AUTHORS file, depending on whether the
|
||||
# individual or corporate CLA was used.
|
||||
|
||||
# Names should be added to this file like so:
|
||||
# Name <email address>
|
||||
#
|
||||
# An entry with two email addresses specifies that the
|
||||
# first address should be used in the submit logs and
|
||||
# that the second address should be recognized as the
|
||||
# same person when interacting with Rietveld.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Aaron Jacobs <jacobsa@google.com> <aaronjjacobs@gmail.com>
|
||||
Alex Reece <awreece@gmail.com>
|
||||
David Symonds <dsymonds@golang.org>
|
||||
Ryan Barrett <ryanb@google.com>
|
|
@ -1,202 +0,0 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright 2019 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.
|
||||
|
||||
// +build !go1.12
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
func printModuleVersion() {
|
||||
log.Printf("No version information is available for Mockgen compiled with " +
|
||||
"version 1.11")
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
// 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/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]model.Type) (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 any) 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()
|
||||
}
|
||||
|
||||
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
|
||||
case *ast.UnaryExpr:
|
||||
if v.Op == token.TILDE {
|
||||
return nil, errConstraintInterface
|
||||
}
|
||||
return nil, fmt.Errorf("~T may only appear as constraint for %T", field.Type)
|
||||
case *ast.BinaryExpr:
|
||||
if v.Op == token.OR {
|
||||
return nil, errConstraintInterface
|
||||
}
|
||||
return nil, fmt.Errorf("A|B may only appear as constraint for %T", field.Type)
|
||||
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)
|
||||
}
|
||||
|
||||
var errConstraintInterface = errors.New("interface contains constraints")
|
|
@ -0,0 +1,41 @@
|
|||
// 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 (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"go.uber.org/mock/mockgen/model"
|
||||
)
|
||||
|
||||
func getTypeSpecTypeParams(ts *ast.TypeSpec) []*ast.Field {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *fileParser) parseGenericType(pkg string, typ ast.Expr, tps map[string]model.Type) (model.Type, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getIdentTypeParams(decl any) 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)
|
||||
}
|
|
@ -21,29 +21,30 @@ package main
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/golang/mock/mockgen/model"
|
||||
|
||||
"golang.org/x/mod/modfile"
|
||||
toolsimports "golang.org/x/tools/imports"
|
||||
|
||||
"go.uber.org/mock/mockgen/model"
|
||||
)
|
||||
|
||||
const (
|
||||
gomockImportPath = "github.com/golang/mock/gomock"
|
||||
gomockImportPath = "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -53,13 +54,19 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
source = flag.String("source", "", "(source mode) Input Go source file; enables source mode.")
|
||||
destination = flag.String("destination", "", "Output file; defaults to stdout.")
|
||||
mockNames = flag.String("mock_names", "", "Comma-separated interfaceName=mockName pairs of explicit mock names to use. Mock names default to 'Mock'+ interfaceName suffix.")
|
||||
packageOut = flag.String("package", "", "Package of the generated code; defaults to the package of the input with a 'mock_' prefix.")
|
||||
selfPackage = flag.String("self_package", "", "The full package import path for the generated code. The purpose of this flag is to prevent import cycles in the generated code by trying to include its own package. This can happen if the mock's package is set to one of its inputs (usually the main one) and the output is stdio so mockgen cannot detect the final output package. Setting this flag will then tell mockgen which import to exclude.")
|
||||
writePkgComment = flag.Bool("write_package_comment", true, "Writes package documentation comment (godoc) if true.")
|
||||
copyrightFile = flag.String("copyright_file", "", "Copyright file used to add copyright header")
|
||||
source = flag.String("source", "", "(source mode) Input Go source file; enables source mode.")
|
||||
destination = flag.String("destination", "", "Output file; defaults to stdout.")
|
||||
mockNames = flag.String("mock_names", "", "Comma-separated interfaceName=mockName pairs of explicit mock names to use. Mock names default to 'Mock'+ interfaceName suffix.")
|
||||
packageOut = flag.String("package", "", "Package of the generated code; defaults to the package of the input with a 'mock_' prefix.")
|
||||
selfPackage = flag.String("self_package", "", "The full package import path for the generated code. The purpose of this flag is to prevent import cycles in the generated code by trying to include its own package. This can happen if the mock's package is set to one of its inputs (usually the main one) and the output is stdio so mockgen cannot detect the final output package. Setting this flag will then tell mockgen which import to exclude.")
|
||||
writePkgComment = flag.Bool("write_package_comment", true, "Writes package documentation comment (godoc) if true.")
|
||||
writeSourceComment = flag.Bool("write_source_comment", true, "Writes original file (source mode) or interface names (reflect mode) comment if true.")
|
||||
writeGenerateDirective = flag.Bool("write_generate_directive", false, "Add //go:generate directive to regenerate the mock")
|
||||
copyrightFile = flag.String("copyright_file", "", "Copyright file used to add copyright header")
|
||||
typed = flag.Bool("typed", false, "Generate Type-safe 'Return', 'Do', 'DoAndReturn' function")
|
||||
imports = flag.String("imports", "", "(source mode) Comma-separated name=path pairs of explicit imports to use.")
|
||||
auxFiles = flag.String("aux_files", "", "(source mode) Comma-separated pkg=path pairs of auxiliary Go source files.")
|
||||
excludeInterfaces = flag.String("exclude_interfaces", "", "Comma-separated names of interfaces to be excluded")
|
||||
|
||||
debugParser = flag.Bool("debug_parser", false, "Print out parser results only.")
|
||||
showVersion = flag.Bool("version", false, "Print version.")
|
||||
|
@ -107,19 +114,6 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
dst := os.Stdout
|
||||
if len(*destination) > 0 {
|
||||
if err := os.MkdirAll(filepath.Dir(*destination), os.ModePerm); err != nil {
|
||||
log.Fatalf("Unable to create directory: %v", err)
|
||||
}
|
||||
f, err := os.Create(*destination)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed opening destination file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
dst = f
|
||||
}
|
||||
|
||||
outputPackageName := *packageOut
|
||||
if outputPackageName == "" {
|
||||
// pkg.Name in reflect mode is the base name of the import path,
|
||||
|
@ -161,7 +155,7 @@ func main() {
|
|||
g.mockNames = parseMockNames(*mockNames)
|
||||
}
|
||||
if *copyrightFile != "" {
|
||||
header, err := ioutil.ReadFile(*copyrightFile)
|
||||
header, err := os.ReadFile(*copyrightFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed reading copyright file: %v", err)
|
||||
}
|
||||
|
@ -171,7 +165,27 @@ func main() {
|
|||
if err := g.Generate(pkg, outputPackageName, outputPackagePath); err != nil {
|
||||
log.Fatalf("Failed generating mock: %v", err)
|
||||
}
|
||||
if _, err := dst.Write(g.Output()); err != nil {
|
||||
output := g.Output()
|
||||
dst := os.Stdout
|
||||
if len(*destination) > 0 {
|
||||
if err := os.MkdirAll(filepath.Dir(*destination), os.ModePerm); err != nil {
|
||||
log.Fatalf("Unable to create directory: %v", err)
|
||||
}
|
||||
existing, err := os.ReadFile(*destination)
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
log.Fatalf("Failed reading pre-exiting destination file: %v", err)
|
||||
}
|
||||
if len(existing) == len(output) && bytes.Equal(existing, output) {
|
||||
return
|
||||
}
|
||||
f, err := os.Create(*destination)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed opening destination file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
dst = f
|
||||
}
|
||||
if _, err := dst.Write(output); err != nil {
|
||||
log.Fatalf("Failed writing to destination: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -188,6 +202,24 @@ func parseMockNames(names string) map[string]string {
|
|||
return mocksMap
|
||||
}
|
||||
|
||||
func parseExcludeInterfaces(names string) map[string]struct{} {
|
||||
splitNames := strings.Split(names, ",")
|
||||
namesSet := make(map[string]struct{}, len(splitNames))
|
||||
for _, name := range splitNames {
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
namesSet[name] = struct{}{}
|
||||
}
|
||||
|
||||
if len(namesSet) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return namesSet
|
||||
}
|
||||
|
||||
func usage() {
|
||||
_, _ = io.WriteString(os.Stderr, usageText)
|
||||
flag.PrintDefaults()
|
||||
|
@ -222,7 +254,7 @@ type generator struct {
|
|||
packageMap map[string]string // map from import path to package name
|
||||
}
|
||||
|
||||
func (g *generator) p(format string, args ...interface{}) {
|
||||
func (g *generator) p(format string, args ...any) {
|
||||
fmt.Fprintf(&g.buf, g.indent+format+"\n", args...)
|
||||
}
|
||||
|
||||
|
@ -274,12 +306,23 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac
|
|||
}
|
||||
|
||||
g.p("// Code generated by MockGen. DO NOT EDIT.")
|
||||
if g.filename != "" {
|
||||
g.p("// Source: %v", g.filename)
|
||||
} else {
|
||||
g.p("// Source: %v (interfaces: %v)", g.srcPackage, g.srcInterfaces)
|
||||
if *writeSourceComment {
|
||||
if g.filename != "" {
|
||||
g.p("// Source: %v", g.filename)
|
||||
} else {
|
||||
g.p("// Source: %v (interfaces: %v)", g.srcPackage, g.srcInterfaces)
|
||||
}
|
||||
}
|
||||
g.p("")
|
||||
g.p("//")
|
||||
g.p("// Generated by this command:")
|
||||
g.p("//")
|
||||
// only log the name of the executable, not the full path
|
||||
name := filepath.Base(os.Args[0])
|
||||
if runtime.GOOS == "windows" {
|
||||
name = strings.TrimSuffix(name, ".exe")
|
||||
}
|
||||
g.p("//\t%v", strings.Join(append([]string{name}, os.Args[1:]...), " "))
|
||||
g.p("//")
|
||||
|
||||
// Get all required imports, and generate unique names for them all.
|
||||
im := pkg.Imports()
|
||||
|
@ -305,6 +348,16 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac
|
|||
|
||||
packagesName := createPackageMap(sortedPaths)
|
||||
|
||||
definedImports := make(map[string]string, len(im))
|
||||
if *imports != "" {
|
||||
for _, kv := range strings.Split(*imports, ",") {
|
||||
eq := strings.Index(kv, "=")
|
||||
if k, v := kv[:eq], kv[eq+1:]; k != "." {
|
||||
definedImports[v] = k
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g.packageMap = make(map[string]string, len(im))
|
||||
localNames := make(map[string]bool, len(im))
|
||||
for _, pth := range sortedPaths {
|
||||
|
@ -316,11 +369,16 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac
|
|||
// Local names for an imported package can usually be the basename of the import path.
|
||||
// A couple of situations don't permit that, such as duplicate local names
|
||||
// (e.g. importing "html/template" and "text/template"), or where the basename is
|
||||
// a keyword (e.g. "foo/case").
|
||||
// a keyword (e.g. "foo/case") or when defining a name for that by using the -imports flag.
|
||||
// try base0, base1, ...
|
||||
pkgName := base
|
||||
|
||||
if _, ok := definedImports[base]; ok {
|
||||
pkgName = definedImports[base]
|
||||
}
|
||||
|
||||
i := 0
|
||||
for localNames[pkgName] || token.Lookup(pkgName).IsKeyword() {
|
||||
for localNames[pkgName] || token.Lookup(pkgName).IsKeyword() || pkgName == "any" {
|
||||
pkgName = base + strconv.Itoa(i)
|
||||
i++
|
||||
}
|
||||
|
@ -335,6 +393,10 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac
|
|||
}
|
||||
|
||||
if *writePkgComment {
|
||||
// Ensure there's an empty line before the package to follow the recommendations:
|
||||
// https://github.com/golang/go/wiki/CodeReviewComments#package-comments
|
||||
g.p("")
|
||||
|
||||
g.p("// Package %v is a generated GoMock package.", outputPkgName)
|
||||
}
|
||||
g.p("package %v", outputPkgName)
|
||||
|
@ -353,6 +415,10 @@ func (g *generator) Generate(pkg *model.Package, outputPkgName string, outputPac
|
|||
g.out()
|
||||
g.p(")")
|
||||
|
||||
if *writeGenerateDirective {
|
||||
g.p("//go:generate %v", strings.Join(os.Args, " "))
|
||||
}
|
||||
|
||||
for _, intf := range pkg.Interfaces {
|
||||
if err := g.GenerateMockInterface(intf, outputPackagePath); err != nil {
|
||||
return err
|
||||
|
@ -371,32 +437,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 +496,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, longTp, shortTp, *typed)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -421,13 +513,17 @@ 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, longTp, shortTp string, typed bool) {
|
||||
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(intf, m, shortTp, typed)
|
||||
if typed {
|
||||
g.p("")
|
||||
_ = g.GenerateMockReturnCallMethod(intf, m, pkgOverride, longTp, shortTp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,9 +542,9 @@ 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 {
|
||||
argNames := g.getArgNames(m)
|
||||
argTypes := g.getArgTypes(m, pkgOverride)
|
||||
func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOverride, shortTp string) error {
|
||||
argNames := g.getArgNames(m, true /* in */)
|
||||
argTypes := g.getArgTypes(m, pkgOverride, true /* in */)
|
||||
argString := makeArgString(argNames, argTypes)
|
||||
|
||||
rets := make([]string, len(m.Out))
|
||||
|
@ -467,7 +563,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)
|
||||
|
||||
|
@ -477,11 +573,11 @@ func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOver
|
|||
callArgs = ", " + strings.Join(argNames, ", ")
|
||||
}
|
||||
} else {
|
||||
// Non-trivial. The generated code must build a []interface{},
|
||||
// Non-trivial. The generated code must build a []any,
|
||||
// but the variadic argument may be any type.
|
||||
idVarArgs := ia.allocateIdentifier("varargs")
|
||||
idVArg := ia.allocateIdentifier("a")
|
||||
g.p("%s := []interface{}{%s}", idVarArgs, strings.Join(argNames[:len(argNames)-1], ", "))
|
||||
g.p("%s := []any{%s}", idVarArgs, strings.Join(argNames[:len(argNames)-1], ", "))
|
||||
g.p("for _, %s := range %s {", idVArg, argNames[len(argNames)-1])
|
||||
g.in()
|
||||
g.p("%s = append(%s, %s)", idVarArgs, idVarArgs, idVArg)
|
||||
|
@ -511,8 +607,9 @@ func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOver
|
|||
return nil
|
||||
}
|
||||
|
||||
func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method) error {
|
||||
argNames := g.getArgNames(m)
|
||||
func (g *generator) GenerateMockRecorderMethod(intf *model.Interface, m *model.Method, shortTp string, typed bool) error {
|
||||
mockType := g.mockName(intf.Name)
|
||||
argNames := g.getArgNames(m, true)
|
||||
|
||||
var argString string
|
||||
if m.Variadic == nil {
|
||||
|
@ -521,21 +618,26 @@ func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method)
|
|||
argString = strings.Join(argNames[:len(argNames)-1], ", ")
|
||||
}
|
||||
if argString != "" {
|
||||
argString += " interface{}"
|
||||
argString += " any"
|
||||
}
|
||||
|
||||
if m.Variadic != nil {
|
||||
if argString != "" {
|
||||
argString += ", "
|
||||
}
|
||||
argString += fmt.Sprintf("%s ...interface{}", argNames[len(argNames)-1])
|
||||
argString += fmt.Sprintf("%s ...any", argNames[len(argNames)-1])
|
||||
}
|
||||
|
||||
ia := newIdentifierAllocator(argNames)
|
||||
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)
|
||||
if typed {
|
||||
g.p("func (%s *%vMockRecorder%v) %v(%v) *%s%sCall%s {", idRecv, mockType, shortTp, m.Name, argString, mockType, m.Name, shortTp)
|
||||
} else {
|
||||
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)
|
||||
|
||||
|
@ -551,42 +653,122 @@ func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method)
|
|||
} else {
|
||||
// Hard: create a temporary slice.
|
||||
idVarArgs := ia.allocateIdentifier("varargs")
|
||||
g.p("%s := append([]interface{}{%s}, %s...)",
|
||||
g.p("%s := append([]any{%s}, %s...)",
|
||||
idVarArgs,
|
||||
strings.Join(argNames[:len(argNames)-1], ", "),
|
||||
argNames[len(argNames)-1])
|
||||
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)
|
||||
if typed {
|
||||
g.p(`call := %s.mock.ctrl.RecordCallWithMethodType(%s.mock, "%s", reflect.TypeOf((*%s%s)(nil).%s)%s)`, idRecv, idRecv, m.Name, mockType, shortTp, m.Name, callArgs)
|
||||
g.p(`return &%s%sCall%s{Call: call}`, mockType, m.Name, shortTp)
|
||||
} else {
|
||||
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("}")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *generator) getArgNames(m *model.Method) []string {
|
||||
argNames := make([]string, len(m.In))
|
||||
for i, p := range m.In {
|
||||
func (g *generator) GenerateMockReturnCallMethod(intf *model.Interface, m *model.Method, pkgOverride, longTp, shortTp string) error {
|
||||
mockType := g.mockName(intf.Name)
|
||||
argNames := g.getArgNames(m, true /* in */)
|
||||
retNames := g.getArgNames(m, false /* out */)
|
||||
argTypes := g.getArgTypes(m, pkgOverride, true /* in */)
|
||||
retTypes := g.getArgTypes(m, pkgOverride, false /* out */)
|
||||
argString := strings.Join(argTypes, ", ")
|
||||
|
||||
rets := make([]string, len(m.Out))
|
||||
for i, p := range m.Out {
|
||||
rets[i] = p.Type.String(g.packageMap, pkgOverride)
|
||||
}
|
||||
|
||||
var retString string
|
||||
switch {
|
||||
case len(rets) == 1:
|
||||
retString = " " + rets[0]
|
||||
case len(rets) > 1:
|
||||
retString = " (" + strings.Join(rets, ", ") + ")"
|
||||
}
|
||||
|
||||
ia := newIdentifierAllocator(argNames)
|
||||
idRecv := ia.allocateIdentifier("c")
|
||||
|
||||
recvStructName := mockType + m.Name
|
||||
|
||||
g.p("// %s%sCall wrap *gomock.Call", mockType, m.Name)
|
||||
g.p("type %s%sCall%s struct{", mockType, m.Name, longTp)
|
||||
g.in()
|
||||
g.p("*gomock.Call")
|
||||
g.out()
|
||||
g.p("}")
|
||||
|
||||
g.p("// Return rewrite *gomock.Call.Return")
|
||||
g.p("func (%s *%sCall%s) Return(%v) *%sCall%s {", idRecv, recvStructName, shortTp, makeArgString(retNames, retTypes), recvStructName, shortTp)
|
||||
g.in()
|
||||
var retArgs string
|
||||
if len(retNames) > 0 {
|
||||
retArgs = strings.Join(retNames, ", ")
|
||||
}
|
||||
g.p(`%s.Call = %v.Call.Return(%v)`, idRecv, idRecv, retArgs)
|
||||
g.p("return %s", idRecv)
|
||||
g.out()
|
||||
g.p("}")
|
||||
|
||||
g.p("// Do rewrite *gomock.Call.Do")
|
||||
g.p("func (%s *%sCall%s) Do(f func(%v)%v) *%sCall%s {", idRecv, recvStructName, shortTp, argString, retString, recvStructName, shortTp)
|
||||
g.in()
|
||||
g.p(`%s.Call = %v.Call.Do(f)`, idRecv, idRecv)
|
||||
g.p("return %s", idRecv)
|
||||
g.out()
|
||||
g.p("}")
|
||||
|
||||
g.p("// DoAndReturn rewrite *gomock.Call.DoAndReturn")
|
||||
g.p("func (%s *%sCall%s) DoAndReturn(f func(%v)%v) *%sCall%s {", idRecv, recvStructName, shortTp, argString, retString, recvStructName, shortTp)
|
||||
g.in()
|
||||
g.p(`%s.Call = %v.Call.DoAndReturn(f)`, idRecv, idRecv)
|
||||
g.p("return %s", idRecv)
|
||||
g.out()
|
||||
g.p("}")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *generator) getArgNames(m *model.Method, in bool) []string {
|
||||
var params []*model.Parameter
|
||||
if in {
|
||||
params = m.In
|
||||
} else {
|
||||
params = m.Out
|
||||
}
|
||||
argNames := make([]string, len(params))
|
||||
for i, p := range params {
|
||||
name := p.Name
|
||||
if name == "" || name == "_" {
|
||||
name = fmt.Sprintf("arg%d", i)
|
||||
}
|
||||
argNames[i] = name
|
||||
}
|
||||
if m.Variadic != nil {
|
||||
if m.Variadic != nil && in {
|
||||
name := m.Variadic.Name
|
||||
if name == "" {
|
||||
name = fmt.Sprintf("arg%d", len(m.In))
|
||||
name = fmt.Sprintf("arg%d", len(params))
|
||||
}
|
||||
argNames = append(argNames, name)
|
||||
}
|
||||
return argNames
|
||||
}
|
||||
|
||||
func (g *generator) getArgTypes(m *model.Method, pkgOverride string) []string {
|
||||
argTypes := make([]string, len(m.In))
|
||||
for i, p := range m.In {
|
||||
func (g *generator) getArgTypes(m *model.Method, pkgOverride string, in bool) []string {
|
||||
var params []*model.Parameter
|
||||
if in {
|
||||
params = m.In
|
||||
} else {
|
||||
params = m.Out
|
||||
}
|
||||
argTypes := make([]string, len(params))
|
||||
for i, p := range params {
|
||||
argTypes[i] = p.Type.String(g.packageMap, pkgOverride)
|
||||
}
|
||||
if m.Variadic != nil {
|
||||
|
@ -670,7 +852,7 @@ func parsePackageImport(srcDir string) (string, error) {
|
|||
if moduleMode != "off" {
|
||||
currentDir := srcDir
|
||||
for {
|
||||
dat, err := ioutil.ReadFile(filepath.Join(currentDir, "go.mod"))
|
||||
dat, err := os.ReadFile(filepath.Join(currentDir, "go.mod"))
|
||||
if os.IsNotExist(err) {
|
||||
if currentDir == filepath.Dir(currentDir) {
|
||||
// at the root
|
|
@ -24,7 +24,7 @@ import (
|
|||
)
|
||||
|
||||
// pkgPath is the importable path for package model
|
||||
const pkgPath = "github.com/golang/mock/mockgen/model"
|
||||
const pkgPath = "go.uber.org/mock/mockgen/model"
|
||||
|
||||
// Package is a Go package. It may be a subset.
|
||||
type Package struct {
|
||||
|
@ -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.
|
||||
|
@ -143,12 +147,14 @@ type Type interface {
|
|||
}
|
||||
|
||||
func init() {
|
||||
gob.Register(&ArrayType{})
|
||||
gob.Register(&ChanType{})
|
||||
gob.Register(&FuncType{})
|
||||
gob.Register(&MapType{})
|
||||
gob.Register(&NamedType{})
|
||||
gob.Register(&PointerType{})
|
||||
// Call gob.RegisterName with pkgPath as prefix to avoid conflicting with
|
||||
// github.com/golang/mock/mockgen/model 's registration.
|
||||
gob.RegisterName(pkgPath+".ArrayType", &ArrayType{})
|
||||
gob.RegisterName(pkgPath+".ChanType", &ChanType{})
|
||||
gob.RegisterName(pkgPath+".FuncType", &FuncType{})
|
||||
gob.RegisterName(pkgPath+".MapType", &MapType{})
|
||||
gob.RegisterName(pkgPath+".NamedType", &NamedType{})
|
||||
gob.RegisterName(pkgPath+".PointerType", &PointerType{})
|
||||
|
||||
// Call gob.RegisterName to make sure it has the consistent name registered
|
||||
// for both gob decoder and encoder.
|
||||
|
@ -156,7 +162,7 @@ func init() {
|
|||
// For a non-pointer type, gob.Register will try to get package full path by
|
||||
// calling rt.PkgPath() for a name to register. If your project has vendor
|
||||
// directory, it is possible that PkgPath will get a path like this:
|
||||
// ../../../vendor/github.com/golang/mock/mockgen/model
|
||||
// ../../../vendor/go.uber.org/mock/mockgen/model
|
||||
gob.RegisterName(pkgPath+".PredeclaredType", PredeclaredType(""))
|
||||
}
|
||||
|
||||
|
@ -259,26 +265,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 +305,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 parameters 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
|
||||
|
@ -431,7 +469,7 @@ func typeFromType(t reflect.Type) (Type, error) {
|
|||
case reflect.Interface:
|
||||
// Two special interfaces.
|
||||
if t.NumMethod() == 0 {
|
||||
return PredeclaredType("interface{}"), nil
|
||||
return PredeclaredType("any"), nil
|
||||
}
|
||||
if t == errorType {
|
||||
return PredeclaredType("error"), nil
|
353
vendor/github.com/golang/mock/mockgen/parse.go → vendor/go.uber.org/mock/mockgen/parse.go
generated
vendored
353
vendor/github.com/golang/mock/mockgen/parse.go → vendor/go.uber.org/mock/mockgen/parse.go
generated
vendored
|
@ -18,7 +18,6 @@ package main
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
|
@ -26,19 +25,14 @@ import (
|
|||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/mock/mockgen/model"
|
||||
)
|
||||
|
||||
var (
|
||||
imports = flag.String("imports", "", "(source mode) Comma-separated name=path pairs of explicit imports to use.")
|
||||
auxFiles = flag.String("aux_files", "", "(source mode) Comma-separated pkg=path pairs of auxiliary Go source files.")
|
||||
"go.uber.org/mock/mockgen/model"
|
||||
)
|
||||
|
||||
// sourceMode generates mocks via source file.
|
||||
|
@ -62,8 +56,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,
|
||||
}
|
||||
|
||||
|
@ -81,6 +75,10 @@ func sourceMode(source string) (*model.Package, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if *excludeInterfaces != "" {
|
||||
p.excludeNamesSet = parseExcludeInterfaces(*excludeInterfaces)
|
||||
}
|
||||
|
||||
// Handle -aux_files.
|
||||
if err := p.parseAuxFiles(*auxFiles); err != nil {
|
||||
return nil, err
|
||||
|
@ -127,21 +125,55 @@ 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 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
|
||||
type interfaceCache struct {
|
||||
m map[string]map[string]*namedInterface
|
||||
}
|
||||
|
||||
func (p *fileParser) errorf(pos token.Pos, format string, args ...interface{}) error {
|
||||
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 *interfaceCache
|
||||
auxFiles []*ast.File
|
||||
auxInterfaces *interfaceCache
|
||||
srcDir string
|
||||
excludeNamesSet map[string]struct{}
|
||||
}
|
||||
|
||||
func (p *fileParser) errorf(pos token.Pos, format string, args ...any) error {
|
||||
ps := p.fileSet.Position(pos)
|
||||
format = "%s:%d:%d: " + format
|
||||
args = append([]interface{}{ps.Filename, ps.Line, ps.Column}, args...)
|
||||
args = append([]any{ps.Filename, ps.Line, ps.Column}, args...)
|
||||
return fmt.Errorf(format, args...)
|
||||
}
|
||||
|
||||
|
@ -168,11 +200,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 +228,13 @@ 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)
|
||||
if _, ok := p.excludeNamesSet[ni.name.String()]; ok {
|
||||
continue
|
||||
}
|
||||
i, err := p.parseInterface(ni.name.String(), importPath, ni)
|
||||
if errors.Is(err, errConstraintInterface) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -219,8 +254,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 +268,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 +279,77 @@ 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) constructInstParams(pkg string, params []*ast.Field, instParams []model.Type, embeddedInstParams []ast.Expr, tps map[string]model.Type) ([]model.Type, error) {
|
||||
pm := make(map[string]int)
|
||||
var i int
|
||||
for _, v := range params {
|
||||
for _, n := range v.Names {
|
||||
pm[n.Name] = i
|
||||
instParams = append(instParams, model.PredeclaredType(n.Name))
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
var runtimeInstParams []model.Type
|
||||
for _, instParam := range embeddedInstParams {
|
||||
switch t := instParam.(type) {
|
||||
case *ast.Ident:
|
||||
if idx, ok := pm[t.Name]; ok {
|
||||
runtimeInstParams = append(runtimeInstParams, instParams[idx])
|
||||
continue
|
||||
}
|
||||
}
|
||||
modelType, err := p.parseType(pkg, instParam, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
runtimeInstParams = append(runtimeInstParams, modelType)
|
||||
}
|
||||
|
||||
return runtimeInstParams, nil
|
||||
}
|
||||
|
||||
func (p *fileParser) constructTps(it *namedInterface) (tps map[string]model.Type) {
|
||||
tps = make(map[string]model.Type)
|
||||
n := 0
|
||||
for _, tp := range it.typeParams {
|
||||
for _, tm := range tp.Names {
|
||||
tps[tm.Name] = nil
|
||||
if len(it.instTypes) != 0 {
|
||||
tps[tm.Name] = it.instTypes[n]
|
||||
n++
|
||||
}
|
||||
}
|
||||
}
|
||||
return tps
|
||||
}
|
||||
|
||||
// parseInterface loads interface specified by pkg and name, parses it and returns
|
||||
// a new model with the parsed.
|
||||
func (p *fileParser) parseInterface(name, pkg string, it *namedInterface) (*model.Interface, error) {
|
||||
iface := &model.Interface{Name: name}
|
||||
for _, field := range it.Methods.List {
|
||||
tps := p.constructTps(it)
|
||||
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 _, field := range it.it.Methods.List {
|
||||
var methods []*model.Method
|
||||
if methods, err = p.parseMethod(field, it, iface, pkg, tps); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, m := range methods {
|
||||
iface.AddMethod(m)
|
||||
}
|
||||
}
|
||||
return iface, nil
|
||||
}
|
||||
|
||||
func (p *fileParser) parseMethod(field *ast.Field, it *namedInterface, iface *model.Interface, pkg string, tps map[string]model.Type) ([]*model.Method, error) {
|
||||
// {} for git diff
|
||||
{
|
||||
switch v := field.Type.(type) {
|
||||
case *ast.FuncType:
|
||||
if nn := len(field.Names); nn != 1 {
|
||||
|
@ -259,37 +359,55 @@ 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)
|
||||
return []*model.Method{m}, nil
|
||||
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
|
||||
if embeddedIfaceType != nil {
|
||||
var err error
|
||||
embeddedIfaceType.instTypes, err = p.constructInstParams(pkg, it.typeParams, it.instTypes, it.embeddedInstTypeParams, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
embeddedIface, err = p.parseInterface(v.String(), pkg, embeddedIfaceType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
} else {
|
||||
// This is built-in error interface.
|
||||
if v.String() == model.ErrorInterface.Name {
|
||||
embeddedIface = &model.ErrorInterface
|
||||
} else {
|
||||
return nil, p.errorf(v.Pos(), "unknown embedded interface %s", v.String())
|
||||
ip, err := p.parsePackage(pkg)
|
||||
if err != nil {
|
||||
return nil, p.errorf(v.Pos(), "could not parse package %s: %v", pkg, err)
|
||||
}
|
||||
|
||||
if embeddedIfaceType = ip.importedInterfaces.Get(pkg, v.String()); embeddedIfaceType == nil {
|
||||
return nil, p.errorf(v.Pos(), "unknown embedded interface %s.%s", pkg, v.String())
|
||||
}
|
||||
|
||||
embeddedIfaceType.instTypes, err = p.constructInstParams(pkg, it.typeParams, it.instTypes, it.embeddedInstTypeParams, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
embeddedIface, err = ip.parseInterface(v.String(), pkg, embeddedIfaceType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copy the methods.
|
||||
for _, m := range embeddedIface.Methods {
|
||||
iface.AddMethod(m)
|
||||
}
|
||||
return embeddedIface.Methods, nil
|
||||
case *ast.SelectorExpr:
|
||||
// Embedded interface in another package.
|
||||
filePkg, sel := v.X.(*ast.Ident).String(), v.Sel.String()
|
||||
|
@ -300,8 +418,12 @@ 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 {
|
||||
embeddedIfaceType.instTypes, err = p.constructInstParams(pkg, it.typeParams, it.instTypes, it.embeddedInstTypeParams, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
embeddedIface, err = p.parseInterface(sel, filePkg, embeddedIfaceType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -320,46 +442,47 @@ 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)
|
||||
}
|
||||
|
||||
embeddedIfaceType.instTypes, err = p.constructInstParams(pkg, it.typeParams, it.instTypes, it.embeddedInstTypeParams, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
embeddedIface, err = parser.parseInterface(sel, path, embeddedIfaceType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Copy the methods.
|
||||
// TODO: apply shadowing rules.
|
||||
for _, m := range embeddedIface.Methods {
|
||||
iface.AddMethod(m)
|
||||
}
|
||||
return embeddedIface.Methods, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("don't know how to mock method of type %T", field.Type)
|
||||
return p.parseGenericMethod(field, it, iface, pkg, tps)
|
||||
}
|
||||
}
|
||||
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]model.Type) (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)
|
||||
}
|
||||
|
@ -367,7 +490,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]model.Type) ([]*model.Parameter, error) {
|
||||
nf := 0
|
||||
for _, f := range fields {
|
||||
nn := len(f.Names)
|
||||
|
@ -382,7 +505,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
|
||||
}
|
||||
|
@ -401,44 +524,27 @@ 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]model.Type) (model.Type, error) {
|
||||
switch v := typ.(type) {
|
||||
case *ast.ArrayType:
|
||||
ln := -1
|
||||
if v.Len != nil {
|
||||
var value string
|
||||
switch val := v.Len.(type) {
|
||||
case (*ast.BasicLit):
|
||||
value = val.Value
|
||||
case (*ast.Ident):
|
||||
// when the length is a const defined locally
|
||||
value = val.Obj.Decl.(*ast.ValueSpec).Values[0].(*ast.BasicLit).Value
|
||||
case (*ast.SelectorExpr):
|
||||
// when the length is a const defined in an external package
|
||||
usedPkg, err := importer.Default().Import(fmt.Sprintf("%s", val.X))
|
||||
if err != nil {
|
||||
return nil, p.errorf(v.Len.Pos(), "unknown package in array length: %v", err)
|
||||
}
|
||||
ev, err := types.Eval(token.NewFileSet(), usedPkg, token.NoPos, val.Sel.Name)
|
||||
if err != nil {
|
||||
return nil, p.errorf(v.Len.Pos(), "unknown constant in array length: %v", err)
|
||||
}
|
||||
value = ev.Value.String()
|
||||
value, err := p.parseArrayLength(v.Len)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
x, err := strconv.Atoi(value)
|
||||
ln, err = strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return nil, p.errorf(v.Len.Pos(), "bad array size: %v", err)
|
||||
}
|
||||
ln = x
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -452,15 +558,16 @@ 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() {
|
||||
it, ok := tps[v.Name]
|
||||
if v.IsExported() && !ok {
|
||||
// `pkg` may be an aliased imported pkg
|
||||
// if so, patch the import w/ the fully qualified import
|
||||
maybeImportedPkg, ok := p.imports[pkg]
|
||||
|
@ -470,20 +577,22 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
|
|||
// assume type in this package
|
||||
return &model.NamedType{Package: pkg, Type: v.Name}, nil
|
||||
}
|
||||
|
||||
if ok && it != nil {
|
||||
return it, nil
|
||||
}
|
||||
// assume predeclared type
|
||||
return model.PredeclaredType(v.Name), nil
|
||||
case *ast.InterfaceType:
|
||||
if v.Methods != nil && len(v.Methods.List) > 0 {
|
||||
return nil, p.errorf(v.Pos(), "can't handle non-empty unnamed interface types")
|
||||
}
|
||||
return model.PredeclaredType("interface{}"), nil
|
||||
return model.PredeclaredType("any"), 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
|
||||
}
|
||||
|
@ -496,7 +605,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
|
||||
}
|
||||
|
@ -507,12 +616,61 @@ 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)
|
||||
}
|
||||
|
||||
func (p *fileParser) parseArrayLength(expr ast.Expr) (string, error) {
|
||||
switch val := expr.(type) {
|
||||
case (*ast.BasicLit):
|
||||
return val.Value, nil
|
||||
case (*ast.Ident):
|
||||
// when the length is a const defined locally
|
||||
return val.Obj.Decl.(*ast.ValueSpec).Values[0].(*ast.BasicLit).Value, nil
|
||||
case (*ast.SelectorExpr):
|
||||
// when the length is a const defined in an external package
|
||||
usedPkg, err := importer.Default().Import(fmt.Sprintf("%s", val.X))
|
||||
if err != nil {
|
||||
return "", p.errorf(expr.Pos(), "unknown package in array length: %v", err)
|
||||
}
|
||||
ev, err := types.Eval(token.NewFileSet(), usedPkg, token.NoPos, val.Sel.Name)
|
||||
if err != nil {
|
||||
return "", p.errorf(expr.Pos(), "unknown constant in array length: %v", err)
|
||||
}
|
||||
return ev.Value.String(), nil
|
||||
case (*ast.ParenExpr):
|
||||
return p.parseArrayLength(val.X)
|
||||
case (*ast.BinaryExpr):
|
||||
x, err := p.parseArrayLength(val.X)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
y, err := p.parseArrayLength(val.Y)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
biExpr := fmt.Sprintf("%s%v%s", x, val.Op, y)
|
||||
tv, err := types.Eval(token.NewFileSet(), nil, token.NoPos, biExpr)
|
||||
if err != nil {
|
||||
return "", p.errorf(expr.Pos(), "invalid expression in array length: %v", err)
|
||||
}
|
||||
return tv.Value.String(), nil
|
||||
default:
|
||||
return "", p.errorf(expr.Pos(), "invalid expression in array length: %v", val)
|
||||
}
|
||||
}
|
||||
|
||||
// importsOfFile returns a map of package name to import path
|
||||
// of the imports in file.
|
||||
func importsOfFile(file *ast.File) (normalImports map[string]importedPackage, dotImports []string) {
|
||||
|
@ -575,13 +733,16 @@ 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
|
||||
embeddedInstTypeParams []ast.Expr
|
||||
instTypes []model.Type
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
@ -598,7 +759,7 @@ func iterInterfaces(file *ast.File) <-chan namedInterface {
|
|||
continue
|
||||
}
|
||||
|
||||
ch <- namedInterface{ts.Name, it}
|
||||
ch <- &namedInterface{name: ts.Name, it: it, typeParams: getTypeSpecTypeParams(ts)}
|
||||
}
|
||||
}
|
||||
close(ch)
|
||||
|
@ -618,7 +779,7 @@ func isVariadic(f *ast.FuncType) bool {
|
|||
|
||||
// packageNameOfDir get package import path via dir
|
||||
func packageNameOfDir(srcDir string) (string, error) {
|
||||
files, err := ioutil.ReadDir(srcDir)
|
||||
files, err := os.ReadDir(srcDir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
|
@ -23,7 +23,6 @@ import (
|
|||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -32,7 +31,7 @@ import (
|
|||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/golang/mock/mockgen/model"
|
||||
"go.uber.org/mock/mockgen/model"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -92,7 +91,7 @@ func writeProgram(importPath string, symbols []string) ([]byte, error) {
|
|||
|
||||
// run the given program and parse the output as a model.Package.
|
||||
func run(program string) (*model.Package, error) {
|
||||
f, err := ioutil.TempFile("", "")
|
||||
f, err := os.CreateTemp("", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -133,7 +132,7 @@ func run(program string) (*model.Package, error) {
|
|||
// parses the output as a model.Package.
|
||||
func runInDir(program []byte, dir string) (*model.Package, error) {
|
||||
// We use TempDir instead of TempFile so we can control the filename.
|
||||
tmpDir, err := ioutil.TempDir(dir, "gomock_reflect_")
|
||||
tmpDir, err := os.MkdirTemp(dir, "gomock_reflect_")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -149,7 +148,7 @@ func runInDir(program []byte, dir string) (*model.Package, error) {
|
|||
progBinary += ".exe"
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(tmpDir, progSource), program, 0600); err != nil {
|
||||
if err := os.WriteFile(filepath.Join(tmpDir, progSource), program, 0600); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -169,8 +168,8 @@ func runInDir(program []byte, dir string) (*model.Package, error) {
|
|||
if err := cmd.Run(); err != nil {
|
||||
sErr := buf.String()
|
||||
if strings.Contains(sErr, `cannot find package "."`) &&
|
||||
strings.Contains(sErr, "github.com/golang/mock/mockgen/model") {
|
||||
fmt.Fprint(os.Stderr, "Please reference the steps in the README to fix this error:\n\thttps://github.com/golang/mock#reflect-vendoring-error.")
|
||||
strings.Contains(sErr, "go.uber.org/mock/mockgen/model") {
|
||||
fmt.Fprint(os.Stderr, "Please reference the steps in the README to fix this error:\n\thttps://go.uber.org/mock#reflect-vendoring-error.\n")
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
|
@ -188,6 +187,7 @@ type reflectData struct {
|
|||
// gob encoding of a model.Package to standard output.
|
||||
// JSON doesn't work because of the model.Type interface.
|
||||
var reflectProgram = template.Must(template.New("program").Parse(`
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -198,7 +198,7 @@ import (
|
|||
"path"
|
||||
"reflect"
|
||||
|
||||
"github.com/golang/mock/mockgen/model"
|
||||
"go.uber.org/mock/mockgen/model"
|
||||
|
||||
pkg_ {{printf "%q" .ImportPath}}
|
||||
)
|
|
@ -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.
|
||||
|
@ -11,9 +11,6 @@
|
|||
// 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.
|
||||
//
|
||||
|
||||
// +build go1.12
|
||||
|
||||
package main
|
||||
|
||||
|
@ -31,5 +28,4 @@ func printModuleVersion() {
|
|||
"GO111MODULE=on when running 'go get' in order to use specific " +
|
||||
"version of the binary.")
|
||||
}
|
||||
|
||||
}
|
|
@ -154,10 +154,6 @@ github.com/gogo/protobuf/vanity/command
|
|||
# github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
|
||||
## explicit
|
||||
github.com/golang/groupcache/lru
|
||||
# github.com/golang/mock v1.6.0
|
||||
## explicit; go 1.11
|
||||
github.com/golang/mock/mockgen
|
||||
github.com/golang/mock/mockgen/model
|
||||
# github.com/golang/protobuf v1.5.3
|
||||
## explicit; go 1.9
|
||||
github.com/golang/protobuf/jsonpb
|
||||
|
@ -575,6 +571,8 @@ go.uber.org/atomic
|
|||
# go.uber.org/mock v0.4.0
|
||||
## explicit; go 1.20
|
||||
go.uber.org/mock/gomock
|
||||
go.uber.org/mock/mockgen
|
||||
go.uber.org/mock/mockgen/model
|
||||
# go.uber.org/multierr v1.8.0
|
||||
## explicit; go 1.14
|
||||
go.uber.org/multierr
|
||||
|
|
Loading…
Reference in New Issue