Beispiel #1
0
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
}
Beispiel #2
0
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
}
Beispiel #3
0
// 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
}
Beispiel #4
0
// 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())
	}
}
Beispiel #5
0
// 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
}
Beispiel #6
0
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
}
Beispiel #7
0
// 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
}
Beispiel #8
0
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
}
Beispiel #9
0
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
}
Beispiel #10
0
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
}
Beispiel #11
0
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
}
Beispiel #12
0
func hasLastError(t reflect.Type) bool {
	N := t.NumOut()
	if N == 0 {
		return false
	}
	return t.Out(N-1) == errorType
}
Beispiel #13
0
// 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
}
Beispiel #14
0
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
}
Beispiel #15
0
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
}
Beispiel #16
0
// 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
}
Beispiel #17
0
// 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
}
Beispiel #18
0
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)
}
Beispiel #19
0
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
}
Beispiel #20
0
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
}
Beispiel #21
0
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
}
Beispiel #22
0
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
}
Beispiel #23
0
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
}
Beispiel #24
0
Datei: funcs.go Projekt: sreis/go
// 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
}
Beispiel #25
0
// 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))
}
Beispiel #26
0
func functionArgRetTypes(funt reflect.Type) (targs, tout []reflect.Type) {
	targs = make([]reflect.Type, funt.NumIn())
	for i := range targs {
		targs[i] = funt.In(i)
	}
	tout = make([]reflect.Type, funt.NumOut())
	for i := range tout {
		tout[i] = funt.Out(i)
	}
	return
}
Beispiel #27
0
// makeZeroReturnValues creates a []interface{} containing appropriate zero
// values for returning from the supplied method type.
func makeZeroReturnValues(signature reflect.Type) []interface{} {
	result := make([]interface{}, signature.NumOut())

	for i, _ := range result {
		outType := signature.Out(i)
		zeroVal := reflect.Zero(outType)
		result[i] = zeroVal.Interface()
	}

	return result
}
Beispiel #28
0
func assertValidFetcher(t reflect.Type) {
	if t.Kind() != reflect.Func {
		panic(fmt.Sprintf("rcache: Fetcher must be a function, got [%v]", t))
	}
	if t.NumIn() != 1 {
		panic(fmt.Sprintf("rcache: Fetcher must be function with one arg, has %d [%v]", t.NumIn(), t))
	}
	if t.NumOut() != 2 || t.Out(0) != byteArrayType || t.Out(1) != errorType {
		panic(fmt.Sprintf("rcache: Fetcher must be function that returns ([]byte, error), has %d [%v]", t.NumOut(), t))
	}
}
Beispiel #29
0
// ForeachResult 遍历instance所有返回值,instance必须是函数类型
func ForeachResult(instance reflect.Type, solve func(result reflect.Type) error) error {
	if instance.Kind() == reflect.Func {
		for i := 0; i < instance.NumOut(); i++ {
			var err = solve(instance.Out(i))
			if err != nil {
				return err
			}
		}
		return nil
	}
	return ErrorParamNotFunc.Format(instance.String()).Error()
}
Beispiel #30
0
func checkFunctionSignatureNums(t reflect.Type, args, results int) error {
	if t.Kind() != reflect.Func {
		return fmt.Errorf("Expected a function but got a %s", t)
	}
	if t.NumIn() != args {
		return fmt.Errorf("Expected %d function arguments, got %d", args, t.NumIn())
	}
	if t.NumOut() != results {
		return fmt.Errorf("Expected %d function results, got %d", results, t.NumOut())
	}
	return nil
}