func addCrossplaneOwnerProperties(idFactory astmodel.IdentifierFactory) PipelineStage {
	return MakePipelineStage(
		"addCrossplaneOwnerProperties",
		"Adds the 3-tuple of (xName, xNameRef, xNameSelector) for each owning resource",
		func(ctx context.Context, types astmodel.Types) (astmodel.Types, error) {
			referenceTypeName := astmodel.MakeTypeName(
				CrossplaneRuntimeV1Alpha1Package,
				idFactory.CreateIdentifier("Reference", astmodel.Exported))
			selectorTypeName := astmodel.MakeTypeName(
				CrossplaneRuntimeV1Alpha1Package,
				idFactory.CreateIdentifier("Selector", astmodel.Exported))
			result := make(astmodel.Types)
			for _, typeDef := range types {
				if resource, ok := typeDef.Type().(*astmodel.ResourceType); ok {
					owners, err := lookupOwners(types, typeDef)
					if err != nil {
						return nil, errors.Wrapf(err, "failed to look up owners for %s", typeDef.Name())
					}
					owners = owners[0 : len(owners)-1]
					if len(owners) == 0 {
						continue
					}
					specDef, err := types.ResolveResourceSpecDefinition(resource)
					if err != nil {
						return nil, errors.Wrapf(err, "getting resource spec definition")
					}
					for _, owner := range owners {
						nameSubset := fmt.Sprintf("%sName", owner.Name())
						name := idFactory.CreatePropertyName(nameSubset, astmodel.Exported)
						nameRef := name + "Ref"
						nameSelector := name + "Selector"
						updatedDef, err := specDef.ApplyObjectTransformation(func(o *astmodel.ObjectType) (astmodel.Type, error) {
							nameProperty := astmodel.NewPropertyDefinition(
								name,
								idFactory.CreateIdentifier(string(name), astmodel.NotExported),
								astmodel.StringType)
							nameRefProperty := astmodel.NewPropertyDefinition(
								nameRef,
								idFactory.CreateIdentifier(string(nameRef), astmodel.NotExported),
								referenceTypeName).MakeOptional()
							nameSelectorProperty := astmodel.NewPropertyDefinition(
								nameSelector,
								idFactory.CreateIdentifier(string(nameSelector), astmodel.NotExported),
								selectorTypeName).MakeOptional()
							result := o.WithProperty(nameProperty).WithProperty(nameRefProperty).WithProperty(nameSelectorProperty)
							return result, nil
						})
						if err != nil {
							return nil, errors.Wrapf(err, "adding ownership properties to spec")
						}
						specDef = updatedDef
					}
					result.Add(typeDef)
					result.Add(specDef)
				}
			}
			for _, typeDef := range types {
				if !result.Contains(typeDef.Name()) {
					result.Add(typeDef)
				}
			}
			return result, nil
		})
}
addCrossplaneOwnerProperties adds the 3-tuple of (xName, xNameRef, xNameSelector) for each owning resource
package codegen
import (
	"context"
	"fmt"
	"github.com/pkg/errors"
	"github.com/Azure/k8s-infra/hack/generator/pkg/astmodel"
)