Skip to content

Commit 23f415e

Browse files
committed
Fixed errors and added complete union serialization implementation
- Added core serialization fixes in JsonSerializerGenerator and QuerySerializerGenerator - Fixed variable reference consistency (_inner vs inner) to prevent unused warnings - Corrected test structure with shared model and proper test locations - Ensured protocol_serde module generation works correctly - All tests now pass without compilation errors or unused variable warnings
1 parent 0859533 commit 23f415e

File tree

4 files changed

+52
-57
lines changed

4 files changed

+52
-57
lines changed

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/JsonSerializerGenerator.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,14 +555,28 @@ class JsonSerializerGenerator(
555555
}
556556
rustBlock("match input") {
557557
for (member in context.shape.members()) {
558+
val memberShape = model.expectShape(member.target)
558559
val variantName =
559560
if (member.isTargetUnit()) {
560561
"${symbolProvider.toMemberName(member)}"
562+
} else if (memberShape.isStructureShape &&
563+
memberShape.asStructureShape().get().allMembers.isEmpty()
564+
) {
565+
// Unit structs don't serialize inner, so it is never accessed
566+
"${symbolProvider.toMemberName(member)}(_inner)"
561567
} else {
562568
"${symbolProvider.toMemberName(member)}(inner)"
563569
}
564570
withBlock("#T::$variantName => {", "},", unionSymbol) {
565-
serializeMember(MemberContext.unionMember(context, "inner", member, jsonName))
571+
val innerRef =
572+
if (memberShape.isStructureShape &&
573+
memberShape.asStructureShape().get().allMembers.isEmpty()
574+
) {
575+
"_inner"
576+
} else {
577+
"inner"
578+
}
579+
serializeMember(MemberContext.unionMember(context, innerRef, member, jsonName))
566580
}
567581
}
568582
if (codegenTarget.renderUnknownVariant()) {

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/QuerySerializerGenerator.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,10 +371,18 @@ abstract class QuerySerializerGenerator(private val codegenContext: CodegenConte
371371
"$memberName(inner)"
372372
}
373373
withBlock("#T::$variantName => {", "},", unionSymbol) {
374+
val innerRef =
375+
if (memberShape.isStructureShape &&
376+
memberShape.asStructureShape().get().allMembers.isEmpty()
377+
) {
378+
"_inner"
379+
} else {
380+
"inner"
381+
}
374382
serializeMember(
375383
MemberContext.unionMember(
376384
context.copy(writerExpression = "writer"),
377-
"inner",
385+
innerRef,
378386
member,
379387
),
380388
)

codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/JsonSerializerGeneratorTest.kt

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,6 @@ import software.amazon.smithy.rust.codegen.core.util.inputShape
3333
import software.amazon.smithy.rust.codegen.core.util.lookup
3434

3535
class JsonSerializerGeneratorTest {
36-
private val unionWithUnitStructModel =
37-
"""
38-
namespace test
39-
use aws.protocols#restJson1
40-
41-
union TestUnion {
42-
unitMember: Unit
43-
}
44-
45-
// Empty unit struct that doesn't need serialization parameters
46-
structure Unit {}
47-
48-
@http(uri: "/test", method: "POST")
49-
operation TestOp {
50-
input: TestInput
51-
}
52-
53-
structure TestInput {
54-
union: TestUnion
55-
}
56-
""".asSmithyModel()
57-
5836
private val baseModel =
5937
"""
6038
namespace test
@@ -371,7 +349,7 @@ class JsonSerializerGeneratorTest {
371349
fun `union with unit struct doesn't cause unused variable warning`() {
372350
// Regression test for https://github.com/smithy-lang/smithy-rs/issues/4308
373351
// This test ensures that union serialization with unit structs compiles without unused variable warnings.
374-
val model = RecursiveShapeBoxer().transform(OperationNormalizer.transform(unionWithUnitStructModel))
352+
val model = RecursiveShapeBoxer().transform(OperationNormalizer.transform(QuerySerializerGeneratorTest.unionWithUnitStructModel))
375353

376354
val codegenContext = testCodegenContext(model)
377355
val symbolProvider = codegenContext.symbolProvider

codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/QuerySerializerGeneratorTest.kt

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,44 +22,40 @@ import software.amazon.smithy.rust.codegen.core.util.inputShape
2222
import software.amazon.smithy.rust.codegen.core.util.lookup
2323

2424
class QuerySerializerGeneratorTest {
25+
companion object {
26+
val unionWithUnitStructModel =
27+
"""
28+
namespace test
29+
30+
union TestUnion {
31+
unitMember: Unit
32+
}
33+
34+
structure Unit {}
35+
36+
@http(uri: "/test", method: "POST")
37+
operation TestOp {
38+
input: TestInput
39+
}
40+
41+
structure TestInput {
42+
union: TestUnion
43+
}
44+
""".asSmithyModel()
45+
}
46+
2547
@Test
2648
fun `union with unit struct doesn't cause unused variable warning`() {
2749
// Regression test for https://github.com/smithy-lang/smithy-rs/issues/4308
28-
// This test ensures that Query serialization with unit structs compiles without unused variable warnings.
29-
// Query serialization for unit structs generates empty blocks where the variable would be unused,
30-
// so the fix uses '_inner' (with underscore prefix) to suppress the unused variable warning.
31-
val model =
32-
RecursiveShapeBoxer().transform(
33-
OperationNormalizer.transform(
34-
"""
35-
namespace test
36-
37-
union TestUnion {
38-
unitMember: Unit
39-
}
40-
41-
structure Unit {}
42-
43-
@http(uri: "/test", method: "POST")
44-
operation TestOp {
45-
input: TestInput
46-
}
47-
48-
structure TestInput {
49-
union: TestUnion
50-
}
51-
""".asSmithyModel(),
52-
),
53-
)
50+
val model = RecursiveShapeBoxer().transform(OperationNormalizer.transform(unionWithUnitStructModel))
5451

5552
val codegenContext = testCodegenContext(model)
5653
val symbolProvider = codegenContext.symbolProvider
57-
58-
val parserSerializer = AwsQuerySerializerGenerator(codegenContext)
59-
val operationGenerator = parserSerializer.operationInputSerializer(model.lookup("test#TestOp"))
60-
6154
val project = TestWorkspace.testProject(symbolProvider)
6255

56+
val querySerializer = Ec2QuerySerializerGenerator(codegenContext)
57+
val operationGenerator = querySerializer.operationInputSerializer(model.lookup("test#TestOp"))
58+
6359
// Render all necessary structures and unions
6460
model.lookup<StructureShape>("test#Unit").renderWithModelBuilder(model, symbolProvider, project)
6561
model.lookup<OperationShape>("test#TestOp").inputShape(model).renderWithModelBuilder(model, symbolProvider, project)
@@ -70,7 +66,7 @@ class QuerySerializerGeneratorTest {
7066

7167
project.lib {
7268
unitTest(
73-
"query_union_serialization_fix_works",
69+
"test_query_union_serialization",
7470
"""
7571
use test_model::{TestUnion, Unit};
7672
@@ -88,7 +84,6 @@ class QuerySerializerGeneratorTest {
8884
)
8985
}
9086

91-
// The test passes if the generated code compiles without unused variable warnings
9287
project.compileAndTest()
9388
}
9489
}

0 commit comments

Comments
 (0)