func checkLastArg(handlerType *reflect.FuncType) bool { index := handlerType.NumIn() - 1 if a0, ok := handlerType.In(index).(*reflect.ChanType); ok { typ := a0.Elem() if typ == reflect.Typeof(true) { return true } } return false }
//should the context be passed to the handler? func requiresContext(handlerType *reflect.FuncType) bool { //if the method doesn't take arguments, no if handlerType.NumIn() == 0 { return false } //if the first argument is not a pointer, no a0, ok := handlerType.In(0).(*reflect.PtrType) if !ok { return false } //if the first argument is a context, yes if a0.Elem() == contextType { return true } //another case -- the first argument is a method receiver, and the //second argument is a web.Context if handlerType.NumIn() > 1 { a1, ok := handlerType.In(1).(*reflect.PtrType) if !ok { return false } if a1.Elem() == contextType { return true } } return false }
// arbitraryValues writes Values to args such that args contains Values // suitable for calling f. func arbitraryValues(args []reflect.Value, f *reflect.FuncType, config *Config, rand *rand.Rand) (err os.Error) { if config.Values != nil { config.Values(args, rand) return } for j := 0; j < len(args); j++ { var ok bool args[j], ok = Value(f.In(j), rand) if !ok { err = SetupError(fmt.Sprintf("cannot create arbitrary value of type %s for argument %d", f.In(j), j)) return } } return }
// Funkcja sprawdza zgodnosc typow argumentow. Jesli to konieczne konwertuje // argumenty do typu interface{}. Jesli to potrzebna, funkcja odpowiednio // dostosowuje args dla funkcji. func argsMatch(ft *reflect.FuncType, args *[]reflect.Value, method int) int { // Liczba arguemntow akceptowanych przez funkcje/metode num_in := ft.NumIn() - method // Sprawdzamy zgodnosc liczby argumentow i obecnosc funkcji dotdotdot var head_args, tail_args []reflect.Value if ft.DotDotDot() { num_in-- if len(*args) < num_in { return RUN_WRONG_ARG_NUM } head_args = (*args)[0:num_in] tail_args = (*args)[num_in:] } else { if num_in != len(*args) { return RUN_WRONG_ARG_NUM } head_args = *args } // Sprawdzamy zgodnosc typow poczatkowych argumentow funkcji for kk, av := range head_args { at := ft.In(kk + method) //fmt.Printf("DEB: ctx: %s, fun: %s\n", av.Type(), at) if at != av.Type() { // Sprawdzamy czy arguentem funkcji jest typ interface{} if it, ok := at.(*reflect.InterfaceType); ok && it.NumMethod() == 0 { // Zmieniamy typ argumentu przekazywanego do funkcji vi := av.Interface() head_args[kk] = reflect.NewValue(&vi).(*reflect.PtrValue).Elem() } else { return RUN_WRONG_ARG_TYP } } } if !ft.DotDotDot() { return RUN_OK } // Okreslamy typ argumentów zawartych w dotdotdot st := ft.In(ft.NumIn() - 1).(*reflect.SliceType) at := st.Elem() it, ok := at.(*reflect.InterfaceType) at_is_interface := (ok && it.NumMethod() == 0) // Przygotowujemy miejsce na argumenty ddd := reflect.MakeSlice(st, len(tail_args), cap(tail_args)) for kk, av := range tail_args { if at != av.Type() { // Sprawdzamy czy arguentem funkcji jest typ interface{} if at_is_interface { // Zmieniamy typ argumentu przekazywanego do funkcji vi := av.Interface() tail_args[kk] = reflect.NewValue(&vi).(*reflect.PtrValue).Elem() } else { return RUN_WRONG_ARG_TYP } } // Umieszczamy argument w ddd ddd.Elem(kk).SetValue(av) } // Zwracamy zmodyfikowana tablice argumentow *args = append(head_args, ddd) return RUN_OK }
// tryOneFunction is the common code for tryMethod and tryFunction. func tryOneFunction(pkg, firstArg, name string, typ *reflect.FuncType, rfn *reflect.FuncValue, args []interface{}) { // Any results? if typ.NumOut() == 0 { return // Nothing to do. } // Right number of arguments + results? if typ.NumIn()+typ.NumOut() != len(args) { return } // Right argument and result types? for i, a := range args { if i < typ.NumIn() { if !compatible(a, typ.In(i)) { return } } else { if !compatible(a, typ.Out(i-typ.NumIn())) { return } } } // Build the call args. argsVal := make([]reflect.Value, typ.NumIn()+typ.NumOut()) for i, a := range args { argsVal[i] = reflect.NewValue(a) } // Call the function and see if the results are as expected. resultVal := rfn.Call(argsVal[:typ.NumIn()]) for i, v := range resultVal { if !reflect.DeepEqual(v.Interface(), args[i+typ.NumIn()]) { return } } // Present the result including a godoc command to get more information. firstIndex := 0 if firstArg != "" { fmt.Fprintf(output, "%s.%s(", firstArg, name) firstIndex = 1 } else { fmt.Fprintf(output, "%s.%s(", pkg, name) } for i := firstIndex; i < typ.NumIn(); i++ { if i > firstIndex { fmt.Fprint(output, ", ") } fmt.Fprintf(output, "%#v", args[i]) } fmt.Fprint(output, ") = ") if typ.NumOut() > 1 { fmt.Fprint(output, "(") } for i := 0; i < typ.NumOut(); i++ { if i > 0 { fmt.Fprint(output, ", ") } fmt.Fprintf(output, "%#v", resultVal[i].Interface()) } if typ.NumOut() > 1 { fmt.Fprint(output, ")") } fmt.Fprintf(output, " // godoc %s %s\n", pkg, name) }