From ff587f4c7302d334b1caa81d8bbccb4032063131 Mon Sep 17 00:00:00 2001 From: Matteo Bigoi <1781140+crisidev@users.noreply.github.com> Date: Wed, 16 Feb 2022 15:42:53 +0000 Subject: [PATCH] Add decorator to allow to make all operations fallible (#1190) Force all operations in the model to be fallible. When this decorator is applied, operations that do not have a Smithy error attatched, will return Result. To enable this decorator, create a file called META-INF/service/software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator containing codegen-server/src/main/resources/META-INF/services/software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator. Closes: #1150 Signed-off-by: Bigo <1781140+crisidev@users.noreply.github.com> --- .../FallibleOperationsDecorator.kt | 54 ++++++++++++++++ .../FallibleOperationsDecoratorTest.kt | 64 +++++++++++++++++++ .../ServerCombinedErrorGeneratorTest.kt | 4 +- 3 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/FallibleOperationsDecorator.kt create mode 100644 codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/FallibleOperationsDecoratorTest.kt rename codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/{ => server}/smithy/generators/ServerCombinedErrorGeneratorTest.kt (95%) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/FallibleOperationsDecorator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/FallibleOperationsDecorator.kt new file mode 100644 index 000000000..8a8f5915d --- /dev/null +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/FallibleOperationsDecorator.kt @@ -0,0 +1,54 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +package software.amazon.smithy.rust.codegen.server.smithy.customizations + +import software.amazon.smithy.model.Model +import software.amazon.smithy.model.shapes.MemberShape +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.model.shapes.ServiceShape +import software.amazon.smithy.model.shapes.StructureShape +import software.amazon.smithy.model.traits.ErrorTrait +import software.amazon.smithy.model.traits.RequiredTrait +import software.amazon.smithy.model.transform.ModelTransformer +import software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator + +/** + * Add at least one error to all operations in the model. + * + * When this decorator is applied, operations that do not have a Smithy error attatched, + * will return `Result`. + * + * To enable this decorator, create a file called `META-INF/services/software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator` + * containing `codegen-server/src/main/resources/META-INF/services/software.amazon.smithy.rust.codegen.smithy.customize.RustCodegenDecorator`. + */ +class FallibleOperationsDecorator : RustCodegenDecorator { + override val name: String = "FallibleOperations" + override val order: Byte = 0 + + private fun internalServerError(namespace: String): StructureShape { + return StructureShape.builder().id("$namespace#InternalServerError") + .addTrait(ErrorTrait("server")) + .addMember( + MemberShape.builder() + .id("$namespace#InternalServerError\$message") + .target("smithy.api#String") + .addTrait(RequiredTrait()) + .build() + ).build() + } + + override fun transformModel(service: ServiceShape, model: Model): Model { + val errorShape = internalServerError(service.id.getNamespace()) + val modelShapes = model.toBuilder().addShapes(listOf(errorShape)).build() + return ModelTransformer.create().mapShapes(modelShapes) { shape -> + if (shape is OperationShape && shape.errors.isEmpty()) { + shape.toBuilder().addError(errorShape).build() + } else { + shape + } + } + } +} diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/FallibleOperationsDecoratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/FallibleOperationsDecoratorTest.kt new file mode 100644 index 000000000..8c7126e48 --- /dev/null +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/FallibleOperationsDecoratorTest.kt @@ -0,0 +1,64 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +package software.amazon.smithy.rust.codegen.server.smithy.customizations + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.model.shapes.ServiceShape +import software.amazon.smithy.model.shapes.ShapeId +import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider +import software.amazon.smithy.rust.codegen.smithy.transformers.OperationNormalizer +import software.amazon.smithy.rust.codegen.testutil.asSmithyModel + +class FallibleOperationsDecoratorTest { + private val baseModel = """ + namespace smithy.test + use aws.protocols#restJson1 + + @restJson1 + @title("Test") + service Test { + version: "2022-01-01", + operations: [ + Infallible, + Fallible + ] + } + + operation Infallible { + input: InfallibleInput, + output: InfallibleOutput + } + structure InfallibleInput {} + structure InfallibleOutput {} + + operation Fallible { + input: FallibleInput, + output: FallibleOutput, + errors: [FallibleError] + } + structure FallibleInput {} + structure FallibleOutput {} + @error("client") + structure FallibleError {} + """.asSmithyModel() + private val model = OperationNormalizer.transform(baseModel) + private val symbolProvider = serverTestSymbolProvider(model) + + @Test + fun `add InternalServerError to infallible operations only`() { + val service = ServiceShape.builder().id("smithy.test#Test").build() + val infallibleId = ShapeId.from("smithy.test#Infallible") + val fallibleId = ShapeId.from("smithy.test#Fallible") + model.expectShape(infallibleId, OperationShape::class.java).errors.isEmpty() shouldBe true + model.expectShape(fallibleId, OperationShape::class.java).errors.size shouldBe 1 + val model = FallibleOperationsDecorator().transformModel(service, model) + model.expectShape(infallibleId, OperationShape::class.java).errors.isEmpty() shouldBe false + model.expectShape(infallibleId, OperationShape::class.java).errors.size shouldBe 1 + model.expectShape(fallibleId, OperationShape::class.java).errors.size shouldBe 1 + } +} diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/ServerCombinedErrorGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerCombinedErrorGeneratorTest.kt similarity index 95% rename from codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/ServerCombinedErrorGeneratorTest.kt rename to codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerCombinedErrorGeneratorTest.kt index 16d49da61..2dd9e88e0 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/smithy/generators/ServerCombinedErrorGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerCombinedErrorGeneratorTest.kt @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0. */ -package software.amazon.smithy.rust.codegen.smithy.generators +package software.amazon.smithy.rust.codegen.server.smithy.generators import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.rustlang.RustModule -import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerCombinedErrorGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider +import software.amazon.smithy.rust.codegen.smithy.generators.CodegenTarget import software.amazon.smithy.rust.codegen.smithy.transformers.OperationNormalizer import software.amazon.smithy.rust.codegen.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.testutil.asSmithyModel -- GitLab