func isDirectlyConvertible(in, out *types.Type, preexisting conversions) bool { // If one of the types is Alias, resolve it. if in.Kind == types.Alias { return isConvertible(in.Underlying, out, preexisting) } if out.Kind == types.Alias { return isConvertible(in, out.Underlying, preexisting) } if in.Kind != out.Kind { return false } switch in.Kind { case types.Builtin, types.Struct, types.Map, types.Slice, types.Pointer: default: // We don't support conversion of other types yet. return false } switch out.Kind { case types.Builtin, types.Struct, types.Map, types.Slice, types.Pointer: default: // We don't support conversion of other types yet. return false } switch in.Kind { case types.Builtin: if in == out { return true } // TODO: Support more conversion types. return types.IsInteger(in) && types.IsInteger(out) case types.Struct: convertible := true for _, inMember := range in.Members { // Check if there is an out member with that name. outMember, found := findMember(out, inMember.Name) if !found { // Check if the member doesn't have comment: // "+ genconversion=false" // comment to ignore this field for conversion. // TODO: Switch to SecondClosestCommentLines. if types.ExtractCommentTags("+", inMember.CommentLines)["genconversion"] == "false" { continue } return false } convertible = convertible && isConvertible(inMember.Type, outMember.Type, preexisting) } return convertible case types.Map: return isConvertible(in.Key, out.Key, preexisting) && isConvertible(in.Elem, out.Elem, preexisting) case types.Slice: return isConvertible(in.Elem, out.Elem, preexisting) case types.Pointer: return isConvertible(in.Elem, out.Elem, preexisting) } glog.Fatalf("All other types should be filtered before") return false }
func isDirectlyConvertible(in, out *types.Type, manualConversions conversionFuncMap) bool { // If one of the types is Alias, resolve it. if in.Kind == types.Alias { return isConvertible(in.Underlying, out, manualConversions) } if out.Kind == types.Alias { return isConvertible(in, out.Underlying, manualConversions) } if in == out { return true } if in.Kind != out.Kind { return false } switch in.Kind { case types.Builtin, types.Struct, types.Map, types.Slice, types.Pointer: default: // We don't support conversion of other types yet. return false } switch in.Kind { case types.Builtin: // TODO: Support more conversion types. return types.IsInteger(in) && types.IsInteger(out) case types.Struct: convertible := true for _, inMember := range in.Members { // Check if there is an out member with that name. outMember, found := findMember(out, inMember.Name) if !found { // Check if the member has opted out with: // "+k8s:conversion-gen=false" // TODO: Switch to SecondClosestCommentLines. if tagvals := extractTag(inMember.CommentLines); tagvals != nil && tagvals[0] == "false" { glog.V(5).Infof("field %v.%s requests no conversion generation, skipping", in, inMember.Name) continue } return false } convertible = convertible && isConvertible(inMember.Type, outMember.Type, manualConversions) } return convertible case types.Map: return isConvertible(in.Key, out.Key, manualConversions) && isConvertible(in.Elem, out.Elem, manualConversions) case types.Slice: return isConvertible(in.Elem, out.Elem, manualConversions) case types.Pointer: return isConvertible(in.Elem, out.Elem, manualConversions) } glog.Fatalf("All other types should be filtered before") return false }
func isDirectlyConvertible(in, out *types.Type, preexisting conversions) bool { // If one of the types is Alias, resolve it. if in.Kind == types.Alias { return isConvertible(in.Underlying, out, preexisting) } if out.Kind == types.Alias { return isConvertible(in, out.Underlying, preexisting) } if in.Kind != out.Kind { return false } switch in.Kind { case types.Builtin, types.Struct, types.Map, types.Slice, types.Pointer: default: // We don't support conversion of other types yet. return false } switch out.Kind { case types.Builtin, types.Struct, types.Map, types.Slice, types.Pointer: default: // We don't support conversion of other types yet. return false } switch in.Kind { case types.Builtin: if in == out { return true } // TODO: Support more conversion types. return types.IsInteger(in) && types.IsInteger(out) case types.Struct: convertible := true for _, inMember := range in.Members { // Check if there is an out member with that name. outMember, found := findMember(out, inMember.Name) if !found { return false } convertible = convertible && isConvertible(inMember.Type, outMember.Type, preexisting) } return convertible case types.Map: return isConvertible(in.Key, out.Key, preexisting) && isConvertible(in.Elem, out.Elem, preexisting) case types.Slice: return isConvertible(in.Elem, out.Elem, preexisting) case types.Pointer: return isConvertible(in.Elem, out.Elem, preexisting) } glog.Fatalf("All other types should be filtered before") return false }
func isDirectlyConvertible(in, out *types.Type, manualConversions conversionFuncMap) bool { // If one of the types is Alias, resolve it. if in.Kind == types.Alias { return isConvertible(in.Underlying, out, manualConversions) } if out.Kind == types.Alias { return isConvertible(in, out.Underlying, manualConversions) } if in == out { return true } if in.Kind != out.Kind { return false } switch in.Kind { case types.Builtin, types.Struct, types.Map, types.Slice, types.Pointer: default: // We don't support conversion of other types yet. return false } switch in.Kind { case types.Builtin: // TODO: Support more conversion types. return types.IsInteger(in) && types.IsInteger(out) case types.Struct: convertible := true for _, inMember := range in.Members { // Check if this member is excluded from conversion if tagvals := extractTag(inMember.CommentLines); tagvals != nil && tagvals[0] == "false" { continue } // Check if there is an out member with that name. outMember, found := findMember(out, inMember.Name) if !found { glog.V(5).Infof("%s.%s is not directly convertible to %s because the destination struct field did not exist", in.Name, inMember.Name, out.Name) return false } convertible = convertible && isConvertible(inMember.Type, outMember.Type, manualConversions) } return convertible case types.Map: return isConvertible(in.Key, out.Key, manualConversions) && isConvertible(in.Elem, out.Elem, manualConversions) case types.Slice: return isConvertible(in.Elem, out.Elem, manualConversions) case types.Pointer: return isConvertible(in.Elem, out.Elem, manualConversions) } glog.Fatalf("All other types should be filtered before") return false }