Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for IDL 2.0 nullability semantics #1725

Merged
merged 3 commits into from
Sep 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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<Shape>()
for (struct in model.structureShapes) {
for (member in struct.allMembers.values) {
updates.add(member.toBuilder().addTrait(ClientOptionalTrait()).build())
}
}
return ModelTransformer.create().replaceShapes(model, updates)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Ec2Decorator : RustCodegenDecorator<ClientCodegenContext> {
// need to be boxed for the API to work properly
return model.letIf(
applies(service),
BoxPrimitiveShapes::processModel,
EC2MakePrimitivesOptional::processModel,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.core.util.hasTrait
import software.amazon.smithy.rust.codegen.core.util.lookup

internal class BoxPrimitiveShapesTest {
internal class EC2MakePrimitivesOptionalTest {
@Test
fun `primitive shapes are boxed`() {
val baseModel = """
Expand All @@ -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<StructureShape>("test#Primitives")
struct.members().forEach {
val target = model.expectShape(it.target)
when (target) {
is StructureShape -> target.hasTrait<BoxTrait>() shouldBe false
else -> target.hasTrait<BoxTrait>() shouldBe true
}
nullableIndex.isMemberNullable(it, NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1) shouldBe true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -61,8 +62,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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ data class SymbolVisitorConfig(
val runtimeConfig: RuntimeConfig,
val renameExceptions: Boolean,
val handleRustBoxing: Boolean,
val handleRequired: Boolean,
val nullabilityCheckMode: NullableIndex.CheckMode,
)

/**
Expand Down Expand Up @@ -210,13 +210,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<T>` when the shape has the `RustBoxTrait`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -37,7 +38,7 @@ val TestSymbolVisitorConfig = SymbolVisitorConfig(
runtimeConfig = TestRuntimeConfig,
renameExceptions = true,
handleRustBoxing = true,
handleRequired = false,
nullabilityCheckMode = NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1,
)

fun testRustSettings(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -24,7 +25,7 @@ val ServerTestSymbolVisitorConfig = SymbolVisitorConfig(
runtimeConfig = TestRuntimeConfig,
renameExceptions = false,
handleRustBoxing = true,
handleRequired = true,
nullabilityCheckMode = NullableIndex.CheckMode.SERVER,
)

fun serverTestSymbolProvider(
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down