func (resource *ResourceType) AsDeclarations(codeGenerationContext *CodeGenerationContext, declContext DeclarationContext) []dst.Decl {
	var fields []*dst.Field
	for _, property := range resource.EmbeddedProperties() {
		f := property.AsField(codeGenerationContext)
		if f != nil {
			fields = append(fields, f)
		}
	}
	for _, property := range resource.Properties() {
		f := property.AsField(codeGenerationContext)
		if f != nil {
			fields = append(fields, f)
		}
	}
	if len(fields) > 0 {
		fields[0].Decs.Before = dst.NewLine
	}
	resourceTypeSpec := &dst.TypeSpec{
		Name: dst.NewIdent(declContext.Name.Name()),
		Type: &dst.StructType{
			Fields: &dst.FieldList{List: fields},
		},
	}
	var comments dst.Decorations
	if resource.isStorageVersion {
		lpr, ok := declContext.Name.PackageReference.AsLocalPackage()
		if !ok {
			panic(fmt.Sprintf("expected resource package reference to be local: %q", declContext.Name))
		}
		group := strings.ToLower(lpr.Group() + GroupSuffix)
		resourceName := strings.ToLower(declContext.Name.Plural().Name())
		astbuilder.AddComment(&comments, fmt.Sprintf("// +kubebuilder:rbac:groups=%s,resources=%s,verbs=get;list;watch;create;update;patch;delete", group, resourceName))
		astbuilder.AddComment(&comments, fmt.Sprintf("// +kubebuilder:rbac:groups=%s,resources={%s/status,%s/finalizers},verbs=get;update;patch", group, resourceName, resourceName))
		comments = append(comments, "\n")
	}
	astbuilder.AddComment(&comments, "// +kubebuilder:object:root=true")
	if resource.status != nil {
		astbuilder.AddComment(&comments, "// +kubebuilder:subresource:status")
	}
	if resource.isStorageVersion {
		astbuilder.AddComment(&comments, "// +kubebuilder:storageversion")
	}
	astbuilder.AddWrappedComments(&comments, declContext.Description, 200)
	AddValidationComments(&comments, declContext.Validations)
	resourceDeclaration := &dst.GenDecl{
		Tok:   token.TYPE,
		Specs: []dst.Spec{resourceTypeSpec},
		Decs: dst.GenDeclDecorations{
			NodeDecs: dst.NodeDecs{
				Before: dst.EmptyLine,
				After:  dst.EmptyLine,
				Start:  comments,
			},
		},
	}
	var declarations []dst.Decl
	declarations = append(declarations, resourceDeclaration)
	declarations = append(declarations, resource.InterfaceImplementer.AsDeclarations(codeGenerationContext, declContext.Name, nil)...)
	declarations = append(declarations, resource.generateMethodDecls(codeGenerationContext, declContext.Name)...)
	declarations = append(declarations, resource.resourceListTypeDecls(codeGenerationContext, declContext.Name, declContext.Description)...)
	return declarations
}
AsDeclarations converts the resource type to a set of go declarations
package astmodel
import (
	"fmt"
	"go/token"
	"sort"
	"strings"
	"github.com/dave/dst"
	"k8s.io/klog/v2"
	"github.com/Azure/k8s-infra/hack/generator/pkg/astbuilder"
)
type ResourceType struct {
	spec             Type
	status           Type
	isStorageVersion bool
	owner            *TypeName
	functions        map[string]Function
	testcases        map[string]TestCase
	InterfaceImplementer
}
func NewResourceType(specType Type, statusType Type) *ResourceType {
	result := &ResourceType{
		isStorageVersion:     false,
		owner:                nil,
		functions:            make(map[string]Function),
		testcases:            make(map[string]TestCase),
		InterfaceImplementer: MakeInterfaceImplementer(),
	}
	return result.WithSpec(specType).WithStatus(statusType)
}
func IsResourceType(t Type) bool {
	_, ok := t.(*ResourceType)
	return ok
}
func IsResourceDefinition(def TypeDefinition) bool {
	return IsResourceType(def.Type())
}
func NewAzureResourceType(specType Type, statusType Type, typeName TypeName) *ResourceType {
	if objectType, ok := specType.(*ObjectType); ok {
		var nameProperty *PropertyDefinition
		var typeProperty *PropertyDefinition
		var apiVersionProperty *PropertyDefinition
		isNameOptional := false
		isTypeOptional := false
		for _, property := range objectType.Properties() {
			if property.HasName(NameProperty) {
				nameProperty = property
				if _, ok := property.PropertyType().(*OptionalType); ok {
					isNameOptional = true
				}
			}
			if property.HasName(TypeProperty) {
				typeProperty = property
				if _, ok := property.PropertyType().(*OptionalType); ok {
					isTypeOptional = true
				}
			}
			if property.HasName(ApiVersionProperty) {
				apiVersionProperty = property
			}
		}
		if typeProperty == nil {
			panic(fmt.Sprintf("Resource %s is missing type property", typeName))
		}
		if nameProperty == nil {
			klog.V(1).Infof("resource %s is missing field 'Name', fabricating one...", typeName)
			nameProperty = NewPropertyDefinition("Name", "name", StringType)
			nameProperty.WithDescription("The name of the resource")
			isNameOptional = true
		}
		if apiVersionProperty == nil {
			panic(fmt.Sprintf("Resource %s is missing apiVersion property", typeName))
		}
		if isNameOptional {
			nameProperty = nameProperty.MakeRequired()
			objectType = objectType.WithProperty(nameProperty)
		}
		apiVersionProperty = apiVersionProperty.MakeRequired()
		objectType = objectType.WithProperty(apiVersionProperty)
		if isTypeOptional {
			typeProperty = typeProperty.MakeRequired()
			objectType = objectType.WithProperty(typeProperty)
		}
		specType = objectType
	}
	return NewResourceType(specType, statusType)
}
var _ Type = &ResourceType{}
var _ PropertyContainer = &ResourceType{}
var _ FunctionContainer = &ResourceType{}
func (resource *ResourceType) SpecType() Type {
	return resource.spec
}
func (resource *ResourceType) StatusType() Type {
	return resource.status
}
func (resource *ResourceType) IsStorageVersion() bool {
	return resource.isStorageVersion
}
func (resource *ResourceType) WithSpec(specType Type) *ResourceType {
	if specResource, ok := specType.(*ResourceType); ok {
		return resource.WithSpec(specResource.SpecType())
	}
	result := resource.copy()
	result.spec = specType
	return result
}
func (resource *ResourceType) WithStatus(statusType Type) *ResourceType {
	if specResource, ok := statusType.(*ResourceType); ok {
		return resource.WithStatus(specResource.StatusType())
	}
	result := resource.copy()
	result.status = statusType
	return result
}
func (resource *ResourceType) WithoutInterface(name TypeName) *ResourceType {
	if !resource.InterfaceImplementer.HasInterface(name) {
		return resource
	}
	result := *resource
	result.InterfaceImplementer = result.InterfaceImplementer.WithoutInterface(name)
	return &result
}
func (resource *ResourceType) WithInterface(iface *InterfaceImplementation) *ResourceType {
	result := resource.copy()
	result.InterfaceImplementer = result.InterfaceImplementer.WithInterface(iface)
	return result
}
func (resource *ResourceType) WithFunction(function Function) *ResourceType {
	result := resource.copy()
	result.functions[function.Name()] = function
	return result
}
func (resource *ResourceType) WithTestCase(testcase TestCase) *ResourceType {
	result := resource.copy()
	result.testcases[testcase.Name()] = testcase
	return result
}
func (resource *ResourceType) AsType(_ *CodeGenerationContext) dst.Expr {
	panic("a resource cannot be used directly as a type")
}
func (resource *ResourceType) AsZero(_ Types, _ *CodeGenerationContext) dst.Expr {
	panic("a resource cannot be used directly as a type")
}
func (resource *ResourceType) Equals(other Type) bool {
	if resource == other {
		return true
	}
	otherResource, ok := other.(*ResourceType)
	if !ok {
		return false
	}
	if resource.isStorageVersion != otherResource.isStorageVersion ||
		len(resource.testcases) != len(otherResource.testcases) ||
		len(resource.functions) != len(otherResource.functions) ||
		!TypeEquals(resource.spec, otherResource.spec) ||
		!TypeEquals(resource.status, otherResource.status) ||
		!resource.InterfaceImplementer.Equals(otherResource.InterfaceImplementer) {
		return false
	}
	for name, fn := range otherResource.functions {
		ourFn, ok := resource.functions[name]
		if !ok {
			return false
		}
		if !ourFn.Equals(fn) {
			return false
		}
	}
	for name, testcase := range otherResource.testcases {
		ourCase, ok := resource.testcases[name]
		if !ok {
			return false
		}
		if !ourCase.Equals(testcase) {
			return false
		}
	}
	return true
}
func (resource *ResourceType) EmbeddedProperties() []*PropertyDefinition {
	typeMetaType := MakeTypeName(MetaV1PackageReference, "TypeMeta")
	typeMetaProperty := NewPropertyDefinition("", "", typeMetaType).
		WithTag("json", "inline")
	objectMetaType := MakeTypeName(MetaV1PackageReference, "ObjectMeta")
	objectMetaProperty := NewPropertyDefinition("", "metadata", objectMetaType).
		WithTag("json", "omitempty")
	return []*PropertyDefinition{
		typeMetaProperty,
		objectMetaProperty,
	}
}
func (resource *ResourceType) Properties() []*PropertyDefinition {
	specProperty := NewPropertyDefinition("Spec", "spec", resource.spec).
		WithTag("json", "omitempty")
	result := []*PropertyDefinition{
		specProperty,
	}
	if resource.status != nil {
		statusProperty := NewPropertyDefinition("Status", "status", resource.status).
			WithTag("json", "omitempty")
		result = append(result, statusProperty)
	}
	return result
}
func (resource *ResourceType) Functions() []Function {
	var functions []Function
	for _, f := range resource.functions {
		functions = append(functions, f)
	}
	sort.Slice(functions, func(i int, j int) bool {
		return functions[i].Name() < functions[j].Name()
	})
	return functions
}
func (resource *ResourceType) References() TypeNameSet {
	spec := resource.spec.References()
	var status TypeNameSet
	if resource.status != nil {
		status = resource.status.References()
	}
	return SetUnion(spec, status)
}
func (resource *ResourceType) Owner() *TypeName {
	return resource.owner
}
func (resource *ResourceType) MarkAsStorageVersion() *ResourceType {
	result := resource.copy()
	result.isStorageVersion = true
	return result
}
func (resource *ResourceType) WithOwner(owner *TypeName) *ResourceType {
	result := resource.copy()
	result.owner = owner
	return result
}
func (resource *ResourceType) RequiredPackageReferences() *PackageReferenceSet {
	references := NewPackageReferenceSet(MetaV1PackageReference)
	references.Merge(resource.spec.RequiredPackageReferences())
	if resource.status != nil {
		references.Merge(resource.status.RequiredPackageReferences())
	}
	references.Merge(resource.InterfaceImplementer.RequiredPackageReferences())
	return references
}