func FormatFuncArguments(t reflect.Type) (decl string) { decl = "(" in := make([]string, t.NumIn()) for i := range in { in[i] = ValType(t.In(i)) } decl += strings.Join(in, ",") + ")" out := make([]string, t.NumOut()) if len(out) > 0 { for i := range out { out[i] = ValType(t.Out(i)) } s := strings.Join(out, ",") if len(out) != 1 { s = "(" + s + ")" } decl += " " + s } return }
// Add all necessary imports for the type, recursing as appropriate. func addImportsForType(imports importMap, t reflect.Type) { // Add any import needed for the type itself. addImportForType(imports, t) // Handle special cases where recursion is needed. switch t.Kind() { case reflect.Array, reflect.Chan, reflect.Ptr, reflect.Slice: addImportsForType(imports, t.Elem()) case reflect.Func: // Input parameters. for i := 0; i < t.NumIn(); i++ { addImportsForType(imports, t.In(i)) } // Return values. for i := 0; i < t.NumOut(); i++ { addImportsForType(imports, t.Out(i)) } case reflect.Map: addImportsForType(imports, t.Key()) addImportsForType(imports, t.Elem()) } }
func typeString_FuncOrMethod( name string, t reflect.Type, pkgPath string) (s string) { // Deal with input types. var in []string for i := 0; i < t.NumIn(); i++ { in = append(in, typeString(t.In(i), pkgPath)) } // And output types. var out []string for i := 0; i < t.NumOut(); i++ { out = append(out, typeString(t.Out(i), pkgPath)) } // Put it all together. s = fmt.Sprintf( "%s(%s) (%s)", name, strings.Join(in, ", "), strings.Join(out, ", ")) return }
func OutTypes(fnType reflect.Type) []reflect.Type { var types []reflect.Type for i := 0; i < fnType.NumOut(); i++ { types = append(types, fnType.Out(i)) } return types }
// Note: Methods take the receiver as the first argument, which the want // signature doesn't include. func sigMatches(got, want reflect.Type) bool { nin := want.NumIn() if got.NumIn()-1 != nin { return false } nout := want.NumOut() if got.NumOut() != nout { return false } for i := 0; i < nin; i++ { if got.In(i+1) != want.In(i) { return false } } for i := 0; i < nout; i++ { if got.Out(i) != want.Out(i) { return false } } return true }
func checkHandleType(t reflect.Type) (*requestType, error) { if t.Kind() != reflect.Func { return nil, errgo.New("not a function") } if n := t.NumIn(); n != 1 && n != 2 { return nil, errgo.Newf("has %d parameters, need 1 or 2", t.NumIn()) } if t.NumOut() > 2 { return nil, errgo.Newf("has %d result parameters, need 0, 1 or 2", t.NumOut()) } if t.NumIn() == 2 { if t.In(0) != paramsType { return nil, errgo.Newf("first argument is %v, need httprequest.Params", t.In(0)) } } else { if t.In(0) == paramsType { return nil, errgo.Newf("no argument parameter after Params argument") } } pt, err := getRequestType(t.In(t.NumIn() - 1)) if err != nil { return nil, errgo.Notef(err, "last argument cannot be used for Unmarshal") } if t.NumOut() > 0 { // func(p Params, arg *ArgT) error // func(p Params, arg *ArgT) (ResultT, error) if et := t.Out(t.NumOut() - 1); et != errorType { return nil, errgo.Newf("final result parameter is %s, need error", et) } } return pt, nil }
func makeClosure(fv reflect.Value, ft reflect.Type) *function { fn := &function{ call: fv, } var rt = Void var at []Type if n := ft.NumOut(); n != 0 { rt = makeRetType(reflect.New(ft.Out(0))) } if n := ft.NumIn(); n != 0 { at = make([]Type, n) for i := 0; i != n; i++ { at[i] = makeArgType(reflect.Zero(ft.In(i))) } } fn.Interface = Prepare(rt, at...) if err := constructClosure(fn); err != nil { panic(err) } runtime.SetFinalizer(fn, destroyClosure) return fn }
func newTypeFromFactoryFunction(function interface{}, factoryType reflect.Type, parameters []interface{}) TypeFactory { if factoryType.NumOut() != 1 { return newInvalidType(fmt.Errorf("invalid number of return parameters: %d", factoryType.NumOut())) } kindOfGeneratedType := factoryType.Out(0).Kind() if kindOfGeneratedType != reflect.Interface && kindOfGeneratedType != reflect.Ptr { return newInvalidType(fmt.Errorf("return parameter is no interface or pointer but a %v", kindOfGeneratedType)) } if factoryType.IsVariadic() { if factoryType.NumIn() > len(parameters) { return newInvalidType(fmt.Errorf("invalid number of input parameters for variadic function: got %d but expected at least %d", len(parameters), factoryType.NumIn())) } } else { if factoryType.NumIn() != len(parameters) { return newInvalidType(fmt.Errorf("invalid number of input parameters: got %d but expected %d", len(parameters), factoryType.NumIn())) } } t := &typeFactory{ factory: reflect.ValueOf(function), factoryType: factoryType, } var err error t.factoryArguments, err = buildFactoryCallArguments(factoryType, parameters) if err != nil { return newInvalidType(err) } return t }
// Verifies whether a deep-copy function has a correct signature. func verifyDeepCopyFunctionSignature(ft reflect.Type) error { if ft.Kind() != reflect.Func { return fmt.Errorf("expected func, got: %v", ft) } if ft.NumIn() != 3 { return fmt.Errorf("expected three 'in' params, got $v", ft) } if ft.NumOut() != 1 { return fmt.Errorf("expected one 'out' param, got %v", ft) } if ft.In(1).Kind() != reflect.Ptr { return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft) } if ft.In(1).Elem() != ft.In(0) { return fmt.Errorf("expected 'in' param 0 the same as param 1, got: %v", ft) } var forClonerType Cloner if expected := reflect.TypeOf(&forClonerType); ft.In(2) != expected { return fmt.Errorf("expected '%v' arg for 'in' param 2, got: '%v'", expected, ft.In(2)) } var forErrorType error // This convolution is necessary, otherwise TypeOf picks up on the fact // that forErrorType is nil errorType := reflect.TypeOf(&forErrorType).Elem() if ft.Out(0) != errorType { return fmt.Errorf("expected error return, got: %v", ft) } return nil }
func checkFunc(fnType reflect.Type) (bool, error) { var state State foundState := 0 nin := fnType.NumIn() for i := 0; i < nin; i++ { if fnType.In(i) == reflect.TypeOf(state) { foundState++ } else if fnType.In(i) == reflect.TypeOf(&state) { return false, fmt.Errorf("raw function can not use `*State' as arg, instead using `State'") } } wrongRawFunc := false if foundState > 1 { wrongRawFunc = true } else if foundState == 1 { nout := fnType.NumOut() if nin != 1 || nout != 1 { wrongRawFunc = true } else { if fnType.Out(0).Kind() != reflect.Int { wrongRawFunc = true } } } if wrongRawFunc { return false, fmt.Errorf("raw function must be type: `func(State) int'") } return true, nil }
func hasLastError(t reflect.Type) bool { N := t.NumOut() if N == 0 { return false } return t.Out(N-1) == errorType }
func (p *MethodMetadata) IsEqual(t reflect.Type) bool { if t.ConvertibleTo(p.Method.Type) { return false } baseIndex := 0 if p.Method.Index >= 0 { baseIndex = 1 } if t.NumIn()+baseIndex != p.Method.Type.NumIn() { return false } for i := 0; i < p.Method.Type.NumIn()-baseIndex; i++ { if p.Method.Type.In(baseIndex+i) != t.In(i) { return false } } for i := 0; i < p.Method.Type.NumOut(); i++ { if p.Method.Type.Out(baseIndex+i) != t.Out(i) { return false } } return true }
func (ms *GobMarshaller) Prepare(name string, fn interface{}) (err error) { var ( fT reflect.Type ) // Gob needs to register type before encode/decode if fT = reflect.TypeOf(fn); fT.Kind() != reflect.Func { err = fmt.Errorf("fn is not a function but %v", fn) return } reg := func(v reflect.Value) (err error) { if !v.CanInterface() { err = fmt.Errorf("Can't convert to value in input of %v for name:%v", fn, name) return } gob.Register(v.Interface()) return } for i := 0; i < fT.NumIn(); i++ { // create a zero value of the type of parameters if err = reg(reflect.Zero(fT.In(i))); err != nil { return } } for i := 0; i < fT.NumOut(); i++ { if err = reg(reflect.Zero(fT.Out(i))); err != nil { return } } return }
func returns(f reflect.Type) []reflect.Type { out := make([]reflect.Type, f.NumOut()) for i := 0; i < f.NumOut(); i++ { out[i] = f.Out(i) } return out }
// A version of Invoke that does error checking, used by both public methods. func (a *returnAction) buildInvokeResult( sig reflect.Type) (res []interface{}, err error) { // Check the length of the return value. numOut := sig.NumOut() numVals := len(a.returnVals) if numOut != numVals { err = errors.New( fmt.Sprintf("Return given %d vals; expected %d.", numVals, numOut)) return } // Attempt to coerce each return value. res = make([]interface{}, numOut) for i, val := range a.returnVals { resType := sig.Out(i) res[i], err = a.coerce(val, resType) if err != nil { res = nil err = errors.New(fmt.Sprintf("Return: arg %d: %v", i, err)) return } } return }
func function2Func(in *reflect.Value, t reflect.Type) { fn := in.MethodByName("Call") wrap := func(args []reflect.Value) (results []reflect.Value) { ret := fn.Call(args)[0] n := t.NumOut() if n == 0 { return } if n == 1 { if t.Out(0) != typeIntf { ret = ret.Elem() } return []reflect.Value{ret} } if ret.Kind() != reflect.Slice || ret.Len() != n { panic(fmt.Sprintf("unexpected return value count, we need `%d` values", n)) } results = make([]reflect.Value, n) for i := 0; i < n; i++ { result := ret.Index(i) if t.Out(i) != typeIntf { result = result.Elem() } results[i] = result } return } *in = reflect.MakeFunc(t, wrap) }
// unify attempts to satisfy a pair of types, where the `param` type is the // expected type of a function argument and the `input` type is the known // type of a function argument. The `param` type may be parametric (that is, // it may contain a type that is convertible to TypeVariable) but the // `input` type may *not* be parametric. // // Any failure to unify the two types results in a panic. // // The end result of unification is a type environment: a set of substitutions // from type variable to a Go type. func (tp typePair) unify(param, input reflect.Type) error { if tyname := tyvarName(input); len(tyname) > 0 { return tp.error("Type variables are not allowed in the types of " + "arguments.") } if tyname := tyvarName(param); len(tyname) > 0 { if cur, ok := tp.tyenv[tyname]; ok && cur != input { return tp.error("Type variable %s expected type '%s' but got '%s'.", tyname, cur, input) } else if !ok { tp.tyenv[tyname] = input } return nil } if param.Kind() != input.Kind() { return tp.error("Cannot unify different kinds of types '%s' and '%s'.", param, input) } switch param.Kind() { case reflect.Array: return tp.unify(param.Elem(), input.Elem()) case reflect.Chan: if param.ChanDir() != input.ChanDir() { return tp.error("Cannot unify '%s' with '%s' "+ "(channel directions are different: '%s' != '%s').", param, input, param.ChanDir(), input.ChanDir()) } return tp.unify(param.Elem(), input.Elem()) case reflect.Func: if param.NumIn() != input.NumIn() || param.NumOut() != input.NumOut() { return tp.error("Cannot unify '%s' with '%s'.", param, input) } for i := 0; i < param.NumIn(); i++ { if err := tp.unify(param.In(i), input.In(i)); err != nil { return err } } for i := 0; i < param.NumOut(); i++ { if err := tp.unify(param.Out(i), input.Out(i)); err != nil { return err } } case reflect.Map: if err := tp.unify(param.Key(), input.Key()); err != nil { return err } return tp.unify(param.Elem(), input.Elem()) case reflect.Ptr: return tp.unify(param.Elem(), input.Elem()) case reflect.Slice: return tp.unify(param.Elem(), input.Elem()) } // The only other container types are Interface and Struct. // I am unsure about what to do with interfaces. Mind is fuzzy. // Structs? I don't think it really makes much sense to use type // variables inside of them. return nil }
// Verifies whether a conversion function has a correct signature. func verifyConversionFunctionSignature(ft reflect.Type) error { if ft.Kind() != reflect.Func { return fmt.Errorf("expected func, got: %v", ft) } if ft.NumIn() != 3 { return fmt.Errorf("expected three 'in' params, got: %v", ft) } if ft.NumOut() != 1 { return fmt.Errorf("expected one 'out' param, got: %v", ft) } if ft.In(0).Kind() != reflect.Ptr { return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft) } if ft.In(1).Kind() != reflect.Ptr { return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft) } scopeType := Scope(nil) if e, a := reflect.TypeOf(&scopeType).Elem(), ft.In(2); e != a { return fmt.Errorf("expected '%v' arg for 'in' param 2, got '%v' (%v)", e, a, ft) } var forErrorType error // This convolution is necessary, otherwise TypeOf picks up on the fact // that forErrorType is nil. errorType := reflect.TypeOf(&forErrorType).Elem() if ft.Out(0) != errorType { return fmt.Errorf("expected error return, got: %v", ft) } return nil }
func getMethod(methodType reflect.Type, fn reflect.Value) *methodWrapper { if methodType.NumOut() != 1 { return nil } if methodType.Out(0) != typeOfError { return nil } if methodType.NumIn() == 2 { // Method needs two ins: receiver, *Conn. if methodType.In(1) != typeOfConn { return nil } return &methodWrapper{plain: true, fn: fn} } if methodType.NumIn() == 4 { // Method needs four ins: receiver, *Conn, request, *reply. if methodType.In(1) != typeOfConn { return nil } if methodType.In(3).Kind() != reflect.Ptr { return nil } return &methodWrapper{ plain: false, fn: fn, requestType: methodType.In(2), responseType: methodType.In(3).Elem()} } return nil }
func methSigMatches(got reflect.Type, _want interface{}) error { // Note: Methods take the receiver as the first argument, which the want // signature doesn't include. if got.NumIn() == 0 { // The receiver is missing! return fmt.Errorf("Method without reciever!") } want := reflect.TypeOf(_want) if got.NumIn()-1 != want.NumIn() { return fmt.Errorf("Method should have %d arguments, not %d", want.NumIn(), got.NumIn()-1) } if got.NumOut() != want.NumOut() { return fmt.Errorf("Method should have %d return values, not %d", want.NumOut(), got.NumOut()) } for i := 0; i < want.NumIn(); i++ { if got.In(i+1) != want.In(i) { return fmt.Errorf("Method argument %d should be %v, not %v", i+1, want.In(i), got.In(i+1)) } } for i := 0; i < want.NumOut(); i++ { if got.Out(i) != want.Out(i) { return fmt.Errorf("Method return value %d should be %v, not %v", i+1, want.Out(i), got.Out(i)) } } return nil }
// verifyHandler ensures that the given t is a function with the following signature: // func(json.Context, *ArgType)(*ResType, error) func verifyHandler(t reflect.Type) error { if t.NumIn() != 2 || t.NumOut() != 2 { return fmt.Errorf("handler should be of format func(json.Context, *ArgType) (*ResType, error)") } isStructPtr := func(t reflect.Type) bool { return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct } isMap := func(t reflect.Type) bool { return t.Kind() == reflect.Map && t.Key().Kind() == reflect.String } validateArgRes := func(t reflect.Type, name string) error { if !isStructPtr(t) && !isMap(t) { return fmt.Errorf("%v should be a pointer to a struct, or a map[string]interface{}", name) } return nil } if t.In(0) != typeOfContext { return fmt.Errorf("arg0 should be of type json.Context") } if err := validateArgRes(t.In(1), "second argument"); err != nil { return err } if err := validateArgRes(t.Out(0), "first return value"); err != nil { return err } if !t.Out(1).AssignableTo(typeOfError) { return fmt.Errorf("second return value should be an error") } return nil }
// t's Kind must be a reflect.Func. func funcArgsFromType(t reflect.Type) (in []*Parameter, variadic *Parameter, out []*Parameter, err error) { nin := t.NumIn() if t.IsVariadic() { nin-- } var p *Parameter for i := 0; i < nin; i++ { p, err = parameterFromType(t.In(i)) if err != nil { return } in = append(in, p) } if t.IsVariadic() { p, err = parameterFromType(t.In(nin).Elem()) if err != nil { return } variadic = p } for i := 0; i < t.NumOut(); i++ { p, err = parameterFromType(t.Out(i)) if err != nil { return } out = append(out, p) } return }
func (s *state) checkFuncReturn(name string, t reflect.Type) { // Check the number of return values if t.NumOut() == 0 || t.NumOut() == 1 || (t.NumOut() == 2 && t.Out(1) == errorType) { return } s.errorf("can't handle multiple returns from function %s", name) }
func funcIsBypass(t reflect.Type) bool { if t.NumIn() == 1 && t.NumOut() == 1 && t.In(0) == refTypeLStatePtr && t.Out(0) == refTypeInt { return true } if t.NumIn() == 2 && t.NumOut() == 1 && t.In(1) == refTypeLStatePtr && t.Out(0) == refTypeInt { return true } return false }
func goodFunc(typ reflect.Type) bool { switch { case typ.NumOut() == 1: return true case typ.NumOut() == 2 && typ.Out(1) == rferrorType: return true } return false }
func (f *FuncUtil) getReturnTypes(t reflect.Type) []reflect.Type { if t.NumOut() == 0 { return nil } rets := []reflect.Type{} for i := 0; i < t.NumOut(); i++ { rets = append(rets, t.Out(i)) } return rets }
func getOutputs(ft reflect.Type) []reflect.Type { numOut := ft.NumOut() outputs := make([]reflect.Type, numOut) for i := 0; i < numOut; i++ { outputs[i] = ft.Out(i) } return outputs }
func (me *MethodInvoker) decipherOutputs(mt reflect.Type) { me.outCount = mt.NumOut() me.outParams = make([]string, mt.NumOut()) for i := 0; i < mt.NumOut(); i++ { pt := mt.Out(i) me.outParams[i] = getSymbolFromType(pt) } }
// goodFunc reports whether the function or method has the right result signature. func goodFunc(typ reflect.Type) bool { // We allow functions with 1 result or 2 results where the second is an error. switch { case typ.NumOut() == 1: return true case typ.NumOut() == 2 && typ.Out(1) == errorType: return true } return false }
// isPubSub tests whether the given method has as as first argument a context.Context // and returns the pair (Subscription, error) func isPubSub(methodType reflect.Type) bool { // numIn(0) is the receiver type if methodType.NumIn() < 2 || methodType.NumOut() != 2 { return false } return isContextType(methodType.In(1)) && isSubscriptionType(methodType.Out(0)) && isErrorType(methodType.Out(1)) }