Close gaps in public boundary checks
This commit is contained in:
@@ -63,6 +63,55 @@ import "example.test/facade/internal/hidden"
|
||||
type privateState struct { value hidden.Value }
|
||||
type Public struct { state privateState }
|
||||
type Option interface { apply(*privateState) }
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "returned private type method is rejected",
|
||||
source: `package facade
|
||||
import "example.test/facade/internal/hidden"
|
||||
type result struct{}
|
||||
func (result) Leak() hidden.Value { return hidden.Value{} }
|
||||
func New() result { return result{} }
|
||||
`,
|
||||
wantReject: true,
|
||||
},
|
||||
{
|
||||
name: "reachable private pointer method is rejected",
|
||||
source: `package facade
|
||||
import "example.test/facade/internal/hidden"
|
||||
type result struct{}
|
||||
func (*result) Leak() hidden.Value { return hidden.Value{} }
|
||||
type Public struct { Result result }
|
||||
`,
|
||||
wantReject: true,
|
||||
},
|
||||
{
|
||||
name: "internal generic argument is rejected",
|
||||
source: `package facade
|
||||
import "example.test/facade/internal/hidden"
|
||||
type Box[T any] struct{}
|
||||
func New() Box[hidden.Value] { return Box[hidden.Value]{} }
|
||||
`,
|
||||
wantReject: true,
|
||||
},
|
||||
{
|
||||
name: "internal alias argument is rejected",
|
||||
source: `package facade
|
||||
import "example.test/facade/internal/hidden"
|
||||
type Box[T any] = struct{}
|
||||
func New() Box[hidden.Value] { return Box[hidden.Value]{} }
|
||||
`,
|
||||
wantReject: true,
|
||||
},
|
||||
{
|
||||
name: "public generic argument and recursive methods are allowed",
|
||||
source: `package facade
|
||||
type Value struct{}
|
||||
type Box[T any] struct{}
|
||||
func New() Box[Value] { return Box[Value]{} }
|
||||
type result struct{}
|
||||
func NewResult() result { return result{} }
|
||||
func (*result) Next() *result { return nil }
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -178,6 +227,8 @@ func publicSurfaceViolations(pkg *types.Package, modulePath string) []string {
|
||||
var inspect func(types.Type, string)
|
||||
var inspectTuple func(*types.Tuple, string)
|
||||
var inspectTypeParams func(*types.TypeParamList, string)
|
||||
var inspectTypeArgs func(*types.TypeList, string)
|
||||
var inspectMethods func(*types.Named, string)
|
||||
inspect = func(typ types.Type, where string) {
|
||||
if typ == nil || seen[typ] {
|
||||
return
|
||||
@@ -186,6 +237,7 @@ func publicSurfaceViolations(pkg *types.Package, modulePath string) []string {
|
||||
|
||||
switch value := typ.(type) {
|
||||
case *types.Named:
|
||||
inspectTypeArgs(value.TypeArgs(), where)
|
||||
if isInternalPackage(value.Obj().Pkg(), modulePath) {
|
||||
record(where, value)
|
||||
return
|
||||
@@ -193,8 +245,10 @@ func publicSurfaceViolations(pkg *types.Package, modulePath string) []string {
|
||||
if value.Obj().Pkg() == pkg {
|
||||
inspectTypeParams(value.TypeParams(), where)
|
||||
inspect(value.Underlying(), where)
|
||||
inspectMethods(value, where)
|
||||
}
|
||||
case *types.Alias:
|
||||
inspectTypeArgs(value.TypeArgs(), where)
|
||||
if isInternalPackage(value.Obj().Pkg(), modulePath) {
|
||||
record(where, value)
|
||||
return
|
||||
@@ -258,21 +312,12 @@ func publicSurfaceViolations(pkg *types.Package, modulePath string) []string {
|
||||
inspect(params.At(index), where)
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range pkg.Scope().Names() {
|
||||
if !token.IsExported(name) {
|
||||
continue
|
||||
}
|
||||
object := pkg.Scope().Lookup(name)
|
||||
inspect(object.Type(), name)
|
||||
typeName, ok := object.(*types.TypeName)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
named, ok := types.Unalias(typeName.Type()).(*types.Named)
|
||||
if !ok {
|
||||
continue
|
||||
inspectTypeArgs = func(args *types.TypeList, where string) {
|
||||
for index := 0; index < args.Len(); index++ {
|
||||
inspect(args.At(index), where)
|
||||
}
|
||||
}
|
||||
inspectMethods = func(named *types.Named, where string) {
|
||||
for _, methodSet := range []*types.MethodSet{types.NewMethodSet(named), types.NewMethodSet(types.NewPointer(named))} {
|
||||
for index := 0; index < methodSet.Len(); index++ {
|
||||
selection := methodSet.At(index)
|
||||
@@ -281,13 +326,19 @@ func publicSurfaceViolations(pkg *types.Package, modulePath string) []string {
|
||||
continue
|
||||
}
|
||||
if isInternalPackage(method.Pkg(), modulePath) {
|
||||
record(name+"."+method.Name(), method.Type())
|
||||
record(where+"."+method.Name(), selection.Type())
|
||||
continue
|
||||
}
|
||||
inspect(method.Type(), name+"."+method.Name())
|
||||
inspect(selection.Type(), where+"."+method.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range pkg.Scope().Names() {
|
||||
if token.IsExported(name) {
|
||||
inspect(pkg.Scope().Lookup(name).Type(), name)
|
||||
}
|
||||
}
|
||||
sort.Strings(violations)
|
||||
return compactStrings(violations)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user