diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsPresigningDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsPresigningDecorator.kt index 3a9002e5e86cafcbb8fd1c6a19ae252b0ad14fed..1d9f14e5a860c88e6b015de2a724d49e1b304c1b 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsPresigningDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsPresigningDecorator.kt @@ -155,7 +155,7 @@ class AwsInputPresignedMethod( } private fun RustWriter.writeInputPresignedMethod(section: OperationSection.InputImpl) { - val operationError = operationShape.errorSymbol(codegenContext.model, symbolProvider, codegenContext.target) + val operationError = operationShape.errorSymbol(symbolProvider) val presignableOp = PRESIGNABLE_OPERATIONS.getValue(operationShape.id) val makeOperationOp = if (presignableOp.hasModelTransforms()) { diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientCodegenVisitor.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientCodegenVisitor.kt index d89f387925c0580b4165bbe2a16fc8f876b478dd..d99b7ccf69f95a33caf46719f843bd72971462f7 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientCodegenVisitor.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientCodegenVisitor.kt @@ -9,6 +9,7 @@ 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.OperationShape import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.shapes.ShapeVisitor @@ -23,6 +24,7 @@ import software.amazon.smithy.rust.codegen.client.smithy.generators.protocol.Cli import software.amazon.smithy.rust.codegen.client.smithy.protocols.ClientProtocolLoader import software.amazon.smithy.rust.codegen.client.smithy.transformers.AddErrorMessage import software.amazon.smithy.rust.codegen.client.smithy.transformers.RemoveEventStreamOperations +import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.SymbolVisitorConfig @@ -30,15 +32,20 @@ import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerat import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator +import software.amazon.smithy.rust.codegen.core.smithy.generators.error.OperationErrorGenerator +import software.amazon.smithy.rust.codegen.core.smithy.generators.error.eventStreamErrorSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.implBlock import software.amazon.smithy.rust.codegen.core.smithy.protocols.ProtocolGeneratorFactory import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait import software.amazon.smithy.rust.codegen.core.smithy.transformers.EventStreamNormalizer import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer import software.amazon.smithy.rust.codegen.core.smithy.transformers.RecursiveShapeBoxer +import software.amazon.smithy.rust.codegen.core.smithy.transformers.eventStreamErrors +import software.amazon.smithy.rust.codegen.core.smithy.transformers.operationErrors import software.amazon.smithy.rust.codegen.core.util.CommandFailed import software.amazon.smithy.rust.codegen.core.util.getTrait import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.rust.codegen.core.util.isEventStream import software.amazon.smithy.rust.codegen.core.util.letIf import software.amazon.smithy.rust.codegen.core.util.runCommand import java.util.logging.Logger @@ -217,5 +224,30 @@ class ClientCodegenVisitor( rustCrate.useShapeWriter(shape) { UnionGenerator(model, symbolProvider, this, shape, renderUnknownVariant = true).render() } + if (shape.isEventStream()) { + rustCrate.withModule(RustModule.Error) { + val symbol = symbolProvider.toSymbol(shape) + val errors = shape.eventStreamErrors() + .map { model.expectShape(it.asMemberShape().get().target, StructureShape::class.java) } + val errorSymbol = shape.eventStreamErrorSymbol(symbolProvider) + OperationErrorGenerator(model, symbolProvider, symbol, errors) + .renderErrors(this, errorSymbol, symbol) + } + } + } + + /** + * Generate errors for operation shapes + */ + override fun operationShape(shape: OperationShape) { + rustCrate.withModule(RustModule.Error) { + val operationSymbol = symbolProvider.toSymbol(shape) + OperationErrorGenerator( + model, + symbolProvider, + operationSymbol, + shape.operationErrors(model).map { it.asStructureShape().get() }, + ).render(this) + } } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt index 0663eecefa2f39fd2bfc1a2a2f53cb2fbd3398a5..54982643e8b1bb9b26f5045c8ddbf090cb615a85 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt @@ -21,7 +21,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol @@ -80,7 +79,7 @@ class PaginatorGenerator private constructor( private val inputType = symbolProvider.toSymbol(operation.inputShape(model)) private val outputShape = operation.outputShape(model) private val outputType = symbolProvider.toSymbol(outputShape) - private val errorType = operation.errorSymbol(model, symbolProvider, CodegenTarget.CLIENT) + private val errorType = operation.errorSymbol(symbolProvider) private fun paginatorType(): RuntimeType = RuntimeType.forInlineFun( paginatorName, diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceGenerator.kt index f21f56dfaf8c2c50d0e04364a5c77eec349a528d..6710ac9c3d56cd33353e3723dadc8f77b2040493 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceGenerator.kt @@ -14,7 +14,7 @@ import software.amazon.smithy.rust.codegen.client.smithy.generators.protocol.Pro import software.amazon.smithy.rust.codegen.core.rustlang.Attribute import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.RustCrate -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.TopLevelErrorGenerator +import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ServiceErrorGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolSupport import software.amazon.smithy.rust.codegen.core.util.inputShape @@ -56,7 +56,7 @@ class ServiceGenerator( } } - TopLevelErrorGenerator(clientCodegenContext, operations).render(rustCrate) + ServiceErrorGenerator(clientCodegenContext, operations).render(rustCrate) rustCrate.withModule(RustModule.Config) { ServiceConfigGenerator.withBaseBehavior( diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt index 903b0d25f303352678e4e09994af6a821fefcde6..08f77fe6b6e1ebc00281d303d8d362345f14910f 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt @@ -36,7 +36,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTypeParameters import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.rustlang.writable -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider @@ -167,7 +166,7 @@ class FluentClientGenerator( val output = operation.outputShape(model) val operationOk = symbolProvider.toSymbol(output) - val operationErr = operation.errorSymbol(model, symbolProvider, CodegenTarget.CLIENT).toSymbol() + val operationErr = operation.errorSymbol(symbolProvider).toSymbol() val inputFieldsBody = generateOperationShapeDocs(writer, symbolProvider, operation, model).joinToString("\n") { @@ -261,7 +260,7 @@ class FluentClientGenerator( "bounds" to generics.bounds, ) { val outputType = symbolProvider.toSymbol(operation.outputShape(model)) - val errorType = operation.errorSymbol(model, symbolProvider, CodegenTarget.CLIENT) + val errorType = operation.errorSymbol(symbolProvider) // Have to use fully-qualified result here or else it could conflict with an op named Result rustTemplate( @@ -331,7 +330,7 @@ class FluentClientGenerator( customizations, FluentClientSection.FluentBuilderImpl( operation, - operation.errorSymbol(model, symbolProvider, CodegenTarget.CLIENT), + operation.errorSymbol(symbolProvider), ), ) input.members().forEach { member -> diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt index 632bdf7849291c76686e1548cdf4769413350725..def2229565f9c5803a395570bc29d7cb6cc95bcf 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGenerator.kt @@ -301,8 +301,7 @@ class ProtocolTestGenerator( "parse_http_response" to RuntimeType.parseHttpResponse(codegenContext.runtimeConfig), ) if (expectedShape.hasTrait()) { - val errorSymbol = - operationShape.errorSymbol(codegenContext.model, codegenContext.symbolProvider, codegenContext.target) + val errorSymbol = operationShape.errorSymbol(codegenContext.symbolProvider) val errorVariant = codegenContext.symbolProvider.toSymbol(expectedShape).name rust("""let parsed = parsed.expect_err("should be error response");""") rustBlock("if let #TKind::$errorVariant(actual_error) = parsed.kind", errorSymbol) { diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/HttpBoundProtocolGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/HttpBoundProtocolGenerator.kt index a312bf9bb549c19a9c317c3871f8c6c83d2bb31e..b78ddfe059015f1cf242f16e56d1070abe108463 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/HttpBoundProtocolGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/HttpBoundProtocolGenerator.kt @@ -125,7 +125,7 @@ class HttpBoundProtocolTraitImplGenerator( }""", *codegenScope, "O" to outputSymbol, - "E" to operationShape.errorSymbol(model, symbolProvider, codegenContext.target), + "E" to operationShape.errorSymbol(symbolProvider), "parse_error" to parseError(operationShape), "parse_response" to parseResponse(operationShape, customizations), ) @@ -156,7 +156,7 @@ class HttpBoundProtocolTraitImplGenerator( } """, "O" to outputSymbol, - "E" to operationShape.errorSymbol(model, symbolProvider, codegenContext.target), + "E" to operationShape.errorSymbol(symbolProvider), "parse_streaming_response" to parseStreamingResponse(operationShape, customizations), "parse_error" to parseError(operationShape), *codegenScope, @@ -167,7 +167,7 @@ class HttpBoundProtocolTraitImplGenerator( val fnName = "parse_${operationShape.id.name.toSnakeCase()}_error" val outputShape = operationShape.outputShape(model) val outputSymbol = symbolProvider.toSymbol(outputShape) - val errorSymbol = operationShape.errorSymbol(model, symbolProvider, codegenContext.target) + val errorSymbol = operationShape.errorSymbol(symbolProvider) return RuntimeType.forInlineFun(fnName, operationDeserModule) { Attribute.Custom("allow(clippy::unnecessary_wraps)").render(this) rustBlockTemplate( @@ -241,7 +241,7 @@ class HttpBoundProtocolTraitImplGenerator( val fnName = "parse_${operationShape.id.name.toSnakeCase()}" val outputShape = operationShape.outputShape(model) val outputSymbol = symbolProvider.toSymbol(outputShape) - val errorSymbol = operationShape.errorSymbol(model, symbolProvider, codegenContext.target) + val errorSymbol = operationShape.errorSymbol(symbolProvider) return RuntimeType.forInlineFun(fnName, operationDeserModule) { Attribute.Custom("allow(clippy::unnecessary_wraps)").render(this) rustBlockTemplate( @@ -270,7 +270,7 @@ class HttpBoundProtocolTraitImplGenerator( val fnName = "parse_${operationShape.id.name.toSnakeCase()}_response" val outputShape = operationShape.outputShape(model) val outputSymbol = symbolProvider.toSymbol(outputShape) - val errorSymbol = operationShape.errorSymbol(model, symbolProvider, codegenContext.target) + val errorSymbol = operationShape.errorSymbol(symbolProvider) return RuntimeType.forInlineFun(fnName, operationDeserModule) { Attribute.Custom("allow(clippy::unnecessary_wraps)").render(this) rustBlockTemplate( @@ -352,7 +352,7 @@ class HttpBoundProtocolTraitImplGenerator( httpBindingGenerator: ResponseBindingGenerator, structuredDataParser: StructuredDataParserGenerator, ): Writable? { - val errorSymbol = operationShape.errorSymbol(model, symbolProvider, codegenContext.target) + val errorSymbol = operationShape.errorSymbol(symbolProvider) val member = binding.member return when (binding.location) { HttpLocation.HEADER -> writable { diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/CodegenVisitorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientCodegenVisitorTest.kt similarity index 98% rename from codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/CodegenVisitorTest.kt rename to codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientCodegenVisitorTest.kt index f337d05659e86509201680d99e02244f3cd16d09..2cb21423fd453402367e14089ce8a7184d07b6a9 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/CodegenVisitorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientCodegenVisitorTest.kt @@ -16,7 +16,7 @@ import software.amazon.smithy.rust.codegen.client.smithy.generators.client.Fluen import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext -class CodegenVisitorTest { +class ClientCodegenVisitorTest { @Test fun `baseline transform verify mixins removed`() { val model = """ diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGeneratorTest.kt index b6421c6533951c3b005be4708061ff1c1aa462a7..4e31ab07736e9066cb034b1686bd19201eb204b0 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolTestGeneratorTest.kt @@ -66,7 +66,7 @@ private class TestProtocolTraitImplGenerator( }""", "parse_strict" to RuntimeType.parseStrictResponse(codegenContext.runtimeConfig), "Output" to symbolProvider.toSymbol(operationShape.outputShape(codegenContext.model)), - "Error" to operationShape.errorSymbol(codegenContext.model, symbolProvider, codegenContext.target), + "Error" to operationShape.errorSymbol(symbolProvider), "Response" to RuntimeType.HttpResponse, "Bytes" to RuntimeType.Bytes, ) diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt index 3f6a7a8c564833e6c805576643ed0f3622ef01ed..1717dab2d676822c22c9b0bcf9b175788a1f852a 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamBaseRequirements.kt @@ -8,6 +8,7 @@ package software.amazon.smithy.rust.codegen.client.smithy.protocols.eventstream import org.junit.jupiter.api.extension.ExtensionContext import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.ArgumentsProvider +import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.ShapeId @@ -18,7 +19,9 @@ import software.amazon.smithy.rust.codegen.client.testutil.clientTestRustSetting import software.amazon.smithy.rust.codegen.client.testutil.testSymbolProvider import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget +import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerator +import software.amazon.smithy.rust.codegen.core.smithy.generators.error.OperationErrorGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.implBlock import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestModels import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestRequirements @@ -56,4 +59,14 @@ abstract class ClientEventStreamBaseRequirements : EventStreamTestRequirements, + ) { + OperationErrorGenerator(model, symbolProvider, operationSymbol, errors).render(writer) + } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt index 332ec5e002f07632230d70985860a9e3690bd8c4..e7a5f6792b1b3b42101627070bbb46a111e8f3e2 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustModule.kt @@ -5,6 +5,8 @@ package software.amazon.smithy.rust.codegen.core.rustlang +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType + /** * RustModule system. * @@ -137,4 +139,7 @@ sealed class RustModule { else -> {} } } + + /** Converts this [RustModule] into a [RuntimeType] */ + fun toType(): RuntimeType = RuntimeType(fullyQualifiedPath()) } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/EventStreamSymbolProvider.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/EventStreamSymbolProvider.kt index 54b43f722b09e436c87c053b6601d3fc603b6ac7..1aff86f7d49124dacf33335c64363215f5da9c13 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/EventStreamSymbolProvider.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/EventStreamSymbolProvider.kt @@ -49,7 +49,7 @@ class EventStreamSymbolProvider( val error = if (target == CodegenTarget.SERVER && unionShape.eventStreamErrors().isEmpty()) { RuntimeType.smithyHttp(runtimeConfig).resolve("event_stream::MessageStreamError").toSymbol() } else { - unionShape.eventStreamErrorSymbol(model, this, target).toSymbol() + unionShape.eventStreamErrorSymbol(this).toSymbol() } val errorFmt = error.rustType().render(fullyQualified = true) val innerFmt = initial.rustType().stripOuter().render(fullyQualified = true) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/CombinedErrorGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGenerator.kt similarity index 78% rename from codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/CombinedErrorGenerator.kt rename to codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGenerator.kt index d4dbc2c7bb15f8d2f83d8e73c47601e254b44da9..7e5bf08b7fdcdc6ef4eefaec39b48e83009ddd4d 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/CombinedErrorGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGenerator.kt @@ -25,18 +25,15 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.customize.Section -import software.amazon.smithy.rust.codegen.core.smithy.transformers.eventStreamErrors -import software.amazon.smithy.rust.codegen.core.smithy.transformers.operationErrors import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.toSnakeCase /** - * For a given Operation ([this]), return the symbol referring to the unified error. This can be used - * if you, e.g. want to return a unified error from a function: + * For a given Operation ([this]), return the symbol referring to the operation error. This can be used + * if you, e.g. want to return an operation error from a function: * * ```kotlin * rustWriter.rustBlock("fn get_error() -> #T", operation.errorSymbol(symbolProvider)) { @@ -44,80 +41,21 @@ import software.amazon.smithy.rust.codegen.core.util.toSnakeCase * } * ``` */ -/* - TODO(Error): refactor when core-codegen is available - This is a possible future implementation: - ``` - inline fun OperationShape.errorSymbol( - model: Model, - symbolProvider: RustSymbolProvider, - generator: KClass - ): RuntimeType { - val symbol = symbolProvider.toSymbol(this) - return RuntimeType.forInlineFun("${symbol.name}Error", RustModule.Error) { - generator.java.newInstance().render( - this, - model, - symbolProvider, - symbol, - this.operationErrors(model).map { it.asStructureShape().get() } - ) - } - } - ``` - Similarly for eventStreamErrorSymbol() below - */ -fun OperationShape.errorSymbol( - model: Model, - symbolProvider: RustSymbolProvider, - target: CodegenTarget, -): RuntimeType { - val symbol = symbolProvider.toSymbol(this) - return RuntimeType.forInlineFun("${symbol.name}Error", RustModule.Error) { - when (target) { - CodegenTarget.CLIENT -> CombinedErrorGenerator( - model, - symbolProvider, - symbol, - operationErrors(model).map { it.asStructureShape().get() }, - ).render(this) - CodegenTarget.SERVER -> ServerCombinedErrorGenerator( - model, - symbolProvider, - symbol, - operationErrors(model).map { it.asStructureShape().get() }, - ).render(this) - } - } +fun OperationShape.errorSymbol(symbolProvider: RustSymbolProvider): RuntimeType { + val operationSymbol = symbolProvider.toSymbol(this) + return RustModule.Error.toType().resolve("${operationSymbol.name}Error") } -fun UnionShape.eventStreamErrorSymbol(model: Model, symbolProvider: RustSymbolProvider, target: CodegenTarget): RuntimeType { - val symbol = symbolProvider.toSymbol(this) - val errorSymbol = RuntimeType("crate::error::${symbol.name}Error") - return RuntimeType.forInlineFun("${symbol.name}Error", RustModule.Error) { - val errors = this@eventStreamErrorSymbol.eventStreamErrors().map { model.expectShape(it.asMemberShape().get().target, StructureShape::class.java) } - when (target) { - CodegenTarget.CLIENT -> - CombinedErrorGenerator(model, symbolProvider, symbol, errors).renderErrors( - this, - errorSymbol, - symbol, - ) - CodegenTarget.SERVER -> - ServerCombinedErrorGenerator(model, symbolProvider, symbol, errors).renderErrors( - this, - errorSymbol, - symbol, - ) - } - } +fun UnionShape.eventStreamErrorSymbol(symbolProvider: RustSymbolProvider): RuntimeType { + val unionSymbol = symbolProvider.toSymbol(this) + return RustModule.Error.toType().resolve("${unionSymbol.name}Error") } /** * Generates a unified error enum for [operation]. [ErrorGenerator] handles generating the individual variants, * but we must still combine those variants into an enum covering all possible errors for a given operation. */ -class CombinedErrorGenerator( +class OperationErrorGenerator( private val model: Model, private val symbolProvider: RustSymbolProvider, private val operationSymbol: Symbol, diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/TopLevelErrorGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGenerator.kt similarity index 93% rename from codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/TopLevelErrorGenerator.kt rename to codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGenerator.kt index bf3c8ccb995614770704cad2282f93ffcf1659a5..c03a30b6ccac49159389834a3755fb2eec1da9ae 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/TopLevelErrorGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGenerator.kt @@ -42,7 +42,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.transformers.eventStreamE * } * ``` */ -class TopLevelErrorGenerator(private val codegenContext: CodegenContext, private val operations: List) { +class ServiceErrorGenerator(private val codegenContext: CodegenContext, private val operations: List) { private val symbolProvider = codegenContext.symbolProvider private val model = codegenContext.model @@ -59,7 +59,7 @@ class TopLevelErrorGenerator(private val codegenContext: CodegenContext, private // Every operation error can be converted into service::Error operations.forEach { operationShape -> // operation errors - renderImplFrom(operationShape.errorSymbol(model, symbolProvider, codegenContext.target), operationShape.errors) + renderImplFrom(operationShape.errorSymbol(symbolProvider), operationShape.errors) } // event stream errors operations.map { it.eventStreamErrors(codegenContext.model) } @@ -67,11 +67,7 @@ class TopLevelErrorGenerator(private val codegenContext: CodegenContext, private .associate { it.key to it.value } .forEach { (unionShape, errors) -> renderImplFrom( - unionShape.eventStreamErrorSymbol( - model, - symbolProvider, - codegenContext.target, - ), + unionShape.eventStreamErrorSymbol(symbolProvider), errors.map { it.id }, ) } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt index b78f347002a0c353546e83386a40141dbb35a767..e6bf4812f3489ba72ebf05d063e5a7f16227799b 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt @@ -60,7 +60,7 @@ class EventStreamUnmarshallerGenerator( private val errorSymbol = if (codegenTarget == CodegenTarget.SERVER && unionShape.eventStreamErrors().isEmpty()) { RuntimeType.smithyHttp(runtimeConfig).resolve("event_stream::MessageStreamError").toSymbol() } else { - unionShape.eventStreamErrorSymbol(model, symbolProvider, codegenTarget).toSymbol() + unionShape.eventStreamErrorSymbol(symbolProvider).toSymbol() } private val smithyEventStream = RuntimeType.smithyEventStream(runtimeConfig) private val eventStreamSerdeModule = RustModule.private("event_stream_serde") diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/EventStreamErrorMarshallerGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/EventStreamErrorMarshallerGenerator.kt index e6e234be7ec051ccb7535ae13aba314d82482a6c..e4ec2cec3ac55256823dc0d82e9e6f50df5bb12f 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/EventStreamErrorMarshallerGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/EventStreamErrorMarshallerGenerator.kt @@ -48,7 +48,7 @@ class EventStreamErrorMarshallerGenerator( private val operationErrorSymbol = if (target == CodegenTarget.SERVER && unionShape.eventStreamErrors().isEmpty()) { RuntimeType.smithyHttp(runtimeConfig).resolve("event_stream::MessageStreamError").toSymbol() } else { - unionShape.eventStreamErrorSymbol(model, symbolProvider, target).toSymbol() + unionShape.eventStreamErrorSymbol(symbolProvider).toSymbol() } private val eventStreamSerdeModule = RustModule.private("event_stream_serde") private val errorsShape = unionShape.expectTrait() diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt index f6b07bed212c0ae282138dc6f576f3f310aca042..05151b7ce7c829c5b124ee1d91dcd445f57eb331 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestTools.kt @@ -5,6 +5,7 @@ package software.amazon.smithy.rust.codegen.core.testutil +import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.ServiceShape @@ -23,8 +24,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.CombinedErrorGenerator -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ServerCombinedErrorGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.renderUnknownVariant import software.amazon.smithy.rust.codegen.core.smithy.protocols.Protocol import software.amazon.smithy.rust.codegen.core.smithy.transformers.EventStreamNormalizer @@ -71,6 +70,15 @@ interface EventStreamTestRequirements { codegenContext: C, shape: StructureShape, ) + + /** Render an operation error for the given operation and error shapes */ + fun renderOperationError( + writer: RustWriter, + model: Model, + symbolProvider: RustSymbolProvider, + operationSymbol: Symbol, + errors: List, + ) } object EventStreamTestTools { @@ -115,11 +123,9 @@ object EventStreamTestTools { val operationSymbol = symbolProvider.toSymbol(operationShape) project.withModule(ErrorsModule) { val errors = model.structureShapes.filter { shape -> shape.hasTrait() } - when (codegenTarget) { - CodegenTarget.CLIENT -> CombinedErrorGenerator(model, symbolProvider, operationSymbol, errors).render(this) - CodegenTarget.SERVER -> ServerCombinedErrorGenerator(model, symbolProvider, operationSymbol, errors).render(this) - } - for (shape in model.structureShapes.filter { shape -> shape.hasTrait() }) { + requirements.renderOperationError(this, model, symbolProvider, operationSymbol, errors) + requirements.renderOperationError(this, model, symbolProvider, symbolProvider.toSymbol(unionShape), errors) + for (shape in errors) { StructureGenerator(model, symbolProvider, this, shape).render(codegenTarget) requirements.renderBuilderForShape(this, codegenContext, shape) } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/CombinedErrorGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGeneratorTest.kt similarity index 95% rename from codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/CombinedErrorGeneratorTest.kt rename to codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGeneratorTest.kt index 30838e82da48b18fa4a517f5de4406f0ce895c50..38b27ecf4f709ae218100acad2ff4e2f867ddf08 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/CombinedErrorGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGeneratorTest.kt @@ -17,7 +17,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.testSymbolProvider import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup -class CombinedErrorGeneratorTest { +class OperationErrorGeneratorTest { private val baseModel = """ namespace error @@ -55,7 +55,7 @@ class CombinedErrorGeneratorTest { model.lookup("error#$it").renderWithModelBuilder(model, symbolProvider, this) } val errors = listOf("FooException", "ComplexError", "InvalidGreeting").map { model.lookup("error#$it") } - val generator = CombinedErrorGenerator(model, symbolProvider, symbolProvider.toSymbol(model.lookup("error#Greeting")), errors) + val generator = OperationErrorGenerator(model, symbolProvider, symbolProvider.toSymbol(model.lookup("error#Greeting")), errors) generator.render(this) unitTest( diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/TopLevelErrorGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGeneratorTest.kt similarity index 83% rename from codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/TopLevelErrorGeneratorTest.kt rename to codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGeneratorTest.kt index a3d8fc364a2e40665a0a33ec443f1fe3401fbe4e..35552743276b9caef29c96f497260d8a83fe7ddd 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/TopLevelErrorGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGeneratorTest.kt @@ -8,6 +8,7 @@ package software.amazon.smithy.rust.codegen.core.smithy.generators.error import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.ShapeId +import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.Attribute import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext @@ -15,6 +16,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.CoreRustSettings import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator +import software.amazon.smithy.rust.codegen.core.smithy.transformers.operationErrors import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.generatePluginContext import software.amazon.smithy.rust.codegen.core.testutil.testSymbolProvider @@ -23,7 +25,7 @@ import kotlin.io.path.ExperimentalPathApi import kotlin.io.path.createDirectory import kotlin.io.path.writeText -internal class TopLevelErrorGeneratorTest { +internal class ServiceErrorGeneratorTest { @ExperimentalPathApi @Test fun `top level errors are send + sync`() { @@ -81,13 +83,23 @@ internal class TopLevelErrorGeneratorTest { Attribute.AllowDeprecated.copy(container = true).render(this) } rustCrate.withModule(RustModule.Error) { + for (operation in model.operationShapes) { + if (operation.id.namespace == "com.example") { + OperationErrorGenerator( + model, + symbolProvider, + symbolProvider.toSymbol(operation), + operation.operationErrors(model).map { it as StructureShape }, + ).render(this) + } + } for (shape in model.structureShapes) { if (shape.id.namespace == "com.example") { StructureGenerator(model, symbolProvider, this, shape).render(CodegenTarget.CLIENT) } } } - TopLevelErrorGenerator(codegenContext, model.operationShapes.toList()).render(rustCrate) + ServiceErrorGenerator(codegenContext, model.operationShapes.toList()).render(rustCrate) testDir.resolve("tests").createDirectory() testDir.resolve("tests/validate_errors.rs").writeText( diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerCombinedErrorGenerator.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerOperationErrorGenerator.kt similarity index 86% rename from codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerCombinedErrorGenerator.kt rename to codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerOperationErrorGenerator.kt index 42d6f07fcf4cb099f5f912d55cb0e8e35fa05ee1..65e53adb6c3cc1a1082a53a39f5b71589fdd61a5 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerCombinedErrorGenerator.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerOperationErrorGenerator.kt @@ -13,22 +13,21 @@ import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ServerCombinedErrorGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.error.errorSymbol import software.amazon.smithy.rust.codegen.server.python.smithy.PythonServerCargoDependency +import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerOperationErrorGenerator /** - * Generates a unified error enum for [operation]. It depends on [ServerCombinedErrorGenerator] + * Generates a unified error enum for [operation]. It depends on [ServerOperationErrorGenerator] * to generate the errors from the model and adds the Rust implementation `From`. */ -class PythonServerCombinedErrorGenerator( +class PythonServerOperationErrorGenerator( private val model: Model, private val symbolProvider: RustSymbolProvider, private val operation: OperationShape, -) : ServerCombinedErrorGenerator(model, symbolProvider, symbolProvider.toSymbol(operation), listOf()) { +) : ServerOperationErrorGenerator(model, symbolProvider, symbolProvider.toSymbol(operation), listOf()) { private val operationIndex = OperationIndex.of(model) private val errors = operationIndex.getErrors(operation) @@ -53,7 +52,7 @@ class PythonServerCombinedErrorGenerator( """, "pyo3" to PythonServerCargoDependency.PyO3.toType(), - "Error" to operation.errorSymbol(model, symbolProvider, CodegenTarget.SERVER), + "Error" to operation.errorSymbol(symbolProvider), "From" to RuntimeType.From, "CastPyErrToRustError" to castPyErrToRustError(), ) diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerServiceGenerator.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerServiceGenerator.kt index 30aa0bf0aa9462d471ddd9c09c1465ab1c31969c..61e331618060dc2b4cc11fc103b2a2adcf491512 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerServiceGenerator.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerServiceGenerator.kt @@ -30,7 +30,7 @@ class PythonServerServiceGenerator( ) : ServerServiceGenerator(rustCrate, protocolGenerator, protocolSupport, protocol, context) { override fun renderCombinedErrors(writer: RustWriter, operation: OperationShape) { - PythonServerCombinedErrorGenerator(context.model, context.symbolProvider, operation).render(writer) + PythonServerOperationErrorGenerator(context.model, context.symbolProvider, operation).render(writer) } override fun renderOperationHandler(writer: RustWriter, operations: List) { 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 74a79753a42618ceddc45f9fb53fe63a95b9caf8..dc35293bca928baa2ffcfad7f868981bb71b8ed4 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 @@ -16,6 +16,7 @@ import software.amazon.smithy.model.shapes.IntegerShape import software.amazon.smithy.model.shapes.ListShape import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape +import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.SetShape import software.amazon.smithy.model.shapes.Shape @@ -27,6 +28,7 @@ import software.amazon.smithy.model.shapes.UnionShape import software.amazon.smithy.model.traits.EnumTrait import software.amazon.smithy.model.traits.LengthTrait import software.amazon.smithy.model.transform.ModelTransformer +import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.ConstrainedModule @@ -37,13 +39,17 @@ import software.amazon.smithy.rust.codegen.core.smithy.SymbolVisitorConfig import software.amazon.smithy.rust.codegen.core.smithy.UnconstrainedModule import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator +import software.amazon.smithy.rust.codegen.core.smithy.generators.error.eventStreamErrorSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.implBlock import software.amazon.smithy.rust.codegen.core.smithy.protocols.ProtocolGeneratorFactory import software.amazon.smithy.rust.codegen.core.smithy.transformers.EventStreamNormalizer import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer import software.amazon.smithy.rust.codegen.core.smithy.transformers.RecursiveShapeBoxer +import software.amazon.smithy.rust.codegen.core.smithy.transformers.eventStreamErrors +import software.amazon.smithy.rust.codegen.core.smithy.transformers.operationErrors import software.amazon.smithy.rust.codegen.core.util.CommandFailed import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.rust.codegen.core.util.isEventStream import software.amazon.smithy.rust.codegen.core.util.runCommand import software.amazon.smithy.rust.codegen.server.smithy.customize.ServerCodegenDecorator import software.amazon.smithy.rust.codegen.server.smithy.generators.CollectionConstraintViolationGenerator @@ -59,6 +65,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.generators.PubCrateCons import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerBuilderGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerBuilderGeneratorWithoutPublicConstrainedTypes import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerEnumGenerator +import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerOperationErrorGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerServiceGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerStructureConstrainedTraitImpl import software.amazon.smithy.rust.codegen.server.smithy.generators.UnconstrainedCollectionGenerator @@ -475,6 +482,17 @@ open class ServerCodegenVisitor( } } } + + if (shape.isEventStream()) { + rustCrate.withModule(RustModule.Error) { + val symbol = codegenContext.symbolProvider.toSymbol(shape) + val errors = shape.eventStreamErrors() + .map { model.expectShape(it.asMemberShape().get().target, StructureShape::class.java) } + val errorSymbol = shape.eventStreamErrorSymbol(codegenContext.symbolProvider) + ServerOperationErrorGenerator(model, codegenContext.symbolProvider, symbol, errors) + .renderErrors(this, errorSymbol, symbol) + } + } } /** @@ -497,4 +515,19 @@ open class ServerCodegenVisitor( ) .render() } + + /** + * Generate errors for operation shapes + */ + override fun operationShape(shape: OperationShape) { + rustCrate.withModule(RustModule.Error) { + val symbol = codegenContext.symbolProvider.toSymbol(shape) + ServerOperationErrorGenerator( + model, + codegenContext.symbolProvider, + symbol, + shape.operationErrors(model).map { it.asStructureShape().get() }, + ).render(this) + } + } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/DocHandlerGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/DocHandlerGenerator.kt index 80fecc16c56a83ac06898df1cfe055eb673f8eff..759f88708837ff3086f7bd39b60509e71aca8a6a 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/DocHandlerGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/DocHandlerGenerator.kt @@ -12,7 +12,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.ErrorsModule import software.amazon.smithy.rust.codegen.core.smithy.InputsModule import software.amazon.smithy.rust.codegen.core.smithy.OutputsModule @@ -34,7 +33,7 @@ class DocHandlerGenerator( private val inputSymbol = symbolProvider.toSymbol(operation.inputShape(model)) private val outputSymbol = symbolProvider.toSymbol(operation.outputShape(model)) - private val errorSymbol = operation.errorSymbol(model, symbolProvider, CodegenTarget.SERVER) + private val errorSymbol = operation.errorSymbol(symbolProvider) /** * Returns the function signature for an operation handler implementation. Used in the documentation. diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServerCombinedErrorGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGenerator.kt similarity index 97% rename from codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServerCombinedErrorGenerator.kt rename to codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGenerator.kt index 6ce5bc8c9381c8b238ab022081f56acf21174437..0d2a982903f79ee11ca35b83ce07e1c92a97ed0f 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServerCombinedErrorGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGenerator.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package software.amazon.smithy.rust.codegen.core.smithy.generators.error +package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model @@ -25,7 +25,7 @@ import software.amazon.smithy.rust.codegen.core.util.toSnakeCase * Generates a unified error enum for [operation]. [ErrorGenerator] handles generating the individual variants, * but we must still combine those variants into an enum covering all possible errors for a given operation. */ -open class ServerCombinedErrorGenerator( +open class ServerOperationErrorGenerator( private val model: Model, private val symbolProvider: RustSymbolProvider, private val operationSymbol: Symbol, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt index 9d757310dd0f40afd2a525155c2b2ce847e10a12..4589de74a5fb084c7e80f6358d8b059bf4695b52 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationGenerator.kt @@ -37,7 +37,7 @@ class ServerOperationGenerator( if (operation.errors.isEmpty()) { rust("std::convert::Infallible") } else { - // Name comes from [ServerCombinedErrorGenerator]. + // Name comes from [ServerOperationErrorGenerator]. rust("crate::error::${symbolProvider.toSymbol(operation).name}Error") } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationHandlerGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationHandlerGenerator.kt index f86a2f2289b94577a90825aed59cbe90f625d365..308f2f047088014d2d08efcf2d0c3bfd105c9407 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationHandlerGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationHandlerGenerator.kt @@ -10,7 +10,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.generators.error.errorSymbol import software.amazon.smithy.rust.codegen.core.smithy.transformers.operationErrors @@ -135,7 +134,7 @@ open class ServerOperationHandlerGenerator( "Fun: FnOnce($inputName) -> Fut + Clone + Send + 'static," } val outputType = if (operation.operationErrors(model).isNotEmpty()) { - "Result<${symbolProvider.toSymbol(operation.outputShape(model)).fullName}, ${operation.errorSymbol(model, symbolProvider, CodegenTarget.SERVER).fullyQualifiedName()}>" + "Result<${symbolProvider.toSymbol(operation.outputShape(model)).fullName}, ${operation.errorSymbol(symbolProvider).fullyQualifiedName()}>" } else { symbolProvider.toSymbol(operation.outputShape(model)).fullName } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationRegistryGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationRegistryGenerator.kt index 494d137e7dabec190e2c74783a60fc025244fda8..fe7905914dfecc13676440478f8f53cb2ad9bbd4 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationRegistryGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationRegistryGenerator.kt @@ -21,7 +21,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.withBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.ErrorsModule import software.amazon.smithy.rust.codegen.core.smithy.InputsModule import software.amazon.smithy.rust.codegen.core.smithy.OutputsModule @@ -379,7 +378,7 @@ ${operationImplementationStubs(operations)} private fun OperationShape.signature(): String { val inputSymbol = symbolProvider.toSymbol(inputShape(model)) val outputSymbol = symbolProvider.toSymbol(outputShape(model)) - val errorSymbol = errorSymbol(model, symbolProvider, CodegenTarget.SERVER) + val errorSymbol = errorSymbol(symbolProvider) // using module names here to avoid generating `crate::...` since we've already added the import val inputT = "${InputsModule.name}::${inputSymbol.name}" diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt index c466a04797944f33b5c33ae6c0de4c77fa7acee4..c3713fc9a125682187e67367186976c7bd89c02e 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt @@ -40,7 +40,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.withBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationCustomization import software.amazon.smithy.rust.codegen.core.smithy.generators.TypeConversionGenerator @@ -259,7 +258,7 @@ private class ServerHttpBoundProtocolTraitImplGenerator( // Implement `into_response` for output types. val outputName = "${operationName}${ServerHttpBoundProtocolGenerator.OPERATION_OUTPUT_WRAPPER_SUFFIX}" - val errorSymbol = operationShape.errorSymbol(model, symbolProvider, CodegenTarget.SERVER) + val errorSymbol = operationShape.errorSymbol(symbolProvider) if (operationShape.operationErrors(model).isNotEmpty()) { // The output of fallible operations is a `Result` which we convert into an @@ -466,7 +465,7 @@ private class ServerHttpBoundProtocolTraitImplGenerator( private fun serverSerializeError(operationShape: OperationShape): RuntimeType { val fnName = "serialize_${operationShape.id.name.toSnakeCase()}_error" - val errorSymbol = operationShape.errorSymbol(model, symbolProvider, CodegenTarget.SERVER) + val errorSymbol = operationShape.errorSymbol(symbolProvider) return RuntimeType.forInlineFun(fnName, operationSerModule) { Attribute.Custom("allow(clippy::unnecessary_wraps)").render(this) rustBlockTemplate( diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerCombinedErrorGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt similarity index 95% rename from codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerCombinedErrorGeneratorTest.kt rename to codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt index 74658c3a674793feaa9a610dfaaea548ae642b08..32f565feba17e0b95ea6a5532c3381f7fe6a515e 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerCombinedErrorGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt @@ -8,7 +8,6 @@ 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.core.smithy.ErrorsModule -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ServerCombinedErrorGenerator import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel @@ -18,7 +17,7 @@ import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider -class ServerCombinedErrorGeneratorTest { +class ServerOperationErrorGeneratorTest { private val baseModel = """ namespace error @@ -57,7 +56,7 @@ class ServerCombinedErrorGeneratorTest { model.lookup("error#$it").serverRenderWithModelBuilder(model, symbolProvider, this) } val errors = listOf("FooException", "ComplexError", "InvalidGreeting").map { model.lookup("error#$it") } - ServerCombinedErrorGenerator( + ServerOperationErrorGenerator( model, symbolProvider, symbolProvider.toSymbol(model.lookup("error#Greeting")), diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt index 1e2cdef43f2eb66b868ab9367c8c9d8e897f9036..e3ff924db85a815a67e77f9852083eab1c39b787 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamBaseRequirements.kt @@ -8,12 +8,14 @@ package software.amazon.smithy.rust.codegen.server.smithy.protocols.eventstream import org.junit.jupiter.api.extension.ExtensionContext import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.ArgumentsProvider +import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget +import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.generators.implBlock import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestModels import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestRequirements @@ -21,6 +23,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenConfig import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerBuilderGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerBuilderGeneratorWithoutPublicConstrainedTypes +import software.amazon.smithy.rust.codegen.server.smithy.generators.ServerOperationErrorGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestRustSettings import java.util.stream.Stream @@ -80,4 +83,14 @@ abstract class ServerEventStreamBaseRequirements : EventStreamTestRequirements, + ) { + ServerOperationErrorGenerator(model, symbolProvider, operationSymbol, errors).render(writer) + } }