diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 7d36001ddfd..a2a98e76179 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -236,3 +236,9 @@ renamed to `with_retry_classifier` and `retry_classifier` respectively. Public m references = ["smithy-rs#1715", "smithy-rs#1717"] meta = { "breaking" = true, "tada" = false, "bug" = false } author = "jdisanti" + +[[smithy-rs]] +message = "Correctly determine nullability of members in IDLv2 models" +references = ["smithy-rs#1725"] +meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "all"} +author = "sugmanue" diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/BoxPrimitiveShapes.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/BoxPrimitiveShapes.kt deleted file mode 100644 index bd830d463e0..00000000000 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/BoxPrimitiveShapes.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -package software.amazon.smithy.rustsdk.customize.ec2 - -import software.amazon.smithy.model.Model -import software.amazon.smithy.model.shapes.AbstractShapeBuilder -import software.amazon.smithy.model.shapes.BigDecimalShape -import software.amazon.smithy.model.shapes.BigIntegerShape -import software.amazon.smithy.model.shapes.BooleanShape -import software.amazon.smithy.model.shapes.ByteShape -import software.amazon.smithy.model.shapes.DoubleShape -import software.amazon.smithy.model.shapes.FloatShape -import software.amazon.smithy.model.shapes.IntegerShape -import software.amazon.smithy.model.shapes.LongShape -import software.amazon.smithy.model.shapes.NumberShape -import software.amazon.smithy.model.shapes.Shape -import software.amazon.smithy.model.shapes.ShortShape -import software.amazon.smithy.model.traits.BoxTrait -import software.amazon.smithy.model.transform.ModelTransformer -import software.amazon.smithy.rust.codegen.client.util.UNREACHABLE -import software.amazon.smithy.utils.ToSmithyBuilder - -object BoxPrimitiveShapes { - fun processModel(model: Model): Model { - val transformer = ModelTransformer.create() - return transformer.mapShapes(model, ::boxPrimitives) - } - - private fun boxPrimitives(shape: Shape): Shape { - return when (shape) { - is NumberShape -> { - when (shape) { - is ByteShape -> box(shape) - is DoubleShape -> box(shape) - is LongShape -> box(shape) - is ShortShape -> box(shape) - is FloatShape -> box(shape) - is BigDecimalShape -> box(shape) - is BigIntegerShape -> box(shape) - is IntegerShape -> box(shape) - else -> UNREACHABLE("unhandled numeric shape: $shape") - } - } - is BooleanShape -> box(shape) - else -> shape - } - } - - private fun box(shape: T): Shape where T : Shape, T : ToSmithyBuilder { - return (shape.toBuilder() as AbstractShapeBuilder<*, T>).addTrait(BoxTrait()).build() - } -} diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/EC2MakePrimitivesOptional.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/EC2MakePrimitivesOptional.kt new file mode 100644 index 00000000000..bff87c0d5d5 --- /dev/null +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/EC2MakePrimitivesOptional.kt @@ -0,0 +1,24 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rustsdk.customize.ec2 + +import software.amazon.smithy.model.Model +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.traits.ClientOptionalTrait +import software.amazon.smithy.model.transform.ModelTransformer + +object EC2MakePrimitivesOptional { + fun processModel(model: Model): Model { + val updates = arrayListOf() + for (struct in model.structureShapes) { + for (member in struct.allMembers.values) { + updates.add(member.toBuilder().addTrait(ClientOptionalTrait()).build()) + } + + } + return ModelTransformer.create().replaceShapes(model, updates) + } +} diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/Ec2Decorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/Ec2Decorator.kt index fb8e67faf94..784ed2c47a1 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/Ec2Decorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/ec2/Ec2Decorator.kt @@ -8,10 +8,10 @@ package software.amazon.smithy.rustsdk.customize.ec2 import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.ShapeId -import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext -import software.amazon.smithy.rust.codegen.client.smithy.CoreCodegenContext -import software.amazon.smithy.rust.codegen.client.smithy.customize.RustCodegenDecorator -import software.amazon.smithy.rust.codegen.client.smithy.letIf +import software.amazon.smithy.rust.codegen.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.smithy.CoreCodegenContext +import software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator +import software.amazon.smithy.rust.codegen.smithy.letIf class Ec2Decorator : RustCodegenDecorator { override val name: String = "Ec2" @@ -26,7 +26,7 @@ class Ec2Decorator : RustCodegenDecorator { // need to be boxed for the API to work properly return model.letIf( applies(service), - BoxPrimitiveShapes::processModel, + EC2MakePrimitivesOptional::processModel, ) } diff --git a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/customize/ec2/BoxPrimitiveShapesTest.kt b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/customize/ec2/EC2MakePrimitivesOptionalTest.kt similarity index 60% rename from aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/customize/ec2/BoxPrimitiveShapesTest.kt rename to aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/customize/ec2/EC2MakePrimitivesOptionalTest.kt index b9674c2b931..2d5f7325a72 100644 --- a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/customize/ec2/BoxPrimitiveShapesTest.kt +++ b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/customize/ec2/EC2MakePrimitivesOptionalTest.kt @@ -7,13 +7,12 @@ package software.amazon.smithy.rustsdk.customize.ec2 import io.kotest.matchers.shouldBe import org.junit.jupiter.api.Test +import software.amazon.smithy.model.knowledge.NullableIndex import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.model.traits.BoxTrait -import software.amazon.smithy.rust.codegen.client.testutil.asSmithyModel -import software.amazon.smithy.rust.codegen.client.util.hasTrait -import software.amazon.smithy.rust.codegen.client.util.lookup +import software.amazon.smithy.rust.codegen.testutil.asSmithyModel +import software.amazon.smithy.rust.codegen.util.lookup -internal class BoxPrimitiveShapesTest { +internal class AddClientOptionalToShapesTest { @Test fun `primitive shapes are boxed`() { val baseModel = """ @@ -33,15 +32,11 @@ internal class BoxPrimitiveShapesTest { structure Other {} """.asSmithyModel() - val model = BoxPrimitiveShapes.processModel(baseModel) - + val model = EC2MakePrimitivesOptional.processModel(baseModel) + val nullableIndex = NullableIndex(model) val struct = model.lookup("test#Primitives") struct.members().forEach { - val target = model.expectShape(it.target) - when (target) { - is StructureShape -> target.hasTrait() shouldBe false - else -> target.hasTrait() shouldBe true - } + nullableIndex.isMemberNullable(it, NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1) shouldBe true } } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/CodegenVisitor.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/CodegenVisitor.kt index 389e332ec30..665b74beb8c 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/CodegenVisitor.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/CodegenVisitor.kt @@ -7,6 +7,7 @@ package software.amazon.smithy.rust.codegen.client.smithy import software.amazon.smithy.build.PluginContext import software.amazon.smithy.model.Model +import software.amazon.smithy.model.knowledge.NullableIndex import software.amazon.smithy.model.neighbor.Walker import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.Shape @@ -60,8 +61,8 @@ class CodegenVisitor(context: PluginContext, private val codegenDecorator: RustC SymbolVisitorConfig( runtimeConfig = settings.runtimeConfig, renameExceptions = settings.codegenConfig.renameExceptions, - handleRequired = false, handleRustBoxing = true, + nullabilityCheckMode = NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1, ) val baseModel = baselineTransform(context.model) val service = settings.getService(baseModel) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/SymbolVisitor.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/SymbolVisitor.kt index f6ee87b5de1..405646ffd52 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/SymbolVisitor.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/SymbolVisitor.kt @@ -64,7 +64,7 @@ data class SymbolVisitorConfig( val runtimeConfig: RuntimeConfig, val renameExceptions: Boolean, val handleRustBoxing: Boolean, - val handleRequired: Boolean, + val nullabilityCheckMode: NullableIndex.CheckMode, ) /** @@ -209,13 +209,7 @@ open class SymbolVisitor( } private fun handleOptionality(symbol: Symbol, member: MemberShape): Symbol = - if (config.handleRequired && member.isRequired) { - symbol - } else if (nullableIndex.isNullable(member)) { - symbol.makeOptional() - } else { - symbol - } + symbol.letIf(nullableIndex.isMemberNullable(member, config.nullabilityCheckMode)) { symbol.makeOptional() } /** * Produce `Box` when the shape has the `RustBoxTrait` diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt index 54c2cf6b387..564dc32c0ed 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt @@ -6,6 +6,7 @@ package software.amazon.smithy.rust.codegen.client.testutil import software.amazon.smithy.model.Model +import software.amazon.smithy.model.knowledge.NullableIndex import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.shapes.StructureShape @@ -37,7 +38,7 @@ val TestSymbolVisitorConfig = SymbolVisitorConfig( runtimeConfig = TestRuntimeConfig, renameExceptions = true, handleRustBoxing = true, - handleRequired = false, + nullabilityCheckMode = NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1, ) fun testRustSettings( diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/SymbolBuilderTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/SymbolBuilderTest.kt index 2b3eeb083c8..96437c61402 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/SymbolBuilderTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/SymbolBuilderTest.kt @@ -125,17 +125,13 @@ class SymbolBuilderTest { "PrimitiveBoolean, false, bool", ) fun `creates primitives`(primitiveType: String, optional: Boolean, rustName: String) { - val memberBuilder = MemberShape.builder().id("foo.bar#MyStruct\$quux").target("smithy.api#$primitiveType") - val member = memberBuilder.build() - val struct = StructureShape.builder() - .id("foo.bar#MyStruct") - .addMember(member) - .build() - val model = Model.assembler() - .addShapes(struct, member) - .assemble() - .unwrap() - + val model = """ + namespace foo.bar + structure MyStruct { + quux: $primitiveType + } +""".asSmithyModel() + val member = model.expectShape(ShapeId.from("foo.bar#MyStruct\$quux")) val provider: SymbolProvider = testSymbolProvider(model) val memberSymbol = provider.toSymbol(member) // builtins should not have a namespace set diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerCodegenVisitor.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerCodegenVisitor.kt index 1f894ea4ada..78151e02e60 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerCodegenVisitor.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerCodegenVisitor.kt @@ -8,6 +8,7 @@ package software.amazon.smithy.rust.codegen.server.python.smithy import software.amazon.smithy.build.PluginContext import software.amazon.smithy.codegen.core.CodegenException +import software.amazon.smithy.model.knowledge.NullableIndex import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.StructureShape @@ -46,8 +47,8 @@ class PythonServerCodegenVisitor( SymbolVisitorConfig( runtimeConfig = settings.runtimeConfig, renameExceptions = false, - handleRequired = true, handleRustBoxing = true, + nullabilityCheckMode = NullableIndex.CheckMode.SERVER, ) val baseModel = baselineTransform(context.model) val service = settings.getService(baseModel) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt index 921ce79aaeb..4337dda97b7 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt @@ -7,6 +7,7 @@ package software.amazon.smithy.rust.codegen.server.smithy import software.amazon.smithy.build.PluginContext import software.amazon.smithy.model.Model +import software.amazon.smithy.model.knowledge.NullableIndex import software.amazon.smithy.model.neighbor.Walker import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.Shape @@ -69,8 +70,8 @@ open class ServerCodegenVisitor( SymbolVisitorConfig( runtimeConfig = settings.runtimeConfig, renameExceptions = false, - handleRequired = true, handleRustBoxing = true, + nullabilityCheckMode = NullableIndex.CheckMode.SERVER, ) val baseModel = baselineTransform(context.model) val service = settings.getService(baseModel) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt index eadfabdf219..e6e930e6313 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt @@ -6,6 +6,7 @@ package software.amazon.smithy.rust.codegen.server.smithy.testutil import software.amazon.smithy.model.Model +import software.amazon.smithy.model.knowledge.NullableIndex import software.amazon.smithy.model.node.ObjectNode import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.ShapeId @@ -24,7 +25,7 @@ val ServerTestSymbolVisitorConfig = SymbolVisitorConfig( runtimeConfig = TestRuntimeConfig, renameExceptions = false, handleRustBoxing = true, - handleRequired = true, + nullabilityCheckMode = NullableIndex.CheckMode.SERVER, ) fun serverTestSymbolProvider( diff --git a/gradle.properties b/gradle.properties index a5e8c71f08f..9e739d51a7b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,7 +15,7 @@ kotlin.code.style=official # codegen smithyGradlePluginVersion=0.6.0 -smithyVersion=1.23.1 +smithyVersion=1.25.0 # kotlin kotlinVersion=1.6.21