Ejemplo n.º 1
0
func (c *_Context) completeValue(
	returnType typs.QLType,
	fieldASTs []*lang.Field,
	info typs.QLResolveInfo,
	result interface{},
) interface{} {

	if returnType, ok := returnType.(*typs.QLNonNull); ok {
		completed := c.completeValue(returnType.OfType, fieldASTs, info, result)
		if completed == nil {
			nodes := make([]lang.INode, len(fieldASTs))
			for i, node := range fieldASTs {
				nodes[i] = node
			}
			panic(lang.NewQLError(
				fmt.Sprintf(
					`Cannot return null for non-nullable field %v.%v.`,
					info.ParentType, info.FieldName),
				nodes))
		}
		return completed
	}

	v := reflect.ValueOf(result)
	if result == nil {
		return nil
	}

	v = reflect.Indirect(v)
	t := v.Type()
	switch returnType := returnType.(type) {
	case *typs.QLList:
		if t.Kind() == reflect.Slice || t.Kind() == reflect.Array {
			itemType := returnType.OfType
			list := make([]interface{}, t.NumField())
			for i, n := 0, t.NumField(); i < n; i++ {
				list[i] = c.completeValueCatchingError(itemType, fieldASTs, info, v.Field(i).Interface())
			}
			return list
		}
		panic("User Error: expected array of slice, but did not find one.")

	case *typs.QLScalar:
		if returnType.Serialize == nil {
			panic("Missing serialize method on type")
		}
		serializedResult := returnType.Serialize(result)
		if serializedResult == nil {
			return nil
		}
		return serializedResult

	case *typs.QLEnum:
		return returnType.Serialize(result)

	case *typs.QLObject:
		runtimeType := returnType
		subFieldASTs := map[string][]*lang.Field{}
		visitedFragmentNames := map[string]struct{}{}
		for _, fieldAST := range fieldASTs {
			selectionSet := fieldAST.SelectionSet
			if selectionSet != nil {
				subFieldASTs = c.collectFields(runtimeType, selectionSet, subFieldASTs, visitedFragmentNames)
			}
		}
		return c.executeFields(runtimeType, result, subFieldASTs)

	case typs.QLAbstractType:
		panic("not implemented")

	default:
		panic("unreachable")
	}
}