Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to the new conversion generator - part1 #23427

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
70 changes: 45 additions & 25 deletions cmd/libs/go2idl/conversion-gen/generators/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
// (in the directory one above) and can be automatically converted to.
for _, p := range context.Universe {
path := p.Path
// TODO: Only a subset of InputDirs is actually where we would like
// to generate conversions, the rest of files are added, because either
// conversion methods are generated there or they contain types
// necessary for conversions.
if !inputs.Has(path) {
continue
}
Expand Down Expand Up @@ -248,6 +252,13 @@ func isDirectlyConvertible(in, out *types.Type, preexisting conversions) bool {
// 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)
Expand Down Expand Up @@ -306,7 +317,7 @@ func (g *genConversion) convertibleOnlyWithinPackage(inType, outType *types.Type
if t.Name.Package != g.targetPackage {
return false
}
if types.ExtractCommentTags("+", t.CommentLines)["genConversion"] == "false" {
if types.ExtractCommentTags("+", t.CommentLines)["genconversion"] == "false" {
return false
}
// TODO: Consider generating functions for other kinds too.
Expand Down Expand Up @@ -478,14 +489,14 @@ func (g *genConversion) doBuiltin(inType, outType *types.Type, sw *generator.Sni
}

func (g *genConversion) doMap(inType, outType *types.Type, sw *generator.SnippetWriter) {
sw.Do("out = make($.|raw$, len(in))\n", outType)
sw.Do("*out = make($.|raw$, len(*in))\n", outType)
if outType.Key.IsAssignable() {
sw.Do("for key, val := range in {\n", nil)
sw.Do("for key, val := range *in {\n", nil)
if outType.Elem.IsAssignable() {
if inType.Key == outType.Key {
sw.Do("out[key] = ", nil)
sw.Do("(*out)[key] = ", nil)
} else {
sw.Do("out[$.|raw$(key)] = ", outType.Key)
sw.Do("(*out)[$.|raw$(key)] = ", outType.Key)
}
if inType.Elem == outType.Elem {
sw.Do("val\n", nil)
Expand All @@ -506,40 +517,40 @@ func (g *genConversion) doMap(inType, outType *types.Type, sw *generator.Snippet
sw.Do("return err\n", nil)
sw.Do("}\n", nil)
if inType.Key == outType.Key {
sw.Do("out[key] = *newVal\n", nil)
sw.Do("(*out)[key] = *newVal\n", nil)
} else {
sw.Do("out[$.|raw$(key)] = *newVal\n", outType.Key)
sw.Do("(*out)[$.|raw$(key)] = *newVal\n", outType.Key)
}
}
} else {
// TODO: Implement it when necessary.
sw.Do("for range in {\n", nil)
sw.Do("for range *in {\n", nil)
sw.Do("// FIXME: Converting unassignable keys unsupported $.|raw$\n", inType.Key)
}
sw.Do("}\n", nil)
}

func (g *genConversion) doSlice(inType, outType *types.Type, sw *generator.SnippetWriter) {
sw.Do("out = make($.|raw$, len(in))\n", outType)
sw.Do("*out = make($.|raw$, len(*in))\n", outType)
if inType.Elem == outType.Elem && inType.Elem.Kind == types.Builtin {
sw.Do("copy(out, in)\n", nil)
sw.Do("copy(*out, *in)\n", nil)
} else {
sw.Do("for i := range in {\n", nil)
sw.Do("for i := range *in {\n", nil)
if outType.Elem.IsAssignable() {
if inType.Elem == outType.Elem {
sw.Do("out[i] = in[i]\n", nil)
sw.Do("(*out)[i] = (*in)[i]\n", nil)
} else {
sw.Do("out[i] = $.|raw$(in[i])\n", outType.Elem)
sw.Do("(*out)[i] = $.|raw$((*in)[i])\n", outType.Elem)
}
} else {
if function, ok := g.preexists(inType.Elem, outType.Elem); ok {
sw.Do("if err := $.|raw$(&in[i], &out[i], s); err != nil {\n", function)
sw.Do("if err := $.|raw$(&(*in)[i], &(*out)[i], s); err != nil {\n", function)
} else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {
funcName := g.funcNameTmpl(inType.Elem, outType.Elem)
sw.Do(fmt.Sprintf("if err := %s(&in[i], &out[i], s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))
sw.Do(fmt.Sprintf("if err := %s(&(*in)[i], &(*out)[i], s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))
} else {
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
sw.Do("if err := s.Convert(&in[i], &out[i], 0); err != nil {\n", nil)
sw.Do("if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil {\n", nil)
}
sw.Do("return err\n", nil)
sw.Do("}\n", nil)
Expand All @@ -550,7 +561,12 @@ func (g *genConversion) doSlice(inType, outType *types.Type, sw *generator.Snipp

func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.SnippetWriter) {
for _, m := range inType.Members {
outMember, _ := findMember(outType, m.Name)
outMember, isOutMember := findMember(outType, m.Name)
if !isOutMember {
// Since this object wasn't filtered out, this means that
// this field has "genconversion=false" comment to ignore it.
continue
}
args := map[string]interface{}{
"inType": m.Type,
"outType": outMember.Type,
Expand All @@ -572,7 +588,7 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
}
case types.Map, types.Slice, types.Pointer:
sw.Do("if in.$.name$ != nil {\n", args)
sw.Do("in, out := in.$.name$, out.$.name$\n", args)
sw.Do("in, out := &in.$.name$, &out.$.name$\n", args)
g.generateFor(m.Type, outMember.Type, sw)
sw.Do("} else {\n", nil)
sw.Do("out.$.name$ = nil\n", args)
Expand All @@ -589,7 +605,11 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
sw.Do("}\n", nil)
case types.Alias:
if outMember.Type.IsAssignable() {
sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)
if m.Type == outMember.Type {
sw.Do("out.$.name$ = in.$.name$\n", args)
} else {
sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)
}
} else {
if g.convertibleOnlyWithinPackage(m.Type, outMember.Type) {
funcName := g.funcNameTmpl(m.Type, outMember.Type)
Expand All @@ -616,22 +636,22 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
}

func (g *genConversion) doPointer(inType, outType *types.Type, sw *generator.SnippetWriter) {
sw.Do("out = new($.Elem|raw$)\n", outType)
sw.Do("*out = new($.Elem|raw$)\n", outType)
if outType.Elem.IsAssignable() {
if inType.Elem == outType.Elem {
sw.Do("*out = *in\n", nil)
sw.Do("**out = **in\n", nil)
} else {
sw.Do("*out = $.|raw$(*in)\n", outType.Elem)
sw.Do("**out = $.|raw$(**in)\n", outType.Elem)
}
} else {
if function, ok := g.preexists(inType.Elem, outType.Elem); ok {
sw.Do("if err := $.|raw$(in, out, s); err != nil {\n", function)
sw.Do("if err := $.|raw$(*in, *out, s); err != nil {\n", function)
} else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {
funcName := g.funcNameTmpl(inType.Elem, outType.Elem)
sw.Do(fmt.Sprintf("if err := %s(in, out, s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))
sw.Do(fmt.Sprintf("if err := %s(*in, *out, s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))
} else {
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
sw.Do("if err := s.Convert(in, out, 0); err != nil {\n", nil)
sw.Do("if err := s.Convert(*in, *out, 0); err != nil {\n", nil)
}
sw.Do("return err\n", nil)
sw.Do("}\n", nil)
Expand Down
3 changes: 1 addition & 2 deletions hack/after-build/run-codegen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ setgen=$(kube::util::find-binary "set-gen")
# update- and verify- scripts.
${clientgen} "$@"
${clientgen} -t "$@"
# TODO: Enable when conversion generator is ready.
# ${conversiongen} "$@"
${conversiongen} "$@"
${deepcopygen} "$@"
${setgen} "$@"

Expand Down
2 changes: 1 addition & 1 deletion hack/after-build/update-generated-conversions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ EOF
}

# TODO(lavalamp): get this list by listing the pkg/apis/ directory?
DEFAULT_GROUP_VERSIONS="v1 authorization/v1beta1 autoscaling/v1 batch/v1 extensions/v1beta1 componentconfig/v1alpha1 metrics/v1alpha1"
DEFAULT_GROUP_VERSIONS="authorization/v1beta1 autoscaling/v1 batch/v1 extensions/v1beta1 componentconfig/v1alpha1 metrics/v1alpha1"
VERSIONS=${VERSIONS:-$DEFAULT_GROUP_VERSIONS}
for ver in $VERSIONS; do
# Ensure that the version being processed is registered by setting
Expand Down
2 changes: 1 addition & 1 deletion hack/after-build/verify-generated-conversions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ source "${KUBE_ROOT}/hack/lib/init.sh"

kube::golang::setup_env

APIROOTS=${APIROOTS:-pkg/api pkg/apis/authorization pkg/apis/autoscaling pkg/apis/batch pkg/apis/extensions pkg/apis/metrics}
APIROOTS=${APIROOTS:-pkg/apis/authorization pkg/apis/autoscaling pkg/apis/batch pkg/apis/extensions pkg/apis/metrics}
_tmp="${KUBE_ROOT}/_tmp"

cleanup() {
Expand Down
1 change: 1 addition & 0 deletions hack/verify-codegen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ source "${KUBE_ROOT}/hack/lib/init.sh"
kube::golang::setup_env

"${KUBE_ROOT}/hack/build-go.sh" cmd/libs/go2idl/client-gen
"${KUBE_ROOT}/hack/build-go.sh" cmd/libs/go2idl/conversion-gen
"${KUBE_ROOT}/hack/build-go.sh" cmd/libs/go2idl/deepcopy-gen
"${KUBE_ROOT}/hack/build-go.sh" cmd/libs/go2idl/set-gen

Expand Down
9 changes: 0 additions & 9 deletions pkg/api/unversioned/deep_copy_generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,6 @@ func DeepCopy_unversioned_Duration(in Duration, out *Duration, c *conversion.Clo
return nil
}

func DeepCopy_unversioned_ExportOptions(in ExportOptions, out *ExportOptions, c *conversion.Cloner) error {
if err := DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
}
out.Export = in.Export
out.Exact = in.Exact
return nil
}

func DeepCopy_unversioned_GroupKind(in GroupKind, out *GroupKind, c *conversion.Cloner) error {
out.Group = in.Group
out.Kind = in.Kind
Expand Down