Skip to content

Commit 7f2bbc1

Browse files
committed
Fix OriginalShapeName handling for union types in SDK code generation
SDK code generation functions for unions did not use OriginalShapeName to restore the correct SDK type name, producing invalid references like svcsdktypes.MemoryStrategyInput_. Extend the existing OriginalShapeName handling (used for structures in varEmptyConstructorSDKType) to the union code paths: setSDKForUnion, setResourceForUnion, and varEmptyConstructorSDKType when RealType is union.
1 parent 60fc9a5 commit 7f2bbc1

6 files changed

Lines changed: 197 additions & 1 deletion

File tree

pkg/api/passes_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,3 +974,91 @@ func TestValidateShapeNameMethod(t *testing.T) {
974974
})
975975
}
976976
}
977+
978+
// TestRenamedUnionShapePreservesOriginalName verifies that when a union
979+
// shape is renamed (e.g. MemoryStrategyInput -> MemoryStrategyInput_) by
980+
// renameIOSuffixedShapeNames, the OriginalShapeName is preserved. The
981+
// downstream SDK code generation functions (setSDKForUnion,
982+
// setResourceForUnion, varEmptyConstructorSDKType) use OriginalShapeName
983+
// to emit correct SDK type references.
984+
func TestRenamedUnionShapePreservesOriginalName(t *testing.T) {
985+
a := &API{
986+
name: "testapi",
987+
Metadata: Metadata{
988+
APIVersion: "0000-00-00",
989+
EndpointPrefix: "testapi",
990+
JSONVersion: "1.1",
991+
Protocol: "json",
992+
ServiceAbbreviation: "TestAPI",
993+
ServiceFullName: "Test API",
994+
SignatureVersion: "v4",
995+
},
996+
Operations: map[string]*Operation{
997+
"CreateMemory": {
998+
Name: "CreateMemory",
999+
InputRef: ShapeRef{ShapeName: "CreateMemoryInput"},
1000+
OutputRef: ShapeRef{ShapeName: "CreateMemoryOutput"},
1001+
},
1002+
},
1003+
Shapes: map[string]*Shape{
1004+
"CreateMemoryInput": {
1005+
ShapeName: "CreateMemoryInput",
1006+
Type: "structure",
1007+
MemberRefs: map[string]*ShapeRef{
1008+
"Strategies": {ShapeName: "MemoryStrategyInputList"},
1009+
},
1010+
},
1011+
"CreateMemoryOutput": {
1012+
ShapeName: "CreateMemoryOutput",
1013+
Type: "structure",
1014+
},
1015+
"MemoryStrategyInputList": {
1016+
ShapeName: "MemoryStrategyInputList",
1017+
Type: "list",
1018+
MemberRef: ShapeRef{ShapeName: "MemoryStrategyInput"},
1019+
},
1020+
"MemoryStrategyInput": {
1021+
ShapeName: "MemoryStrategyInput",
1022+
Type: "structure",
1023+
RealType: "union",
1024+
},
1025+
},
1026+
}
1027+
1028+
// Wire up shape refs
1029+
for _, op := range a.Operations {
1030+
op.InputRef.API = a
1031+
op.InputRef.Shape = a.Shapes[op.InputRef.ShapeName]
1032+
op.OutputRef.API = a
1033+
op.OutputRef.Shape = a.Shapes[op.OutputRef.ShapeName]
1034+
}
1035+
for _, s := range a.Shapes {
1036+
s.API = a
1037+
for k := range s.MemberRefs {
1038+
ref := s.MemberRefs[k]
1039+
ref.API = a
1040+
ref.Shape = a.Shapes[ref.ShapeName]
1041+
s.MemberRefs[k] = ref
1042+
}
1043+
if s.MemberRef.ShapeName != "" {
1044+
s.MemberRef.API = a
1045+
s.MemberRef.Shape = a.Shapes[s.MemberRef.ShapeName]
1046+
}
1047+
}
1048+
1049+
unionShape := a.Shapes["MemoryStrategyInput"]
1050+
if unionShape.OriginalShapeName != "" {
1051+
t.Fatalf("expected empty OriginalShapeName before rename, got %q", unionShape.OriginalShapeName)
1052+
}
1053+
1054+
a.renameIOSuffixedShapeNames()
1055+
1056+
// ShapeName gets underscore suffix, OriginalShapeName preserves the
1057+
// pre-rename value for downstream SDK code generation.
1058+
if unionShape.ShapeName != "MemoryStrategyInput_" {
1059+
t.Fatalf("expected ShapeName %q after rename, got %q", "MemoryStrategyInput_", unionShape.ShapeName)
1060+
}
1061+
if unionShape.OriginalShapeName != "MemoryStrategyInput" {
1062+
t.Fatalf("expected OriginalShapeName %q after rename, got %q", "MemoryStrategyInput", unionShape.OriginalShapeName)
1063+
}
1064+
}

pkg/generate/code/set_resource.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2454,6 +2454,11 @@ func setResourceForUnion(
24542454

24552455
sdkGoType := sourceShape.GoTypeWithPkgName()
24562456
sdkGoType = model.ReplacePkgName(sdkGoType, r.SDKAPIPackageName(), "svcsdktypes", true)
2457+
// Use the original shape name for SDK type references when the shape
2458+
// was renamed (e.g. Input/Output suffix collision avoidance).
2459+
if sourceShape.OriginalShapeName != "" {
2460+
sdkGoType = "*svcsdktypes." + sourceShape.OriginalShapeName
2461+
}
24572462

24582463
out += fmt.Sprintf("%sswitch %s.(type) {\n", indent, sourceVarName)
24592464
for _, targetMemberName := range targetShape.MemberNames() {

pkg/generate/code/set_resource_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5579,3 +5579,31 @@ func TestSetResource_BedrockAgentCoreControl_GatewayTarget_NestedUnionTypeSwitch
55795579
assert.Contains(got, "case *svcsdktypes.ApiSchemaConfigurationMemberInlinePayload:")
55805580
assert.Contains(got, "case *svcsdktypes.ApiSchemaConfigurationMemberS3:")
55815581
}
5582+
5583+
// TestSetResource_BedrockAgentCoreControl_Memory_InputSuffixUnion tests that
5584+
// union types whose names end in "Input" (e.g. MemoryStrategyInput) use the
5585+
// original SDK shape name in generated set-output code, not the renamed
5586+
// version with an underscore suffix (MemoryStrategyInput_).
5587+
func TestSetResource_BedrockAgentCoreControl_Memory_InputSuffixUnion(t *testing.T) {
5588+
assert := assert.New(t)
5589+
require := require.New(t)
5590+
5591+
g := testutil.NewModelForServiceWithOptions(t, "bedrock-agentcore-control", &testutil.TestingModelOptions{
5592+
GeneratorConfigFile: "generator-with-input-suffix-union.yaml",
5593+
})
5594+
5595+
crd := testutil.GetCRDByName(t, g, "Memory")
5596+
require.NotNil(crd)
5597+
assert.NotNil(crd.Ops.ReadOne)
5598+
5599+
got, err := code.SetResource(crd.Config(), crd, model.OpTypeGet, "resp", "ko", 1)
5600+
require.NoError(err)
5601+
5602+
// On the read path, union type switches must use the original SDK name
5603+
assert.NotContains(got, "MemoryStrategyInput_",
5604+
"Should use original SDK shape name MemoryStrategyInput, not renamed MemoryStrategyInput_")
5605+
assert.NotContains(got, "CustomConfigurationInput_",
5606+
"Should use original SDK shape name CustomConfigurationInput, not renamed version")
5607+
assert.NotContains(got, "TriggerConditionInput_",
5608+
"Should use original SDK shape name TriggerConditionInput, not renamed version")
5609+
}

pkg/generate/code/set_sdk.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1533,7 +1533,7 @@ func varEmptyConstructorSDKType(
15331533
// For SDK types, we need to use the original shape name (before stutter
15341534
// removal) since the AWS SDK uses the original names. The stutter removal
15351535
// renames are only for CRD types.
1536-
if shape.Type == "structure" && shape.OriginalShapeName != "" {
1536+
if (shape.Type == "structure" || shape.RealType == "union") && shape.OriginalShapeName != "" {
15371537
// Replace the renamed shape name with the original SDK shape name
15381538
goType = "svcsdktypes." + shape.OriginalShapeName
15391539
}
@@ -1863,6 +1863,11 @@ func setSDKForUnion(
18631863

18641864
sdkGoType := targetShape.GoTypeWithPkgName()
18651865
sdkGoType = model.ReplacePkgName(sdkGoType, r.SDKAPIPackageName(), "svcsdktypes", false)
1866+
// Use the original shape name for SDK type references when the shape
1867+
// was renamed (e.g. Input/Output suffix collision avoidance).
1868+
if targetShape.OriginalShapeName != "" {
1869+
sdkGoType = "svcsdktypes." + targetShape.OriginalShapeName
1870+
}
18661871

18671872
out += fmt.Sprintf("%sisInterfaceSet := false\n", indent)
18681873

pkg/generate/code/set_sdk_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6769,3 +6769,40 @@ func TestSetSDK_BedrockAgentCoreControl_GatewayTarget_NestedUnionNoDereference(t
67696769
// dereferenced (e.g., ApiGatewayTargetConfiguration is a regular struct)
67706770
assert.Contains(got, "f7f0f0Parent.Value = *f7f0f0\n")
67716771
}
6772+
6773+
// TestSetSDK_BedrockAgentCoreControl_Memory_InputSuffixUnion tests that
6774+
// union types whose names end in "Input" (e.g. MemoryStrategyInput) use
6775+
// the original SDK shape name in generated code, not the renamed version
6776+
// with an underscore suffix (MemoryStrategyInput_). The rename pass adds
6777+
// the underscore to avoid collisions with operation input types, but SDK
6778+
// type references must use the original name.
6779+
func TestSetSDK_BedrockAgentCoreControl_Memory_InputSuffixUnion(t *testing.T) {
6780+
assert := assert.New(t)
6781+
require := require.New(t)
6782+
6783+
g := testutil.NewModelForServiceWithOptions(t, "bedrock-agentcore-control", &testutil.TestingModelOptions{
6784+
GeneratorConfigFile: "generator-with-input-suffix-union.yaml",
6785+
})
6786+
6787+
crd := testutil.GetCRDByName(t, g, "Memory")
6788+
require.NotNil(crd)
6789+
assert.NotNil(crd.Ops.Create)
6790+
6791+
got, err := code.SetSDK(crd.Config(), crd, model.OpTypeCreate, "r.ko", "res", 1)
6792+
require.NoError(err)
6793+
6794+
// MemoryStrategyInput is a union whose name ends in "Input". The code-gen
6795+
// renames it to MemoryStrategyInput_ to avoid collision with operation
6796+
// input types. SDK references must use the original name.
6797+
assert.Contains(got, "svcsdktypes.MemoryStrategyInput")
6798+
assert.NotContains(got, "MemoryStrategyInput_",
6799+
"Should use original SDK shape name MemoryStrategyInput, not renamed MemoryStrategyInput_")
6800+
6801+
// CustomConfigurationInput is also a union ending in "Input"
6802+
assert.NotContains(got, "CustomConfigurationInput_",
6803+
"Should use original SDK shape name CustomConfigurationInput, not renamed version")
6804+
6805+
// TriggerConditionInput is also a union ending in "Input"
6806+
assert.NotContains(got, "TriggerConditionInput_",
6807+
"Should use original SDK shape name TriggerConditionInput, not renamed version")
6808+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
ignore:
2+
resource_names:
3+
- AgentRuntime
4+
- AgentRuntimeEndpoint
5+
- ApiKeyCredentialProvider
6+
- Browser
7+
- BrowserProfile
8+
- CodeInterpreter
9+
- Evaluator
10+
- Gateway
11+
- GatewayTarget
12+
# Memory
13+
- Oauth2CredentialProvider
14+
- OnlineEvaluationConfig
15+
- WorkloadIdentity
16+
- Policy
17+
- PolicyEngine
18+
field_paths:
19+
- MemoryStrategy.Configuration
20+
- CreateMemoryInput.ClientToken
21+
- UpdateMemoryInput.ClientToken
22+
- DeleteMemoryInput.ClientToken
23+
sdk_names:
24+
model_name: bedrock-agentcore-control
25+
26+
resources:
27+
Memory:
28+
ignore_idempotency_token: true
29+
fields:
30+
MemoryId:
31+
is_primary_key: true
32+
tags:
33+
ignore: true

0 commit comments

Comments
 (0)