Add a Name getter in named ApplyConfigurations

This will be used when generifying client-go: applying
ApplyConfigurations requires extracting their name, which is currently
done by accessing the corresponding public field directly; but that
can't be done with interfaces, which is what have to be used with
generics.

Signed-off-by: Stephen Kitt <skitt@redhat.com>
This commit is contained in:
Stephen Kitt 2023-10-18 12:38:53 +02:00
parent ef9965ebc6
commit 53356d5516
No known key found for this signature in database
GPG Key ID: 1CC5FA453662A71D

View File

@ -115,6 +115,7 @@ func (g *applyConfigurationGenerator) GenerateType(c *generator.Context, t *type
}
}
g.generateWithFuncs(t, typeParams, sw, nil)
g.generateGetters(t, typeParams, sw, nil)
return sw.Error()
}
@ -141,6 +142,40 @@ func blocklisted(t *types.Type, member types.Member) bool {
return false
}
func needsGetter(t *types.Type, member types.Member) bool {
// Needed when applying an ApplyConfiguration
return objectMeta.Name == t.Name && member.Name == "Name"
}
func (g *applyConfigurationGenerator) generateGetters(t *types.Type, typeParams TypeParams, sw *generator.SnippetWriter, embed *memberParams) {
for _, member := range t.Members {
if blocklisted(t, member) {
continue
}
memberType := g.refGraph.applyConfigForType(member.Type)
if g.refGraph.isApplyConfig(member.Type) {
memberType = &types.Type{Kind: types.Pointer, Elem: memberType}
}
if jsonTags, ok := lookupJSONTags(member); ok {
memberParams := memberParams{
TypeParams: typeParams,
Member: member,
MemberType: memberType,
JSONTags: jsonTags,
EmbeddedIn: embed,
}
if memberParams.Member.Embedded {
g.generateGetters(member.Type, typeParams, sw, &memberParams)
continue
}
if needsGetter(t, member) {
g.generateMemberGetter(sw, memberParams)
}
}
}
}
func (g *applyConfigurationGenerator) generateWithFuncs(t *types.Type, typeParams TypeParams, sw *generator.SnippetWriter, embed *memberParams) {
for _, member := range t.Members {
if blocklisted(t, member) {
@ -244,7 +279,7 @@ func (g *applyConfigurationGenerator) generateMemberWith(sw *generator.SnippetWr
sw.Do("// and returns the receiver, so that objects can be built by chaining \"With\" function invocations.\n", memberParams)
sw.Do("// If called multiple times, the $.Member.Name$ field is set to the value of the last call.\n", memberParams)
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) With$.Member.Name$(value $.MemberType|raw$) *$.ApplyConfig.ApplyConfiguration|public$ {\n", memberParams)
g.ensureEnbedExistsIfApplicable(sw, memberParams)
g.ensureEmbedExistsIfApplicable(sw, memberParams)
if g.refGraph.isApplyConfig(memberParams.Member.Type) || isNillable(memberParams.Member.Type) {
sw.Do("b.$.Member.Name$ = value\n", memberParams)
} else {
@ -254,6 +289,18 @@ func (g *applyConfigurationGenerator) generateMemberWith(sw *generator.SnippetWr
sw.Do("}\n", memberParams)
}
func (g *applyConfigurationGenerator) generateMemberGetter(sw *generator.SnippetWriter, memberParams memberParams) {
sw.Do("// Get$.Member.Name$ retrieves the value of the $.Member.Name$ field in the declarative configuration.\n", memberParams)
if g.refGraph.isApplyConfig(memberParams.Member.Type) || isNillable(memberParams.Member.Type) {
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) Get$.Member.Name$() $.MemberType|raw$ {\n", memberParams)
} else {
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) Get$.Member.Name$() *$.MemberType|raw$ {\n", memberParams)
}
g.ensureEmbedExistsIfApplicable(sw, memberParams)
sw.Do(" return b.$.Member.Name$\n", memberParams)
sw.Do("}\n", memberParams)
}
func (g *applyConfigurationGenerator) generateMemberWithForSlice(sw *generator.SnippetWriter, member types.Member, memberParams memberParams) {
memberIsPointerToSlice := member.Type.Kind == types.Pointer
if memberIsPointerToSlice {
@ -264,7 +311,7 @@ func (g *applyConfigurationGenerator) generateMemberWithForSlice(sw *generator.S
sw.Do("// and returns the receiver, so that objects can be build by chaining \"With\" function invocations.\n", memberParams)
sw.Do("// If called multiple times, values provided by each call will be appended to the $.Member.Name$ field.\n", memberParams)
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) With$.Member.Name$(values ...$.ArgType|raw$) *$.ApplyConfig.ApplyConfiguration|public$ {\n", memberParams)
g.ensureEnbedExistsIfApplicable(sw, memberParams)
g.ensureEmbedExistsIfApplicable(sw, memberParams)
if memberIsPointerToSlice {
sw.Do("b.ensure$.MemberType.Elem|public$Exists()\n", memberParams)
@ -299,7 +346,7 @@ func (g *applyConfigurationGenerator) generateMemberWithForMap(sw *generator.Sni
sw.Do("// If called multiple times, the entries provided by each call will be put on the $.Member.Name$ field,\n", memberParams)
sw.Do("// overwriting an existing map entries in $.Member.Name$ field with the same key.\n", memberParams)
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) With$.Member.Name$(entries $.MemberType|raw$) *$.ApplyConfig.ApplyConfiguration|public$ {\n", memberParams)
g.ensureEnbedExistsIfApplicable(sw, memberParams)
g.ensureEmbedExistsIfApplicable(sw, memberParams)
sw.Do(" if b.$.Member.Name$ == nil && len(entries) > 0 {\n", memberParams)
sw.Do(" b.$.Member.Name$ = make($.MemberType|raw$, len(entries))\n", memberParams)
sw.Do(" }\n", memberParams)
@ -310,7 +357,7 @@ func (g *applyConfigurationGenerator) generateMemberWithForMap(sw *generator.Sni
sw.Do("}\n", memberParams)
}
func (g *applyConfigurationGenerator) ensureEnbedExistsIfApplicable(sw *generator.SnippetWriter, memberParams memberParams) {
func (g *applyConfigurationGenerator) ensureEmbedExistsIfApplicable(sw *generator.SnippetWriter, memberParams memberParams) {
// Embedded types that are not inlined must be nillable so they are not included in the apply configuration
// when all their fields are omitted.
if memberParams.EmbeddedIn != nil && !memberParams.EmbeddedIn.JSONTags.inline {