Ejemplo n.º 1
0
func checkDescriptions(objType reflect.Type, seen *map[reflect.Type]bool, t *testing.T) {
	if _, exists := (*seen)[objType]; exists {
		return
	}
	(*seen)[objType] = true
	if !strings.Contains(objType.PkgPath(), "openshift/origin") {
		return
	}

	for i := 0; i < objType.NumField(); i++ {
		structField := objType.FieldByIndex([]int{i})

		// these fields don't need descriptions
		if structField.Name == "TypeMeta" || structField.Name == "ObjectMeta" || structField.Name == "ListMeta" {
			continue
		}
		if structField.Type == reflect.TypeOf(unversioned.Time{}) || structField.Type == reflect.TypeOf(time.Time{}) || structField.Type == reflect.TypeOf(runtime.RawExtension{}) {
			continue
		}

		descriptionTag := structField.Tag.Get("description")
		if len(descriptionTag) == 0 {
			t.Errorf("%v", structField.Tag)
			t.Errorf("%v.%v does not have a description", objType, structField.Name)
		}

		switch structField.Type.Kind() {
		case reflect.Struct:
			checkDescriptions(structField.Type, seen, t)
		}
	}
}
Ejemplo n.º 2
0
func checkJsonTags(objType reflect.Type, seen *map[reflect.Type]bool, t *testing.T) {
	if _, exists := (*seen)[objType]; exists {
		return
	}
	(*seen)[objType] = true
	if !strings.Contains(objType.PkgPath(), "openshift/origin") {
		return
	}
	if internalTypesWithAllowedJsonTags.Has(objType.Name()) {
		return
	}

	for i := 0; i < objType.NumField(); i++ {
		structField := objType.FieldByIndex([]int{i})

		jsonTag := structField.Tag.Get("json")
		if len(jsonTag) != 0 {
			t.Errorf("%v.%v should not have a json tag", objType, structField.Name)
		}

		switch structField.Type.Kind() {
		case reflect.Struct:
			checkJsonTags(structField.Type, seen, t)
		}
	}
}
Ejemplo n.º 3
0
// recrusively describe a struct's field using our custom struct tags.
// This is recursive to allow embedding
func extractParams(T reflect.Type) (ret []ParamInfo) {

	ret = make([]ParamInfo, 0, T.NumField())

	for i := 0; i < T.NumField(); i++ {

		field := T.FieldByIndex([]int{i})
		if field.Name == "_" {
			continue
		}

		// a struct means this is an embedded request object
		if field.Type.Kind() == reflect.Struct {
			ret = append(extractParams(field.Type), ret...)
		} else {

			ret = append(ret, newParamInfo(field))

		}

	}

	return

}
Ejemplo n.º 4
0
func checkExternalJsonTags(objType reflect.Type, seen *map[reflect.Type]bool, t *testing.T) {
	if _, exists := (*seen)[objType]; exists {
		return
	}
	(*seen)[objType] = true
	if !strings.Contains(objType.PkgPath(), "github.com/openshift/origin/pkg") {
		return
	}

	for i := 0; i < objType.NumField(); i++ {
		structField := objType.FieldByIndex([]int{i})

		jsonTag := structField.Tag.Get("json")
		if len(jsonTag) == 0 {
			t.Errorf("%v.%v should have a json tag", objType, structField.Name)
		}

		switch structField.Type.Kind() {
		case reflect.Struct:
			checkExternalJsonTags(structField.Type, seen, t)
		case reflect.Ptr:
			checkExternalJsonTags(structField.Type.Elem(), seen, t)
		}
	}
}
Ejemplo n.º 5
0
func (m *structCache) getFields(typ reflect.Type) fields {
	numField := typ.NumField()
	fs := make(fields, numField)
	for i := 0; i < numField; i++ {
		f := typ.Field(i)

		if f.PkgPath != "" {
			continue
		}

		name, opts := parseTag(f.Tag.Get("msgpack"))
		if name == "-" {
			continue
		}
		if name == "" {
			name = f.Name
		}

		fieldTyp := typ.FieldByIndex(f.Index).Type
		fs[name] = &field{
			index:     f.Index,
			omitEmpty: opts.Contains("omitempty"),

			encoder: m.getEncoder(fieldTyp),
			decoder: m.getDecoder(fieldTyp),
		}
	}
	return fs
}
Ejemplo n.º 6
0
func (m *structCache) newStructField(typ reflect.Type, f *reflect.StructField) field {
	tokens := strings.Split(f.Tag.Get("msgpack"), ",")
	name := tokens[0]
	if name == "-" {
		return nil
	} else if name == "" {
		name = f.Name
	}

	baseField := &baseField{
		idx:  f.Index,
		name: name,
	}

	ft := typ.FieldByIndex(f.Index).Type
	if encodeFunc, ok := typEncMap[ft]; ok {
		decodeFunc := typDecMap[ft]
		return &customField{
			encode:    encodeFunc,
			decode:    decodeFunc,
			baseField: baseField,
		}
	}

	switch ft.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return &intField{
			baseField: baseField,
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return &uintField{
			baseField: baseField,
		}
	case reflect.Bool:
		return &boolField{
			baseField: baseField,
		}
	case reflect.Float32:
		return &float32Field{
			baseField: baseField,
		}
	case reflect.Float64:
		return &float64Field{
			baseField: baseField,
		}
	case reflect.Array, reflect.Slice:
		if ft.Elem().Kind() == reflect.Uint8 {
			return &bytesField{
				baseField: baseField,
			}
		}
	case reflect.String:
		return &stringField{
			baseField: baseField,
		}
	}
	return baseField
}
Ejemplo n.º 7
0
// NewRequestInfo Builds a requestInfo from a requestHandler struct using reflection
func NewRequestInfo(T reflect.Type, pth string, description string, returnValue interface{}) (RequestInfo, error) {

	if T.Kind() == reflect.Ptr {
		T = T.Elem()
	}

	// we only allow funcs and structs
	if T.Kind() != reflect.Struct && T.Kind() != reflect.Func {
		return RequestInfo{}, fmt.Errorf("Could not extract request info from non struct type")
	}

	ret := RequestInfo{Path: pth,
		Description: description,
		Params:      make([]ParamInfo, 0),
		Returns:     returnValue,
	}

	// take the first part of the path and make it the "group" name for swagger tagging
	if parts := strings.SplitN(strings.TrimLeft(pth, "/"), "/", 2); len(parts) > 0 {
		ret.Group = parts[0]
	}

	// for funcs we don't create struct based info
	if T.Kind() != reflect.Struct {
		return ret, nil
	}

	for i := 0; i < T.NumField(); i++ {

		field := T.FieldByIndex([]int{i})
		if field.Name == "_" {
			continue
		}

		// a struct means this is an embedded request object
		if field.Type.Kind() == reflect.Struct && field.Anonymous {
			ret.Params = append(extractParams(field.Type), ret.Params...)
		} else {

			ret.Params = append(ret.Params, newParamInfo(field))

		}

	}

	return ret, nil

}
Ejemplo n.º 8
0
Archivo: encoder.go Proyecto: erkl/binn
func (e *Encoder) _compileStruct(f *encoder, t reflect.Type) {
	fields := enumStructFields(t)
	se := &structEncoder{
		fields: make([]structEncoderField, len(fields)),
	}

	for i, f := range fields {
		se.fields[i] = structEncoderField{
			name:  encodeString(nil, reflect.ValueOf(f.Name)),
			index: f.Index,
		}
		e._compile(&se.fields[i].encode, t.FieldByIndex(f.Index).Type)
	}

	*f = se.encode
}
Ejemplo n.º 9
0
Archivo: util.go Proyecto: erkl/binn
// enumStructFields enumerates all fields with "binn" tags in a struct type,
// including fields of embedded structs.
func enumStructFields(t reflect.Type) []reflect.StructField {
	// We use this queue to visit every field in the struct (both immediate
	// ones and those in embedded structs), breadth-first.
	queue := make([][]int, t.NumField())
	for i := 0; i < t.NumField(); i++ {
		queue[i] = []int{i}
	}

	var names = make(map[string]bool)
	var fields []reflect.StructField

	// Work through the queue.
	for ; len(queue) > 0; queue = queue[1:] {
		index := queue[0]
		field := t.FieldByIndex(index)

		// todo: Distinguish between empty struct tags and ones that are
		// simply missing.
		name := field.Tag.Get("binn")

		// Visit the fields any embedded structs.
		if field.Anonymous && field.Type.Kind() == reflect.Struct && name == "" {
			index = index[:len(index):len(index)]
			for j := 0; j < field.Type.NumField(); j++ {
				queue = append(queue, append(index, field.Type.Field(j).Index...))
			}
			continue
		}

		// Ignore unexported fields and fields without a "binn" tag.
		if field.PkgPath != "" && name == "" {
			continue
		}

		field.Name = name
		field.Index = index
		fields = append(fields, field)

		names[name] = true
	}

	// Order the fields by their position in the root struct.
	sort.Sort(fieldsByIndex(fields))

	return fields
}
Ejemplo n.º 10
0
// addFieldInfo adds finfo to tinfo.fields if there are no
// conflicts, or if conflicts arise from previous fields that were
// obtained from deeper embedded structures than finfo. In the latter
// case, the conflicting entries are dropped.
// A conflict occurs when the path (parent + name) to a field is
// itself a prefix of another path, or when two paths match exactly.
// It is okay for field paths to share a common, shorter prefix.
func addFieldInfo(typ reflect.Type, tinfo *typeInfo, newf *fieldInfo) error {
	var conflicts []int
Loop:
	// First, figure all conflicts. Most working code will have none.
	for i := range tinfo.fields {
		oldf := &tinfo.fields[i]
		if oldf.flags&fMode != newf.flags&fMode {
			continue
		}
		if oldf.xmlns != "" && newf.xmlns != "" && oldf.xmlns != newf.xmlns {
			continue
		}
		minl := min(len(newf.parents), len(oldf.parents))
		for p := 0; p < minl; p++ {
			if oldf.parents[p] != newf.parents[p] {
				continue Loop
			}
		}
		if len(oldf.parents) > len(newf.parents) {
			if oldf.parents[len(newf.parents)] == newf.name {
				conflicts = append(conflicts, i)
			}
		} else if len(oldf.parents) < len(newf.parents) {
			if newf.parents[len(oldf.parents)] == oldf.name {
				conflicts = append(conflicts, i)
			}
		} else {
			if newf.name == oldf.name {
				conflicts = append(conflicts, i)
			}
		}
	}
	// Without conflicts, add the new field and return.
	if conflicts == nil {
		tinfo.fields = append(tinfo.fields, *newf)
		return nil
	}

	// If any conflict is shallower, ignore the new field.
	// This matches the Go field resolution on embedding.
	for _, i := range conflicts {
		if len(tinfo.fields[i].idx) < len(newf.idx) {
			return nil
		}
	}

	// Otherwise, if any of them is at the same depth level, it's an error.
	for _, i := range conflicts {
		oldf := &tinfo.fields[i]
		if len(oldf.idx) == len(newf.idx) {
			f1 := typ.FieldByIndex(oldf.idx)
			f2 := typ.FieldByIndex(newf.idx)
			return &TagPathError{typ, f1.Name, f1.Tag.Get("xml"), f2.Name, f2.Tag.Get("xml")}
		}
	}

	// Otherwise, the new field is shallower, and thus takes precedence,
	// so drop the conflicting fields from tinfo and append the new one.
	for c := len(conflicts) - 1; c >= 0; c-- {
		i := conflicts[c]
		copy(tinfo.fields[i:], tinfo.fields[i+1:])
		tinfo.fields = tinfo.fields[:len(tinfo.fields)-1]
	}
	tinfo.fields = append(tinfo.fields, *newf)
	return nil
}
Ejemplo n.º 11
0
func typeFieldByLoc(t reflect.Type, loc fieldLoc) reflect.StructField {
	if len(loc.path) > 0 {
		return t.FieldByIndex(loc.path)
	}
	return t.Field(loc.i)
}