Skip to content

Commit 97eb460

Browse files
committed
issue-1092: implement verification for private types
1 parent 766bca7 commit 97eb460

File tree

6 files changed

+259
-0
lines changed

6 files changed

+259
-0
lines changed

.mockery_matryer.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ packages:
4040
OutputDirWithSamePkgNameAsSrc:
4141
config:
4242
dir: "{{.InterfaceDir}}/output_dir"
43+
github.com/vektra/mockery/v3/internal/fixtures/private_types:
44+
config:
45+
all: true
46+
pkgname: privatetypes_test

go.work.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,7 @@ cloud.google.com/go/speech v1.20.1/go.mod h1:wwolycgONvfz2EDU8rKuHRW3+wc9ILPsAWo
678678
cloud.google.com/go/speech v1.21.1/go.mod h1:E5GHZXYQlkqWQwY5xRSLHw2ci5NMQNG52FfMU1aZrIA=
679679
cloud.google.com/go/speech v1.24.0 h1:3j+WpeBY57C0FDJxg317vpKgOLjL/kNxlcNPGSqXkqE=
680680
cloud.google.com/go/speech v1.24.0/go.mod h1:HcVyIh5jRXM5zDMcbFCW+DF2uK/MSGN6Rastt6bj1ic=
681+
cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA=
681682
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
682683
cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ=
683684
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
@@ -900,6 +901,7 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
900901
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
901902
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
902903
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
904+
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
903905
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
904906
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
905907
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
@@ -1039,6 +1041,7 @@ github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2I
10391041
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
10401042
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
10411043
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
1044+
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
10421045
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
10431046
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
10441047
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
@@ -1463,6 +1466,7 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
14631466
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
14641467
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
14651468
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
1469+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
14661470
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
14671471
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
14681472
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
@@ -1509,11 +1513,13 @@ google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9
15091513
google.golang.org/api v0.189.0/go.mod h1:FLWGJKb0hb+pU2j+rJqwbnsF+ym+fQs73rbJ+KAUgy8=
15101514
google.golang.org/api v0.192.0 h1:PljqpNAfZaaSpS+TnANfnNAXKdzHM/B9bKhwRlo7JP0=
15111515
google.golang.org/api v0.192.0/go.mod h1:9VcphjvAxPKLmSxVSzPlSRXy/5ARMEw5bf58WoVXafQ=
1516+
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
15121517
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
15131518
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
15141519
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
15151520
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
15161521
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
1522+
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8=
15171523
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
15181524
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
15191525
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=

internal/cmd/mockery.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,28 @@ func (i *InterfaceCollection) Append(ctx context.Context, iface *internal.Interf
178178
return nil
179179
}
180180

181+
func isSamePackage(src *packages.Package, cfg *config.Config) bool {
182+
if cfg.PkgName != nil && src.Name != *cfg.PkgName {
183+
return false
184+
}
185+
186+
if cfg.InPackage != nil && *cfg.InPackage {
187+
return true
188+
}
189+
190+
if cfg.Dir != nil {
191+
if *cfg.Dir == "." {
192+
return true
193+
}
194+
195+
if absPath, err := filepath.Abs(*cfg.Dir); err == nil && src.Dir == absPath {
196+
return true
197+
}
198+
}
199+
200+
return false
201+
}
202+
181203
func (r *RootApp) Run() error {
182204
remoteTemplateCache := make(map[string]*internal.RemoteTemplate)
183205

@@ -285,6 +307,11 @@ func (r *RootApp) Run() error {
285307
log.Err(err).Msg("Can't parse config templates for interface")
286308
return err
287309
}
310+
311+
if !isSamePackage(iface.Pkg, ifaceConfig) && (!iface.IsExported() || iface.ContainsUnexportedTypes()) {
312+
continue
313+
}
314+
288315
filePath := ifaceConfig.FilePath()
289316
ifaceLog.Info().Str("collection", filePath).Msg("adding interface to collection")
290317

internal/fixtures/private_types/mocks_matryer_privatetypes_test.go

Lines changed: 85 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package privatetypes
2+
3+
type (
4+
private int
5+
6+
privateInterface interface {
7+
A()
8+
}
9+
10+
PrivateMethod interface {
11+
a()
12+
}
13+
14+
PrivateParam interface {
15+
B(private)
16+
}
17+
18+
PrivateReturn interface {
19+
C() private
20+
}
21+
22+
Public interface {
23+
A()
24+
}
25+
26+
PrivateVariadic interface {
27+
A(...private)
28+
}
29+
30+
PrivateChannel interface {
31+
A(chan private)
32+
}
33+
34+
PrivateMapValue interface {
35+
A(map[string]private)
36+
}
37+
38+
PrivateMapKey interface {
39+
A(map[private]string)
40+
}
41+
42+
PrivateSlice interface {
43+
A([]private)
44+
}
45+
46+
PrivatePointer interface {
47+
A(*private)
48+
}
49+
)

internal/interface.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package internal
22

33
import (
44
"go/ast"
5+
"go/token"
56

67
"github.com/vektra/mockery/v3/config"
78
"golang.org/x/tools/go/packages"
@@ -36,3 +37,90 @@ func NewInterface(
3637
Config: config,
3738
}
3839
}
40+
41+
func isBuiltInType(name string) bool {
42+
switch name {
43+
case
44+
"any", "interface", "bool", "byte", "complex64", "complex128",
45+
"error", "float32", "float64", "int", "int8", "int16", "int32", "int64",
46+
"rune", "string", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr":
47+
return true
48+
default:
49+
return false
50+
}
51+
}
52+
53+
func isPrivateType(expr ast.Expr) bool {
54+
switch t := expr.(type) {
55+
case *ast.SelectorExpr:
56+
return false
57+
case *ast.Ident:
58+
if isBuiltInType(t.Name) {
59+
return false
60+
}
61+
return !token.IsExported(t.Name)
62+
case *ast.StarExpr:
63+
return isPrivateType(t.X)
64+
case *ast.Ellipsis:
65+
return isPrivateType(t.Elt)
66+
case *ast.ChanType:
67+
return isPrivateType(t.Value)
68+
case *ast.MapType:
69+
return isPrivateType(t.Key) || isPrivateType(t.Value)
70+
case *ast.ArrayType:
71+
return isPrivateType(t.Elt)
72+
default:
73+
return false
74+
}
75+
}
76+
77+
func containsPrivateTypesInInterface(ts ast.Expr) bool {
78+
iface, ok := ts.(*ast.InterfaceType)
79+
if !ok {
80+
return false
81+
}
82+
83+
for _, field := range iface.Methods.List {
84+
if len(field.Names) == 0 {
85+
if private := containsPrivateTypesInInterface(field.Type); private {
86+
return true
87+
}
88+
}
89+
90+
for _, name := range field.Names {
91+
if !token.IsExported(name.Name) {
92+
return true
93+
}
94+
}
95+
96+
funcType, ok := field.Type.(*ast.FuncType)
97+
if !ok {
98+
continue
99+
}
100+
101+
if funcType.Params != nil {
102+
for _, p := range funcType.Params.List {
103+
if isPrivateType(p.Type) {
104+
return true
105+
}
106+
}
107+
}
108+
if funcType.Results != nil {
109+
for _, r := range funcType.Results.List {
110+
if isPrivateType(r.Type) {
111+
return true
112+
}
113+
}
114+
}
115+
}
116+
117+
return false
118+
}
119+
120+
func (i *Interface) ContainsUnexportedTypes() bool {
121+
return containsPrivateTypesInInterface(i.TypeSpec.Type)
122+
}
123+
124+
func (i *Interface) IsExported() bool {
125+
return token.IsExported(i.Name)
126+
}

0 commit comments

Comments
 (0)