diff --git a/builtin_test.go b/builtin_test.go index 0a46065a..d81bf590 100644 --- a/builtin_test.go +++ b/builtin_test.go @@ -634,6 +634,35 @@ func TestMethodAutoProperty(t *testing.T) { } } +func TestCheckSigFuncExObjects(t *testing.T) { + pkg := types.NewPackage("", "") + objs := []types.Object{ + types.NewFunc(0, pkg, "foo", types.NewSignatureType(nil, nil, nil, nil, nil, false)), + types.NewFunc(0, pkg, "bar", types.NewSignatureType(nil, nil, nil, nil, nil, false)), + } + named := types.NewNamed(types.NewTypeName(0, pkg, "named", nil), types.NewSignatureType(nil, nil, nil, nil, nil, false), nil) + fn := types.NewFunc(0, pkg, "fn", sigFuncEx(nil, nil, &TyOverloadFunc{objs})) + type testTyp struct { + } + tests := []struct { + name string + sig *types.Signature + count int + }{ + {"TyOverloadFunc", sigFuncEx(nil, nil, &TyOverloadFunc{objs}), 2}, + {"TyOverloadMethod", sigFuncEx(nil, nil, &TyOverloadMethod{objs}), 2}, + {"TyTemplateRecvMethod", sigFuncEx(nil, nil, &TyTemplateRecvMethod{types.NewParam(0, nil, "", tyInt)}), 1}, + {"TyTemplateRecvMethod", sigFuncEx(nil, nil, &TyTemplateRecvMethod{fn}), 2}, + {"TyOverloadNamed", sigFuncEx(nil, nil, &TyOverloadNamed{Types: []*types.Named{named}}), 1}, + } + for n, test := range tests { + typ, objs := CheckSigFuncExObjects(test.sig) + if typ == nil || len(objs) != test.count { + t.Fatalf("CheckSigFuncExObjects error: %v %v", n, test.name) + } + } +} + func TestHasAutoProperty(t *testing.T) { if HasAutoProperty(nil) { t.Fatal("nil has autoprop?") diff --git a/func_ext.go b/func_ext.go index 5508f882..421d9194 100644 --- a/func_ext.go +++ b/func_ext.go @@ -43,6 +43,38 @@ func CheckFuncEx(sig *types.Signature) (ext TyFuncEx, ok bool) { return } +// CheckSigFuncExObjects retruns hide recv type and objects from func($overloadArgs ...interface{$overloadMethod()}) +// The return type can be OverloadType (*TyOverloadFunc, *TyOverloadMethod, *TyOverloadNamed) or +// *TyTemplateRecvMethod. +func CheckSigFuncExObjects(sig *types.Signature) (typ types.Type, objs []types.Object) { + if ext, ok := CheckSigFuncEx(sig); ok { + switch t := ext.(type) { + case *TyOverloadFunc: + typ, objs = t, t.Funcs + case *TyOverloadMethod: + typ, objs = t, t.Methods + case *TyTemplateRecvMethod: + typ = t + if tsig, ok := t.Func.Type().(*types.Signature); ok { + if ex, ok := CheckSigFuncEx(tsig); ok { + if t, ok := ex.(*TyOverloadFunc); ok { + objs = t.Funcs + break + } + } + } + objs = []types.Object{t.Func} + case *TyOverloadNamed: + typ = t + objs = make([]types.Object, len(t.Types)) + for i, typ := range t.Types { + objs[i] = typ.Obj() + } + } + } + return +} + const ( overloadArgs = "__gop_overload_args__" overloadMethod = "_"