diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt index f8a50a7723..d16bcce33a 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt @@ -75,7 +75,7 @@ private class AwsClientGenerics(private val types: Types) : FluentClientGenerics override fun sendBounds( operation: Symbol, operationOutput: Symbol, - operationError: RuntimeType, + operationError: Symbol, retryClassifier: RuntimeType, ): Writable = writable { } 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 c733138076..be12bf8e98 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 @@ -35,7 +35,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig 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.customize.OperationSection -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.errorSymbol import software.amazon.smithy.rust.codegen.core.smithy.protocols.HttpBoundProtocolPayloadGenerator import software.amazon.smithy.rust.codegen.core.util.cloneOperation import software.amazon.smithy.rust.codegen.core.util.expectTrait @@ -155,7 +154,7 @@ class AwsInputPresignedMethod( } private fun RustWriter.writeInputPresignedMethod(section: OperationSection.InputImpl) { - val operationError = operationShape.errorSymbol(symbolProvider) + val operationError = symbolProvider.symbolForOperationError(operationShape) val presignableOp = PRESIGNABLE_OPERATIONS.getValue(operationShape.id) val makeOperationOp = if (presignableOp.hasModelTransforms()) { diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/SdkConfigDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/SdkConfigDecorator.kt index f0e2a7e7d6..1d94cd6082 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/SdkConfigDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/SdkConfigDecorator.kt @@ -6,10 +6,10 @@ package software.amazon.smithy.rustsdk import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigCustomization import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfig -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule 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 @@ -105,7 +105,7 @@ class SdkConfigDecorator : ClientCodegenDecorator { val codegenScope = arrayOf( "SdkConfig" to AwsRuntimeType.awsTypes(codegenContext.runtimeConfig).resolve("sdk_config::SdkConfig"), ) - rustCrate.withModule(RustModule.Config) { + rustCrate.withModule(ClientRustModule.Config) { rustTemplate( """ impl From<&#{SdkConfig}> for Builder { 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 1816240ef9..3694cc992d 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 @@ -24,7 +24,6 @@ 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.DirectedWalker import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider @@ -33,15 +32,12 @@ import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerat 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.hasTrait import software.amazon.smithy.rust.codegen.core.util.isEventStream @@ -56,7 +52,6 @@ class ClientCodegenVisitor( context: PluginContext, private val codegenDecorator: ClientCodegenDecorator, ) : ShapeVisitor.Default() { - private val logger = Logger.getLogger(javaClass.name) private val settings = ClientRustSettings.from(context.model, context.settings) @@ -69,12 +64,12 @@ class ClientCodegenVisitor( private val protocolGenerator: ClientProtocolGenerator init { - val symbolVisitorConfig = - SymbolVisitorConfig( - runtimeConfig = settings.runtimeConfig, - renameExceptions = settings.codegenConfig.renameExceptions, - nullabilityCheckMode = NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1, - ) + val symbolVisitorConfig = SymbolVisitorConfig( + runtimeConfig = settings.runtimeConfig, + renameExceptions = settings.codegenConfig.renameExceptions, + nullabilityCheckMode = NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1, + moduleProvider = ClientModuleProvider, + ) val baseModel = baselineTransform(context.model) val untransformedService = settings.getService(baseModel) val (protocol, generator) = ClientProtocolLoader( @@ -224,13 +219,8 @@ class ClientCodegenVisitor( 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) + rustCrate.withModule(ClientRustModule.Error) { + OperationErrorGenerator(model, symbolProvider, shape).render(this) } } } @@ -239,14 +229,8 @@ class ClientCodegenVisitor( * 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) + rustCrate.withModule(ClientRustModule.Error) { + OperationErrorGenerator(model, symbolProvider, shape).render(this) } } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt new file mode 100644 index 0000000000..53fe9c6921 --- /dev/null +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt @@ -0,0 +1,59 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.client.smithy + +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.shapes.StructureShape +import software.amazon.smithy.model.shapes.UnionShape +import software.amazon.smithy.model.traits.ErrorTrait +import software.amazon.smithy.rust.codegen.core.rustlang.RustModule +import software.amazon.smithy.rust.codegen.core.smithy.ModuleProvider +import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait +import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticOutputTrait +import software.amazon.smithy.rust.codegen.core.util.hasTrait + +/** + * Modules for code generated client crates. + */ +object ClientRustModule { + /** crate::client */ + val client = Client.self + object Client { + /** crate::client */ + val self = RustModule.public("client", "Client and fluent builders for calling the service.") + + /** crate::client::customize */ + val customize = RustModule.public("customize", "Operation customization and supporting types", parent = self) + } + + val Config = RustModule.public("config", documentation = "Configuration for the service.") + val Error = RustModule.public("error", documentation = "All error types that operations can return. Documentation on these types is copied from the model.") + val Operation = RustModule.public("operation", documentation = "All operations that this crate can perform.") + val Model = RustModule.public("model", documentation = "Data structures used by operation inputs/outputs. Documentation on these types is copied from the model.") + val Input = RustModule.public("input", documentation = "Input structures for operations. Documentation on these types is copied from the model.") + val Output = RustModule.public("output", documentation = "Output structures for operations. Documentation on these types is copied from the model.") + val Types = RustModule.public("types", documentation = "Data primitives referenced by other data types.") +} + +object ClientModuleProvider : ModuleProvider { + override fun moduleForShape(shape: Shape): RustModule.LeafModule = when (shape) { + is OperationShape -> ClientRustModule.Operation + is StructureShape -> when { + shape.hasTrait() -> ClientRustModule.Error + shape.hasTrait() -> ClientRustModule.Input + shape.hasTrait() -> ClientRustModule.Output + else -> ClientRustModule.Model + } + else -> ClientRustModule.Model + } + + override fun moduleForOperationError(operation: OperationShape): RustModule.LeafModule = + ClientRustModule.Error + + override fun moduleForEventStreamError(eventStream: UnionShape): RustModule.LeafModule = + ClientRustModule.Error +} diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt index 84a6d5f38a..a52c4a81d6 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt @@ -5,9 +5,9 @@ package software.amazon.smithy.rust.codegen.client.smithy.customizations +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigCustomization import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfig -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule 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 @@ -235,7 +235,7 @@ class ResiliencyConfigCustomization(codegenContext: CodegenContext) : ConfigCust class ResiliencyReExportCustomization(private val runtimeConfig: RuntimeConfig) { fun extras(rustCrate: RustCrate) { - rustCrate.withModule(RustModule.Config) { + rustCrate.withModule(ClientRustModule.Config) { rustTemplate( """ pub use #{sleep}::{AsyncSleep, Sleep}; diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customize/RequiredCustomizations.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customize/RequiredCustomizations.kt index f65e042d44..0f51ba4d58 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customize/RequiredCustomizations.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customize/RequiredCustomizations.kt @@ -7,6 +7,7 @@ package software.amazon.smithy.rust.codegen.client.smithy.customize import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule import software.amazon.smithy.rust.codegen.client.smithy.customizations.EndpointPrefixGenerator import software.amazon.smithy.rust.codegen.client.smithy.customizations.HttpChecksumRequiredGenerator import software.amazon.smithy.rust.codegen.client.smithy.customizations.HttpVersionListCustomization @@ -65,6 +66,8 @@ class RequiredCustomizations : ClientCodegenDecorator { // Re-export resiliency types ResiliencyReExportCustomization(codegenContext.runtimeConfig).extras(rustCrate) - pubUseSmithyTypes(codegenContext.runtimeConfig, codegenContext.model, rustCrate) + rustCrate.withModule(ClientRustModule.Types) { + pubUseSmithyTypes(codegenContext.runtimeConfig, codegenContext.model)(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 54982643e8..cbde592f02 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 @@ -24,7 +24,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext 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 -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.errorSymbol import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.util.PANIC import software.amazon.smithy.rust.codegen.core.util.findMemberWithTrait @@ -79,7 +78,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(symbolProvider) + private val errorType = symbolProvider.symbolForOperationError(operation) 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 6710ac9c3d..2a9adeac90 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 @@ -7,12 +7,12 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators import software.amazon.smithy.model.knowledge.TopDownIndex import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfigGenerator import software.amazon.smithy.rust.codegen.client.smithy.generators.protocol.ClientProtocolGenerator import software.amazon.smithy.rust.codegen.client.smithy.generators.protocol.ProtocolTestGenerator 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.ServiceErrorGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolSupport @@ -58,7 +58,7 @@ class ServiceGenerator( ServiceErrorGenerator(clientCodegenContext, operations).render(rustCrate) - rustCrate.withModule(RustModule.Config) { + rustCrate.withModule(ClientRustModule.Config) { ServiceConfigGenerator.withBaseBehavior( clientCodegenContext, extraCustomizations = decorator.configCustomizations(clientCodegenContext, listOf()), diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDecorator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDecorator.kt index b6fced279f..475c9c490a 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDecorator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDecorator.kt @@ -5,6 +5,7 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.client +import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext @@ -65,7 +66,7 @@ sealed class FluentClientSection(name: String) : Section(name) { /** Write custom code into an operation fluent builder's impl block */ data class FluentBuilderImpl( val operationShape: OperationShape, - val operationErrorType: RuntimeType, + val operationErrorType: Symbol, ) : FluentClientSection("FluentBuilderImpl") /** Write custom code into the docs */ 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 d5b8ebd941..75a2d3bd8c 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 @@ -44,7 +44,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizations import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.errorSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.util.inputShape @@ -168,7 +167,7 @@ class FluentClientGenerator( val output = operation.outputShape(model) val operationOk = symbolProvider.toSymbol(output) - val operationErr = operation.errorSymbol(symbolProvider).toSymbol() + val operationErr = symbolProvider.symbolForOperationError(operation) val inputFieldsBody = generateOperationShapeDocs(writer, symbolProvider, operation, model).joinToString("\n") { @@ -263,7 +262,7 @@ class FluentClientGenerator( "bounds" to generics.bounds, ) { val outputType = symbolProvider.toSymbol(operation.outputShape(model)) - val errorType = operation.errorSymbol(symbolProvider) + val errorType = symbolProvider.symbolForOperationError(operation) // Have to use fully-qualified result here or else it could conflict with an op named Result rustTemplate( @@ -333,7 +332,7 @@ class FluentClientGenerator( customizations, FluentClientSection.FluentBuilderImpl( operation, - operation.errorSymbol(symbolProvider), + symbolProvider.symbolForOperationError(operation), ), ) input.members().forEach { member -> diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerics.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerics.kt index b3229051e6..399085d5e5 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerics.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerics.kt @@ -28,7 +28,7 @@ interface FluentClientGenerics { val bounds: Writable /** Bounds for generated `send()` functions */ - fun sendBounds(operation: Symbol, operationOutput: Symbol, operationError: RuntimeType, retryClassifier: RuntimeType): Writable + fun sendBounds(operation: Symbol, operationOutput: Symbol, operationError: Symbol, retryClassifier: RuntimeType): Writable /** Convert this `FluentClientGenerics` into the more general `RustGenerics` */ fun toRustGenerics(): RustGenerics @@ -70,7 +70,7 @@ data class FlexibleClientGenerics( } /** Bounds for generated `send()` functions */ - override fun sendBounds(operation: Symbol, operationOutput: Symbol, operationError: RuntimeType, retryClassifier: RuntimeType): Writable = writable { + override fun sendBounds(operation: Symbol, operationOutput: Symbol, operationError: Symbol, retryClassifier: RuntimeType): Writable = writable { rustTemplate( """ where diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/ResponseBindingGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/ResponseBindingGenerator.kt index 7becd9df01..210715c3eb 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/ResponseBindingGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/ResponseBindingGenerator.kt @@ -34,11 +34,7 @@ class ResponseBindingGenerator( fun generateDeserializePayloadFn( binding: HttpBindingDescriptor, - errorT: RuntimeType, + errorSymbol: Symbol, payloadParser: RustWriter.(String) -> Unit, - ): RuntimeType = httpBindingGenerator.generateDeserializePayloadFn( - binding, - errorT, - payloadParser, - ) + ): RuntimeType = httpBindingGenerator.generateDeserializePayloadFn(binding, errorSymbol, payloadParser) } 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 3cc82af7a0..c1db56fa4c 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 @@ -32,7 +32,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.writable 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.generators.protocol.ProtocolSupport import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.getTrait @@ -290,7 +289,7 @@ class ProtocolTestGenerator( "parse_http_response" to RuntimeType.parseHttpResponse(codegenContext.runtimeConfig), ) if (expectedShape.hasTrait()) { - val errorSymbol = operationShape.errorSymbol(codegenContext.symbolProvider) + val errorSymbol = codegenContext.symbolProvider.symbolForOperationError(operationShape) 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 0592d91cd9..f1cc486575 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 @@ -30,7 +30,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationSectio import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizations import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.errorSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolTraitImplGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName import software.amazon.smithy.rust.codegen.core.smithy.protocols.HttpBindingDescriptor @@ -125,7 +124,7 @@ class HttpBoundProtocolTraitImplGenerator( }""", *codegenScope, "O" to outputSymbol, - "E" to operationShape.errorSymbol(symbolProvider), + "E" to symbolProvider.symbolForOperationError(operationShape), "parse_error" to parseError(operationShape), "parse_response" to parseResponse(operationShape, customizations), ) @@ -156,7 +155,7 @@ class HttpBoundProtocolTraitImplGenerator( } """, "O" to outputSymbol, - "E" to operationShape.errorSymbol(symbolProvider), + "E" to symbolProvider.symbolForOperationError(operationShape), "parse_streaming_response" to parseStreamingResponse(operationShape, customizations), "parse_error" to parseError(operationShape), *codegenScope, @@ -167,7 +166,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(symbolProvider) + val errorSymbol = symbolProvider.symbolForOperationError(operationShape) return RuntimeType.forInlineFun(fnName, operationDeserModule) { Attribute.AllowClippyUnnecessaryWraps.render(this) rustBlockTemplate( @@ -241,7 +240,7 @@ class HttpBoundProtocolTraitImplGenerator( val fnName = "parse_${operationShape.id.name.toSnakeCase()}" val outputShape = operationShape.outputShape(model) val outputSymbol = symbolProvider.toSymbol(outputShape) - val errorSymbol = operationShape.errorSymbol(symbolProvider) + val errorSymbol = symbolProvider.symbolForOperationError(operationShape) return RuntimeType.forInlineFun(fnName, operationDeserModule) { Attribute.AllowClippyUnnecessaryWraps.render(this) rustBlockTemplate( @@ -270,7 +269,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(symbolProvider) + val errorSymbol = symbolProvider.symbolForOperationError(operationShape) return RuntimeType.forInlineFun(fnName, operationDeserModule) { Attribute.AllowClippyUnnecessaryWraps.render(this) rustBlockTemplate( @@ -296,7 +295,7 @@ class HttpBoundProtocolTraitImplGenerator( operationShape: OperationShape, outputShape: StructureShape, bindings: List, - errorSymbol: RuntimeType, + errorSymbol: Symbol, customizations: List, ) { val httpBindingGenerator = ResponseBindingGenerator(protocol, codegenContext, operationShape) @@ -352,7 +351,7 @@ class HttpBoundProtocolTraitImplGenerator( httpBindingGenerator: ResponseBindingGenerator, structuredDataParser: StructuredDataParserGenerator, ): Writable? { - val errorSymbol = operationShape.errorSymbol(symbolProvider) + val errorSymbol = symbolProvider.symbolForOperationError(operationShape) val member = binding.member return when (binding.location) { HttpLocation.HEADER -> writable { diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestConfigCustomization.kt index da2362a195..cb06688225 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestConfigCustomization.kt @@ -5,10 +5,10 @@ package software.amazon.smithy.rust.codegen.client.testutil +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigCustomization import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfig import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfigGenerator -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule 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.writable @@ -74,7 +74,7 @@ fun validateConfigCustomizations( fun stubConfigProject(customization: ConfigCustomization, project: TestWriterDelegator): TestWriterDelegator { val customizations = listOf(stubConfigCustomization("a")) + customization + stubConfigCustomization("b") val generator = ServiceConfigGenerator(customizations = customizations.toList()) - project.withModule(RustModule.Config) { + project.withModule(ClientRustModule.Config) { generator.render(this) unitTest( "config_send_sync", 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 1b3f813959..d82e7b93c4 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,10 +6,12 @@ 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.node.ObjectNode import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenConfig +import software.amazon.smithy.rust.codegen.client.smithy.ClientModuleProvider import software.amazon.smithy.rust.codegen.client.smithy.ClientRustSettings import software.amazon.smithy.rust.codegen.client.smithy.RustClientCodegenPlugin import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext @@ -17,8 +19,8 @@ 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.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider +import software.amazon.smithy.rust.codegen.core.smithy.SymbolVisitorConfig import software.amazon.smithy.rust.codegen.core.testutil.TestRuntimeConfig -import software.amazon.smithy.rust.codegen.core.testutil.TestSymbolVisitorConfig import software.amazon.smithy.rust.codegen.core.testutil.testRustSettings fun clientTestRustSettings( @@ -47,11 +49,18 @@ fun clientTestRustSettings( customizationConfig, ) +val ClientTestSymbolVisitorConfig = SymbolVisitorConfig( + runtimeConfig = TestRuntimeConfig, + renameExceptions = true, + nullabilityCheckMode = NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1, + moduleProvider = ClientModuleProvider, +) + fun testSymbolProvider(model: Model, serviceShape: ServiceShape? = null): RustSymbolProvider = RustClientCodegenPlugin.baseSymbolProvider( model, serviceShape ?: ServiceShape.builder().version("test").id("test#Service").build(), - TestSymbolVisitorConfig, + ClientTestSymbolVisitorConfig, ) fun testCodegenContext( diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/EventStreamSymbolProviderTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/EventStreamSymbolProviderTest.kt index 5fb38e58e3..c7dd8efc70 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/EventStreamSymbolProviderTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/EventStreamSymbolProviderTest.kt @@ -10,6 +10,7 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.ShapeId +import software.amazon.smithy.rust.codegen.client.testutil.ClientTestSymbolVisitorConfig import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.EventStreamSymbolProvider @@ -17,7 +18,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.SymbolVisitor import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer import software.amazon.smithy.rust.codegen.core.testutil.TestRuntimeConfig -import software.amazon.smithy.rust.codegen.core.testutil.TestSymbolVisitorConfig import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel class EventStreamSymbolProviderTest { @@ -46,7 +46,7 @@ class EventStreamSymbolProviderTest { ) val service = model.expectShape(ShapeId.from("test#TestService")) as ServiceShape - val provider = EventStreamSymbolProvider(TestRuntimeConfig, SymbolVisitor(model, service, TestSymbolVisitorConfig), model, CodegenTarget.CLIENT) + val provider = EventStreamSymbolProvider(TestRuntimeConfig, SymbolVisitor(model, service, ClientTestSymbolVisitorConfig), model, CodegenTarget.CLIENT) // Look up the synthetic input/output rather than the original input/output val inputStream = model.expectShape(ShapeId.from("test.synthetic#TestOperationInput\$inputStream")) as MemberShape @@ -82,7 +82,7 @@ class EventStreamSymbolProviderTest { ) val service = model.expectShape(ShapeId.from("test#TestService")) as ServiceShape - val provider = EventStreamSymbolProvider(TestRuntimeConfig, SymbolVisitor(model, service, TestSymbolVisitorConfig), model, CodegenTarget.CLIENT) + val provider = EventStreamSymbolProvider(TestRuntimeConfig, SymbolVisitor(model, service, ClientTestSymbolVisitorConfig), model, CodegenTarget.CLIENT) // Look up the synthetic input/output rather than the original input/output val inputStream = model.expectShape(ShapeId.from("test.synthetic#TestOperationInput\$inputStream")) as MemberShape diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/SymbolVisitorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/SymbolVisitorTest.kt index bc26847bef..f1dc61e337 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/SymbolVisitorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/SymbolVisitorTest.kt @@ -29,9 +29,6 @@ import software.amazon.smithy.model.traits.SparseTrait import software.amazon.smithy.rust.codegen.client.testutil.testSymbolProvider import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.render -import software.amazon.smithy.rust.codegen.core.smithy.ErrorsModule -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule -import software.amazon.smithy.rust.codegen.core.smithy.OperationsModule import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel @@ -57,7 +54,7 @@ class SymbolVisitorTest { val provider: SymbolProvider = testSymbolProvider(model) val sym = provider.toSymbol(struct) sym.rustType().render(false) shouldBe "MyStruct" - sym.definitionFile shouldContain ModelsModule.definitionFile() + sym.definitionFile shouldContain ClientRustModule.Model.definitionFile() sym.namespace shouldBe "crate::model" } @@ -77,7 +74,7 @@ class SymbolVisitorTest { val provider: SymbolProvider = testSymbolProvider(model) val sym = provider.toSymbol(struct) sym.rustType().render(false) shouldBe "TerribleError" - sym.definitionFile shouldContain ErrorsModule.definitionFile() + sym.definitionFile shouldContain ClientRustModule.Error.definitionFile() } @Test @@ -101,7 +98,7 @@ class SymbolVisitorTest { val provider: SymbolProvider = testSymbolProvider(model) val sym = provider.toSymbol(shape) sym.rustType().render(false) shouldBe "StandardUnit" - sym.definitionFile shouldContain ModelsModule.definitionFile() + sym.definitionFile shouldContain ClientRustModule.Model.definitionFile() sym.namespace shouldBe "crate::model" } @@ -260,7 +257,7 @@ class SymbolVisitorTest { } """.asSmithyModel() val symbol = testSymbolProvider(model).toSymbol(model.expectShape(ShapeId.from("smithy.example#PutObject"))) - symbol.definitionFile shouldBe(OperationsModule.definitionFile()) + symbol.definitionFile shouldBe ClientRustModule.Operation.definitionFile() symbol.name shouldBe "PutObject" } } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGeneratorTest.kt index c366fbe5ee..5ff6215beb 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientEnumGeneratorTest.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.rust.codegen.client.testutil.testCodegenContext -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel @@ -24,7 +23,7 @@ class ClientEnumGeneratorTest { val shape = model.lookup(shapeId) val context = testCodegenContext(model) val project = TestWorkspace.testProject(context.symbolProvider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { ClientEnumGenerator(context, shape).render(this) unitTest( "matching_on_enum_should_be_forward_compatible", @@ -81,7 +80,7 @@ class ClientEnumGeneratorTest { val shape = model.lookup("test#SomeEnum") val context = testCodegenContext(model) val project = TestWorkspace.testProject(context.symbolProvider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { ClientEnumGenerator(context, shape).render(this) unitTest( "impl_debug_for_non_sensitive_enum_should_implement_the_derived_debug_trait", @@ -113,7 +112,7 @@ class ClientEnumGeneratorTest { val shape = model.lookup("test#SomeEnum") val context = testCodegenContext(model) val project = TestWorkspace.testProject(context.symbolProvider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { ClientEnumGenerator(context, shape).render(this) unitTest( "it_escapes_the_unknown_variant_if_the_enum_has_an_unknown_value_in_the_model", @@ -141,7 +140,7 @@ class ClientEnumGeneratorTest { val shape = model.lookup("test#InstanceType") val context = testCodegenContext(model) val project = TestWorkspace.testProject(context.symbolProvider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { rust("##![allow(deprecated)]") ClientEnumGenerator(context, shape).render(this) unitTest( diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientInstantiatorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientInstantiatorTest.kt index 39b0041aa2..827a8c0204 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientInstantiatorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientInstantiatorTest.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.node.Node import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.rust.codegen.client.testutil.testCodegenContext -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace @@ -51,8 +50,8 @@ internal class ClientInstantiatorTest { val sut = clientInstantiator(codegenContext) val data = Node.parse("t2.nano".dq()) - val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + val project = TestWorkspace.testProject(symbolProvider) + project.moduleFor(shape) { ClientEnumGenerator(codegenContext, shape).render(this) unitTest("generate_named_enums") { withBlock("let result = ", ";") { @@ -70,8 +69,8 @@ internal class ClientInstantiatorTest { val sut = clientInstantiator(codegenContext) val data = Node.parse("t2.nano".dq()) - val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + val project = TestWorkspace.testProject(symbolProvider) + project.moduleFor(shape) { ClientEnumGenerator(codegenContext, shape).render(this) unitTest("generate_unnamed_enums") { withBlock("let result = ", ";") { diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt index 366ff370dc..7273428183 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt @@ -8,8 +8,8 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.config import io.kotest.matchers.shouldBe import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.ServiceShape +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule import software.amazon.smithy.rust.codegen.client.testutil.testSymbolProvider -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule 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.writable @@ -102,7 +102,7 @@ internal class ServiceConfigGeneratorTest { val sut = ServiceConfigGenerator(listOf(ServiceCustomizer())) val symbolProvider = testSymbolProvider("namespace empty".asSmithyModel()) val project = TestWorkspace.testProject(symbolProvider) - project.withModule(RustModule.Config) { + project.withModule(ClientRustModule.Config) { sut.render(this) unitTest( "set_config_fields", 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 1da709422d..b29e23bc53 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 @@ -21,7 +21,6 @@ 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.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationCustomization -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.errorSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolPayloadGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolSupport import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolTraitImplGenerator @@ -65,7 +64,7 @@ private class TestProtocolTraitImplGenerator( }""", "parse_strict" to RuntimeType.parseStrictResponse(codegenContext.runtimeConfig), "Output" to symbolProvider.toSymbol(operationShape.outputShape(codegenContext.model)), - "Error" to operationShape.errorSymbol(symbolProvider), + "Error" to symbolProvider.symbolForOperationError(operationShape), "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 1717dab2d6..8d07242211 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,9 +8,9 @@ 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.Shape import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext @@ -64,9 +64,8 @@ abstract class ClientEventStreamBaseRequirements : EventStreamTestRequirements, + operationOrEventStream: Shape, ) { - OperationErrorGenerator(model, symbolProvider, operationSymbol, errors).render(writer) + OperationErrorGenerator(model, symbolProvider, operationOrEventStream).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 573fa242f0..d98102d80b 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 @@ -99,24 +99,10 @@ sealed class RustModule { parent = parent, ).cfgTest() - /* Common modules used across client, server and tests */ - val Config = public("config", documentation = "Configuration for the service.") - val Error = public( - "error", - documentation = "All error types that operations can return. Documentation on these types is copied from the model.", - ) - val Model = public( - "model", - documentation = "Data structures used by operation inputs/outputs. Documentation on these types is copied from the model.", - ) - val Input = public( - "input", - documentation = "Input structures for operations. Documentation on these types is copied from the model.", - ) - val Output = public( - "output", - documentation = "Output structures for operations. Documentation on these types is copied from the model.", - ) + // TODO(https://github.com/awslabs/smithy-rs/pull/2129): Remove once #2129 merges + val Error = public("error", documentation = "All error types that operations can return. Documentation on these types is copied from the model.") + + // TODO(https://github.com/awslabs/smithy-rs/pull/2334): Remove once #2334 merges val Types = public("types", documentation = "Data primitives referenced by other data types.") /** diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CodegenDelegator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CodegenDelegator.kt index ccb3005d69..167a16f917 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CodegenDelegator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CodegenDelegator.kt @@ -162,6 +162,12 @@ open class RustCrate( return this } + /** + * Returns the module for a given Shape. + */ + fun moduleFor(shape: Shape, moduleWriter: Writable): RustCrate = + withModule((symbolProvider as RustSymbolProvider).moduleForShape(shape), moduleWriter) + /** * Create a new file directly */ @@ -172,24 +178,7 @@ open class RustCrate( } } -val ErrorsModule = RustModule.public( - "error", - documentation = "All error types that operations can return. Documentation on these types is copied from the model.", -) -val OperationsModule = RustModule.public("operation", documentation = "All operations that this crate can perform.") -val ModelsModule = RustModule.public( - "model", - documentation = "Data structures used by operation inputs/outputs. Documentation on these types is copied from the model.", -) -val InputsModule = RustModule.public( - "input", - documentation = "Input structures for operations. Documentation on these types is copied from the model.", -) -val OutputsModule = RustModule.public( - "output", - documentation = "Output structures for operations. Documentation on these types is copied from the model.", -) - +// TODO(https://github.com/awslabs/smithy-rs/issues/2341): Remove unconstrained/constrained from codegen-core val UnconstrainedModule = RustModule.private("unconstrained", "Unconstrained types for constrained shapes.") val ConstrainedModule = 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 1aff86f7d4..d1c3afd9f4 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 @@ -14,7 +14,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.render import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.eventStreamErrorSymbol import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticOutputTrait import software.amazon.smithy.rust.codegen.core.smithy.transformers.eventStreamErrors @@ -49,7 +48,7 @@ class EventStreamSymbolProvider( val error = if (target == CodegenTarget.SERVER && unionShape.eventStreamErrors().isEmpty()) { RuntimeType.smithyHttp(runtimeConfig).resolve("event_stream::MessageStreamError").toSymbol() } else { - unionShape.eventStreamErrorSymbol(this).toSymbol() + symbolForEventStreamError(unionShape) } 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/SymbolMetadataProvider.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolMetadataProvider.kt index 51df865479..a1faf8702c 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolMetadataProvider.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolMetadataProvider.kt @@ -14,6 +14,7 @@ import software.amazon.smithy.model.shapes.ListShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.NumberShape +import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.StructureShape @@ -31,21 +32,13 @@ import software.amazon.smithy.rust.codegen.core.util.hasTrait * Default delegator to enable easily decorating another symbol provider. */ open class WrappingSymbolProvider(private val base: RustSymbolProvider) : RustSymbolProvider { - override fun config(): SymbolVisitorConfig { - return base.config() - } - - override fun toEnumVariantName(definition: EnumDefinition): MaybeRenamed? { - return base.toEnumVariantName(definition) - } - - override fun toSymbol(shape: Shape): Symbol { - return base.toSymbol(shape) - } - - override fun toMemberName(shape: MemberShape): String { - return base.toMemberName(shape) - } + override fun config(): SymbolVisitorConfig = base.config() + override fun toEnumVariantName(definition: EnumDefinition): MaybeRenamed? = base.toEnumVariantName(definition) + override fun toSymbol(shape: Shape): Symbol = base.toSymbol(shape) + override fun toMemberName(shape: MemberShape): String = base.toMemberName(shape) + override fun symbolForOperationError(operation: OperationShape): Symbol = base.symbolForOperationError(operation) + override fun symbolForEventStreamError(eventStream: UnionShape): Symbol = + base.symbolForEventStreamError(eventStream) } /** diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolVisitor.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolVisitor.kt index c6a1b1dac6..21c09ac693 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolVisitor.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolVisitor.kt @@ -45,8 +45,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.smithy.traits.RustBoxTrait -import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait -import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticOutputTrait import software.amazon.smithy.rust.codegen.core.util.PANIC import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf @@ -67,10 +65,25 @@ val SimpleShapes: Map, RustType> = mapOf( StringShape::class to RustType.String, ) +/** + * Provider for RustModules so that the symbol provider knows where to organize things. + */ +interface ModuleProvider { + /** Returns the module for a shape */ + fun moduleForShape(shape: Shape): RustModule.LeafModule + + /** Returns the module for an operation error */ + fun moduleForOperationError(operation: OperationShape): RustModule.LeafModule + + /** Returns the module for an event stream error */ + fun moduleForEventStreamError(eventStream: UnionShape): RustModule.LeafModule +} + data class SymbolVisitorConfig( val runtimeConfig: RuntimeConfig, val renameExceptions: Boolean, val nullabilityCheckMode: CheckMode, + val moduleProvider: ModuleProvider, ) /** @@ -164,9 +177,21 @@ data class MaybeRenamed(val name: String, val renamedFrom: String?) /** * SymbolProvider interface that carries both the inner configuration and a function to produce an enum variant name. */ -interface RustSymbolProvider : SymbolProvider { +interface RustSymbolProvider : SymbolProvider, ModuleProvider { fun config(): SymbolVisitorConfig fun toEnumVariantName(definition: EnumDefinition): MaybeRenamed? + + override fun moduleForShape(shape: Shape): RustModule.LeafModule = config().moduleProvider.moduleForShape(shape) + override fun moduleForOperationError(operation: OperationShape): RustModule.LeafModule = + config().moduleProvider.moduleForOperationError(operation) + override fun moduleForEventStreamError(eventStream: UnionShape): RustModule.LeafModule = + config().moduleProvider.moduleForEventStreamError(eventStream) + + /** Returns the symbol for an operation error */ + fun symbolForOperationError(operation: OperationShape): Symbol + + /** Returns the symbol for an event stream error */ + fun symbolForEventStreamError(eventStream: UnionShape): Symbol } /** @@ -211,6 +236,18 @@ open class SymbolVisitor( return shape.accept(this) } + override fun symbolForOperationError(operation: OperationShape): Symbol = + toSymbol(operation).let { symbol -> + val module = moduleForOperationError(operation) + module.toType().resolve("${symbol.name}Error").toSymbol().toBuilder().locatedIn(module).build() + } + + override fun symbolForEventStreamError(eventStream: UnionShape): Symbol = + toSymbol(eventStream).let { symbol -> + val module = moduleForEventStreamError(eventStream) + module.toType().resolve("${symbol.name}Error").toSymbol().toBuilder().locatedIn(module).build() + } + /** * Return the name of a given `enum` variant. Note that this refers to `enum` in the Smithy context * where enum is a trait that can be applied to [StringShape] and not in the Rust context of an algebraic data type. @@ -261,7 +298,7 @@ open class SymbolVisitor( override fun stringShape(shape: StringShape): Symbol { return if (shape.hasTrait()) { val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) - symbolBuilder(shape, rustType).locatedIn(ModelsModule).build() + symbolBuilder(shape, rustType).locatedIn(moduleForShape(shape)).build() } else { simpleShape(shape) } @@ -312,7 +349,7 @@ open class SymbolVisitor( .replaceFirstChar { it.uppercase() }, ), ) - .locatedIn(OperationsModule) + .locatedIn(moduleForShape(shape)) .build() } @@ -326,25 +363,15 @@ open class SymbolVisitor( override fun structureShape(shape: StructureShape): Symbol { val isError = shape.hasTrait() - val isInput = shape.hasTrait() - val isOutput = shape.hasTrait() val name = shape.contextName(serviceShape).toPascalCase().letIf(isError && config.renameExceptions) { it.replace("Exception", "Error") } - val builder = symbolBuilder(shape, RustType.Opaque(name)) - return when { - isError -> builder.locatedIn(ErrorsModule) - isInput -> builder.locatedIn(InputsModule) - isOutput -> builder.locatedIn(OutputsModule) - else -> builder.locatedIn(ModelsModule) - }.build() + return symbolBuilder(shape, RustType.Opaque(name)).locatedIn(moduleForShape(shape)).build() } override fun unionShape(shape: UnionShape): Symbol { val name = shape.contextName(serviceShape).toPascalCase() - val builder = symbolBuilder(shape, RustType.Opaque(name)).locatedIn(ModelsModule) - - return builder.build() + return symbolBuilder(shape, RustType.Opaque(name)).locatedIn(moduleForShape(shape)).build() } override fun memberShape(shape: MemberShape): Symbol { diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtra.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtra.kt index 02a8843c19..ce4b7085a5 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtra.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/customizations/SmithyTypesPubUseExtra.kt @@ -8,11 +8,11 @@ package software.amazon.smithy.rust.codegen.core.smithy.customizations import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule +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.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig 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.util.hasEventStreamMember import software.amazon.smithy.rust.codegen.core.util.hasStreamingMember @@ -64,11 +64,9 @@ internal fun pubUseTypes(runtimeConfig: RuntimeConfig, model: Model): List rust("pub use #T;", type) } - } +fun pubUseSmithyTypes(runtimeConfig: RuntimeConfig, model: Model): Writable = writable { + val types = pubUseTypes(runtimeConfig, model) + if (types.isNotEmpty()) { + types.forEach { type -> rust("pub use #T;", type) } } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGenerator.kt index 69f1ad8639..a86c9fce19 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGenerator.kt @@ -14,7 +14,6 @@ import software.amazon.smithy.model.shapes.UnionShape import software.amazon.smithy.model.traits.RetryableTrait import software.amazon.smithy.rust.codegen.core.rustlang.Attribute import software.amazon.smithy.rust.codegen.core.rustlang.RustMetadata -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.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.rustlang.Writable @@ -28,61 +27,49 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable 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.UNREACHABLE 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 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)) { - * write("todo!() // function body") - * } - * ``` - */ -fun OperationShape.errorSymbol(symbolProvider: RustSymbolProvider): RuntimeType { - val operationSymbol = symbolProvider.toSymbol(this) - return RustModule.Error.toType().resolve("${operationSymbol.name}Error") -} - -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. + * + * This generator also generates errors for event streams. */ class OperationErrorGenerator( private val model: Model, private val symbolProvider: RustSymbolProvider, - private val operationSymbol: Symbol, - private val errors: List, + private val operationOrEventStream: Shape, ) { private val runtimeConfig = symbolProvider.config().runtimeConfig + private val symbol = symbolProvider.toSymbol(operationOrEventStream) private val genericError = RuntimeType.genericError(symbolProvider.config().runtimeConfig) private val createUnhandledError = RuntimeType.smithyHttp(runtimeConfig).resolve("result::CreateUnhandledError") + private fun operationErrors(): List = + (operationOrEventStream as OperationShape).operationErrors(model).map { it.asStructureShape().get() } + private fun eventStreamErrors(): List = + (operationOrEventStream as UnionShape).eventStreamErrors() + .map { model.expectShape(it.asMemberShape().get().target, StructureShape::class.java) } + fun render(writer: RustWriter) { - val errorSymbol = RuntimeType("crate::error::${operationSymbol.name}Error") - renderErrors(writer, errorSymbol, operationSymbol) - } + val (errorSymbol, errors) = when (operationOrEventStream) { + is OperationShape -> symbolProvider.symbolForOperationError(operationOrEventStream) to operationErrors() + is UnionShape -> symbolProvider.symbolForEventStreamError(operationOrEventStream) to eventStreamErrors() + else -> UNREACHABLE("OperationErrorGenerator only supports operation or event stream shapes") + } - fun renderErrors( - writer: RustWriter, - errorSymbol: RuntimeType, - operationSymbol: Symbol, - ) { val meta = RustMetadata( derives = setOf(RuntimeType.Debug), additionalAttributes = listOf(Attribute.NonExhaustive), visibility = Visibility.PUBLIC, ) - writer.rust("/// Error type for the `${operationSymbol.name}` operation.") + writer.rust("/// Error type for the `${symbol.name}` operation.") meta.render(writer) writer.rustBlock("struct ${errorSymbol.name}") { rust( @@ -98,13 +85,13 @@ class OperationErrorGenerator( writer.rustBlock("impl #T for ${errorSymbol.name}", createUnhandledError) { rustBlock("fn create_unhandled_error(source: Box) -> Self") { rustBlock("Self") { - rust("kind: ${errorSymbol.name}Kind::Unhandled(#T::new(source)),", unhandledError()) + rust("kind: ${errorSymbol.name}Kind::Unhandled(#T::new(source)),", unhandledError(symbolProvider)) rust("meta: Default::default()") } } } - writer.rust("/// Types of errors that can occur for the `${operationSymbol.name}` operation.") + writer.rust("/// Types of errors that can occur for the `${symbol.name}` operation.") meta.render(writer) writer.rustBlock("enum ${errorSymbol.name}Kind") { errors.forEach { errorVariant -> @@ -118,7 +105,7 @@ class OperationErrorGenerator( """ Unhandled(#T), """, - unhandledError(), + unhandledError(symbolProvider), ) } writer.rustBlock("impl #T for ${errorSymbol.name}", RuntimeType.Display) { @@ -201,7 +188,7 @@ class OperationErrorGenerator( """, "generic_error" to genericError, "std_error" to RuntimeType.StdError, - "Unhandled" to unhandledError(), + "Unhandled" to unhandledError(symbolProvider), ) errors.forEach { error -> val errorVariantSymbol = symbolProvider.toSymbol(error) @@ -248,7 +235,7 @@ class OperationErrorGenerator( */ private fun RustWriter.delegateToVariants( errors: List, - symbol: RuntimeType, + symbol: Symbol, handler: (VariantMatch) -> Writable, ) { rustBlock("match &self.kind") { diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGenerator.kt index c03a30b6cc..606d375c74 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGenerator.kt @@ -5,6 +5,7 @@ package software.amazon.smithy.rust.codegen.core.smithy.generators.error +import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.shapes.StructureShape @@ -59,7 +60,7 @@ class ServiceErrorGenerator(private val codegenContext: CodegenContext, private // Every operation error can be converted into service::Error operations.forEach { operationShape -> // operation errors - renderImplFrom(operationShape.errorSymbol(symbolProvider), operationShape.errors) + renderImplFrom(symbolProvider.symbolForOperationError(operationShape), operationShape.errors) } // event stream errors operations.map { it.eventStreamErrors(codegenContext.model) } @@ -67,7 +68,7 @@ class ServiceErrorGenerator(private val codegenContext: CodegenContext, private .associate { it.key to it.value } .forEach { (unionShape, errors) -> renderImplFrom( - unionShape.eventStreamErrorSymbol(symbolProvider), + symbolProvider.symbolForEventStreamError(unionShape), errors.map { it.id }, ) } @@ -89,7 +90,7 @@ class ServiceErrorGenerator(private val codegenContext: CodegenContext, private } } - private fun RustWriter.renderImplFrom(errorSymbol: RuntimeType, errors: List) { + private fun RustWriter.renderImplFrom(errorSymbol: Symbol, errors: List) { if (errors.isNotEmpty() || CodegenTarget.CLIENT == codegenContext.target) { val operationErrors = errors.map { model.expectShape(it) } rustBlock( @@ -104,7 +105,7 @@ class ServiceErrorGenerator(private val codegenContext: CodegenContext, private ) { rustBlock("match err") { rust("#T::ServiceError(context) => Self::from(context.into_err()),", sdkError) - rust("_ => Error::Unhandled(#T::new(err.into())),", unhandledError()) + rust("_ => Error::Unhandled(#T::new(err.into())),", unhandledError(symbolProvider)) } } } @@ -122,7 +123,7 @@ class ServiceErrorGenerator(private val codegenContext: CodegenContext, private rustTemplate( "#{errorSymbol}Kind::Unhandled(inner) => Error::Unhandled(#{unhandled}::new(inner.into())),", "errorSymbol" to errorSymbol, - "unhandled" to unhandledError(), + "unhandled" to unhandledError(symbolProvider), ) } } @@ -144,7 +145,7 @@ class ServiceErrorGenerator(private val codegenContext: CodegenContext, private rust("${sym.name}(#T),", sym) } docs(UNHANDLED_ERROR_DOCS) - rust("Unhandled(#T)", unhandledError()) + rust("Unhandled(#T)", unhandledError(symbolProvider)) } } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/UnhandledErrorGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/UnhandledErrorGenerator.kt index bd28c1a852..8080377c62 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/UnhandledErrorGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/UnhandledErrorGenerator.kt @@ -9,6 +9,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.rustlang.docs import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider internal const val UNHANDLED_ERROR_DOCS = """ @@ -20,31 +21,32 @@ internal const val UNHANDLED_ERROR_DOCS = [`Error::source`](std::error::Error::source) for more details about the underlying cause. """ -internal fun unhandledError(): RuntimeType = RuntimeType.forInlineFun("Unhandled", RustModule.Error) { - docs(UNHANDLED_ERROR_DOCS) - rustTemplate( - """ - ##[derive(Debug)] - pub struct Unhandled { - source: Box, - } - impl Unhandled { - ##[allow(unused)] - pub(crate) fn new(source: Box) -> Self { - Self { source } +internal fun unhandledError(symbolProvider: RustSymbolProvider): RuntimeType = + RuntimeType.forInlineFun("Unhandled", RustModule.Error) { + docs(UNHANDLED_ERROR_DOCS) + rustTemplate( + """ + ##[derive(Debug)] + pub struct Unhandled { + source: Box, } - } - impl std::fmt::Display for Unhandled { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - write!(f, "unhandled error") + impl Unhandled { + ##[allow(unused)] + pub(crate) fn new(source: Box) -> Self { + Self { source } + } } - } - impl #{StdError} for Unhandled { - fn source(&self) -> Option<&(dyn #{StdError} + 'static)> { - Some(self.source.as_ref() as _) + impl std::fmt::Display for Unhandled { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + write!(f, "unhandled error") + } } - } - """, - "StdError" to RuntimeType.StdError, - ) -} + impl #{StdError} for Unhandled { + fn source(&self) -> Option<&(dyn #{StdError} + 'static)> { + Some(self.source.as_ref() as _) + } + } + """, + "StdError" to RuntimeType.StdError, + ) + } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/http/HttpBindingGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/http/HttpBindingGenerator.kt index e018147808..c3a156fcca 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/http/HttpBindingGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/http/HttpBindingGenerator.kt @@ -210,7 +210,7 @@ class HttpBindingGenerator( */ fun generateDeserializePayloadFn( binding: HttpBindingDescriptor, - errorT: RuntimeType, + errorSymbol: Symbol, // Deserialize a single structure, union or document member marked as a payload payloadParser: RustWriter.(String) -> Unit, httpMessageType: HttpMessageType = HttpMessageType.RESPONSE, @@ -224,7 +224,7 @@ class HttpBindingGenerator( "pub fn $fnName(body: &mut #T) -> std::result::Result<#T, #T>", RuntimeType.sdkBody(runtimeConfig), outputT, - errorT, + errorSymbol, ) { // Streaming unions are Event Streams and should be handled separately val target = model.expectShape(binding.member.target) @@ -238,10 +238,10 @@ class HttpBindingGenerator( // The output needs to be Optional when deserializing the payload body or the caller signature // will not match. val outputT = symbolProvider.toSymbol(binding.member).makeOptional() - rustBlock("pub fn $fnName(body: &[u8]) -> std::result::Result<#T, #T>", outputT, errorT) { + rustBlock("pub fn $fnName(body: &[u8]) -> std::result::Result<#T, #T>", outputT, errorSymbol) { deserializePayloadBody( binding, - errorT, + errorSymbol, structuredHandler = payloadParser, httpMessageType, ) @@ -286,7 +286,7 @@ class HttpBindingGenerator( private fun RustWriter.deserializePayloadBody( binding: HttpBindingDescriptor, - errorSymbol: RuntimeType, + errorSymbol: Symbol, structuredHandler: RustWriter.(String) -> Unit, httpMessageType: HttpMessageType = HttpMessageType.RESPONSE, ) { 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 e6bf4812f3..2743d1f246 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 @@ -33,7 +33,6 @@ 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.UnionGenerator -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.eventStreamErrorSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.renderUnknownVariant import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName import software.amazon.smithy.rust.codegen.core.smithy.protocols.Protocol @@ -60,7 +59,7 @@ class EventStreamUnmarshallerGenerator( private val errorSymbol = if (codegenTarget == CodegenTarget.SERVER && unionShape.eventStreamErrors().isEmpty()) { RuntimeType.smithyHttp(runtimeConfig).resolve("event_stream::MessageStreamError").toSymbol() } else { - unionShape.eventStreamErrorSymbol(symbolProvider).toSymbol() + symbolProvider.symbolForEventStreamError(unionShape) } 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 e4ec2cec3a..579781996a 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 @@ -23,7 +23,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig 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.eventStreamErrorSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.renderUnknownVariant import software.amazon.smithy.rust.codegen.core.smithy.generators.unknownVariantError import software.amazon.smithy.rust.codegen.core.smithy.rustType @@ -48,7 +47,7 @@ class EventStreamErrorMarshallerGenerator( private val operationErrorSymbol = if (target == CodegenTarget.SERVER && unionShape.eventStreamErrors().isEmpty()) { RuntimeType.smithyHttp(runtimeConfig).resolve("event_stream::MessageStreamError").toSymbol() } else { - unionShape.eventStreamErrorSymbol(symbolProvider).toSymbol() + symbolProvider.symbolForEventStreamError(unionShape) } 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 34fac717aa..d11811ae36 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,7 +5,6 @@ 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 @@ -14,13 +13,10 @@ import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.shapes.UnionShape import software.amazon.smithy.model.traits.ErrorTrait -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.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.DirectedWalker -import software.amazon.smithy.rust.codegen.core.smithy.ErrorsModule -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule 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 @@ -77,8 +73,7 @@ interface EventStreamTestRequirements { writer: RustWriter, model: Model, symbolProvider: RustSymbolProvider, - operationSymbol: Symbol, - errors: List, + operationOrEventStream: Shape, ) } @@ -122,25 +117,27 @@ object EventStreamTestTools { val walker = DirectedWalker(model) val project = TestWorkspace.testProject(symbolProvider) - val operationSymbol = symbolProvider.toSymbol(operationShape) - project.withModule(ErrorsModule) { - val errors = model.serviceShapes - .flatMap { walker.walkShapes(it) } - .filterIsInstance() - .filter { shape -> shape.hasTrait() } - requirements.renderOperationError(this, model, symbolProvider, operationSymbol, errors) - requirements.renderOperationError(this, model, symbolProvider, symbolProvider.toSymbol(unionShape), errors) + val errors = model.serviceShapes + .flatMap { walker.walkShapes(it) } + .filterIsInstance() + .filter { shape -> shape.hasTrait() } + check(errors.isNotEmpty()) { "must have at least one error modeled" } + project.withModule(codegenContext.symbolProvider.moduleForShape(errors[0])) { + requirements.renderOperationError(this, model, symbolProvider, operationShape) + requirements.renderOperationError(this, model, symbolProvider, unionShape) for (shape in errors) { StructureGenerator(model, symbolProvider, this, shape).render(codegenTarget) requirements.renderBuilderForShape(this, codegenContext, shape) } } - project.withModule(ModelsModule) { - val inputOutput = model.lookup("test#TestStreamInputOutput") + val inputOutput = model.lookup("test#TestStreamInputOutput") + project.withModule(codegenContext.symbolProvider.moduleForShape(inputOutput)) { recursivelyGenerateModels(model, symbolProvider, inputOutput, this, codegenTarget) } - project.withModule(RustModule.Output) { - operationShape.outputShape(model).renderWithModelBuilder(model, symbolProvider, this) + operationShape.outputShape(model).also { outputShape -> + project.moduleFor(outputShape) { + outputShape.renderWithModelBuilder(model, symbolProvider, this) + } } return TestEventStreamProject( model, diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/Rust.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/Rust.kt index a09ca9f10c..5fa053e4b0 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/Rust.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/Rust.kt @@ -10,13 +10,11 @@ import org.intellij.lang.annotations.Language import software.amazon.smithy.build.FileManifest import software.amazon.smithy.build.PluginContext import software.amazon.smithy.codegen.core.CodegenException -import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model +import software.amazon.smithy.model.loader.ModelAssembler import software.amazon.smithy.model.node.Node import software.amazon.smithy.model.node.ObjectNode -import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.shapes.ShapeId -import software.amazon.smithy.model.traits.EnumDefinition import software.amazon.smithy.rust.codegen.core.rustlang.Attribute import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency import software.amazon.smithy.rust.codegen.core.rustlang.DependencyScope @@ -28,13 +26,10 @@ import software.amazon.smithy.rust.codegen.core.rustlang.raw 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.smithy.CoreCodegenConfig -import software.amazon.smithy.rust.codegen.core.smithy.MaybeRenamed import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig 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 import software.amazon.smithy.rust.codegen.core.util.CommandFailed -import software.amazon.smithy.rust.codegen.core.util.PANIC import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.letIf import software.amazon.smithy.rust.codegen.core.util.orNullIfEmpty @@ -116,22 +111,14 @@ object TestWorkspace { } } - @Suppress("NAME_SHADOWING") - fun testProject(symbolProvider: RustSymbolProvider? = null, debugMode: Boolean = false): TestWriterDelegator { - val subprojectDir = subproject() - val symbolProvider = symbolProvider ?: object : RustSymbolProvider { - override fun config(): SymbolVisitorConfig { - PANIC("") - } + fun testProject(debugMode: Boolean = false): TestWriterDelegator = + testProject(ModelAssembler().assemble().unwrap(), debugMode) - override fun toEnumVariantName(definition: EnumDefinition): MaybeRenamed? { - PANIC("") - } + fun testProject(model: Model, debugMode: Boolean = false): TestWriterDelegator = + testProject(testSymbolProvider(model), debugMode) - override fun toSymbol(shape: Shape?): Symbol { - PANIC("") - } - } + fun testProject(symbolProvider: RustSymbolProvider, debugMode: Boolean = false): TestWriterDelegator { + val subprojectDir = subproject() return TestWriterDelegator( FileManifest.create(subprojectDir.toPath()), symbolProvider, @@ -311,7 +298,10 @@ fun FileManifest.printGeneratedFiles() { * should generally be set to `false` to avoid invalidating the Cargo cache between * every unit test run. */ -fun TestWriterDelegator.compileAndTest(runClippy: Boolean = false) { +fun TestWriterDelegator.compileAndTest( + runClippy: Boolean = false, + expectFailure: Boolean = false, +): String { val stubModel = """ namespace fake service Fake { @@ -332,10 +322,11 @@ fun TestWriterDelegator.compileAndTest(runClippy: Boolean = false) { // cargo fmt errors are useless, ignore } val env = mapOf("RUSTFLAGS" to "-A dead_code") - "cargo test".runCommand(baseDir, env) + val testOutput = "cargo test".runCommand(baseDir, env) if (runClippy) { "cargo clippy".runCommand(baseDir, env) } + return testOutput } fun TestWriterDelegator.rustSettings() = diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/TestHelpers.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/TestHelpers.kt index 6c9310a309..05ef9bf216 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/TestHelpers.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/TestHelpers.kt @@ -7,10 +7,15 @@ package software.amazon.smithy.rust.codegen.core.testutil import software.amazon.smithy.model.Model import software.amazon.smithy.model.knowledge.NullableIndex +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.ShapeId import software.amazon.smithy.model.shapes.StructureShape +import software.amazon.smithy.model.shapes.UnionShape +import software.amazon.smithy.model.traits.ErrorTrait 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.rustlang.RustReservedWordSymbolProvider import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.smithy.BaseSymbolMetadataProvider @@ -18,6 +23,7 @@ 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.CoreCodegenConfig import software.amazon.smithy.rust.codegen.core.smithy.CoreRustSettings +import software.amazon.smithy.rust.codegen.core.smithy.ModuleProvider import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RuntimeCrateLocation import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider @@ -26,16 +32,53 @@ import software.amazon.smithy.rust.codegen.core.smithy.SymbolVisitorConfig import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.StructureGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.implBlock +import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait +import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticOutputTrait import software.amazon.smithy.rust.codegen.core.util.dq +import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf import java.io.File val TestRuntimeConfig = RuntimeConfig(runtimeCrateLocation = RuntimeCrateLocation.Path(File("../rust-runtime/").absolutePath)) + +/** + * IMPORTANT: You shouldn't need to refer to these directly in code or tests. They are private for a reason. + * + * In general, the RustSymbolProvider's `config()` has a `moduleFor` function that should be used + * to find the destination module for a given shape. + */ +private object CodegenCoreTestModules { + // Use module paths that don't align with either server or client to make sure + // the codegen is resilient to differences in module path. + val ModelsTestModule = RustModule.public("test_model", documentation = "Test models module") + val ErrorsTestModule = RustModule.public("test_error", documentation = "Test error module") + val InputsTestModule = RustModule.public("test_input", documentation = "Test input module") + val OutputsTestModule = RustModule.public("test_output", documentation = "Test output module") + val OperationsTestModule = RustModule.public("test_operation", documentation = "Test operation module") + + object TestModuleProvider : ModuleProvider { + override fun moduleForShape(shape: Shape): RustModule.LeafModule = when (shape) { + is OperationShape -> OperationsTestModule + is StructureShape -> when { + shape.hasTrait() -> ErrorsTestModule + shape.hasTrait() -> InputsTestModule + shape.hasTrait() -> OutputsTestModule + else -> ModelsTestModule + } + else -> ModelsTestModule + } + + override fun moduleForOperationError(operation: OperationShape): RustModule.LeafModule = ErrorsTestModule + override fun moduleForEventStreamError(eventStream: UnionShape): RustModule.LeafModule = ErrorsTestModule + } +} + val TestSymbolVisitorConfig = SymbolVisitorConfig( runtimeConfig = TestRuntimeConfig, renameExceptions = true, nullabilityCheckMode = NullableIndex.CheckMode.CLIENT_ZERO_VALUE_V1, + moduleProvider = CodegenCoreTestModules.TestModuleProvider, ) fun testRustSettings( @@ -104,9 +147,10 @@ fun StructureShape.renderWithModelBuilder( forWhom: CodegenTarget = CodegenTarget.CLIENT, ) { StructureGenerator(model, symbolProvider, writer, this).render(forWhom) - val modelBuilder = BuilderGenerator(model, symbolProvider, this) - modelBuilder.render(writer) - writer.implBlock(this, symbolProvider) { - modelBuilder.renderConvenienceMethod(this) + BuilderGenerator(model, symbolProvider, this).also { builderGen -> + builderGen.render(writer) + writer.implBlock(this, symbolProvider) { + builderGen.renderConvenienceMethod(this) + } } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/util/Panic.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/util/Panic.kt index b7dc3e681c..7d24a17988 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/util/Panic.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/util/Panic.kt @@ -6,7 +6,7 @@ package software.amazon.smithy.rust.codegen.core.util /** Something has gone horribly wrong due to a coding error */ -fun PANIC(reason: String): Nothing = throw RuntimeException(reason) +fun PANIC(reason: String = ""): Nothing = throw RuntimeException(reason) /** This code should never be executed (but Kotlin cannot prove that) */ fun UNREACHABLE(reason: String): Nothing = throw IllegalStateException("This should be unreachable: $reason") diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWordsTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWordsTest.kt index 5f72e33765..9ef10a5af8 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWordsTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustReservedWordsTest.kt @@ -9,7 +9,9 @@ import io.kotest.matchers.shouldBe import org.junit.jupiter.api.Test import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.MemberShape +import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.shapes.UnionShape import software.amazon.smithy.model.traits.EnumDefinition import software.amazon.smithy.rust.codegen.core.smithy.MaybeRenamed import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider @@ -21,9 +23,9 @@ import software.amazon.smithy.rust.codegen.core.util.toPascalCase internal class RustReservedWordSymbolProviderTest { class Stub : RustSymbolProvider { - override fun config(): SymbolVisitorConfig { - PANIC("") - } + override fun config(): SymbolVisitorConfig = PANIC() + override fun symbolForOperationError(operation: OperationShape): Symbol = PANIC() + override fun symbolForEventStreamError(eventStream: UnionShape): Symbol = PANIC() override fun toEnumVariantName(definition: EnumDefinition): MaybeRenamed? { return definition.name.orNull()?.let { MaybeRenamed(it.toPascalCase(), null) } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriterTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriterTest.kt index 86d48a2602..7d6295e72b 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriterTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriterTest.kt @@ -96,7 +96,7 @@ class RustWriterTest { val symbol = testSymbolProvider(model).toSymbol(shape) val sut = RustWriter.forModule("lib") sut.docs("A link! #D", symbol) - sut.toString() shouldContain "/// A link! [`Foo`](crate::model::Foo)" + sut.toString() shouldContain "/// A link! [`Foo`](crate::test_model::Foo)" } @Test diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGeneratorTest.kt index 3d5c75384c..b735d16806 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGeneratorTest.kt @@ -8,17 +8,22 @@ package software.amazon.smithy.rust.codegen.core.smithy.generators import org.junit.jupiter.api.Test import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.MemberShape +import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.shapes.UnionShape import software.amazon.smithy.model.traits.EnumDefinition -import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter +import software.amazon.smithy.rust.codegen.core.rustlang.Attribute.Companion.AllowDeprecated import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.smithy.Default import software.amazon.smithy.rust.codegen.core.smithy.MaybeRenamed import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.SymbolVisitorConfig import software.amazon.smithy.rust.codegen.core.smithy.setDefault +import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest 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.PANIC internal class BuilderGeneratorTest { private val model = StructureGeneratorTest.model @@ -30,29 +35,34 @@ internal class BuilderGeneratorTest { @Test fun `generate builders`() { val provider = testSymbolProvider(model) - val writer = RustWriter.forModule("model") - writer.rust("##![allow(deprecated)]") - val innerGenerator = StructureGenerator(model, provider, writer, inner) - val generator = StructureGenerator(model, provider, writer, struct) - val builderGenerator = BuilderGenerator(model, provider, struct) - generator.render() - innerGenerator.render() - builderGenerator.render(writer) - writer.implBlock(struct, provider) { - builderGenerator.renderConvenienceMethod(this) + val project = TestWorkspace.testProject(provider) + project.moduleFor(inner) { + rust("##![allow(deprecated)]") + StructureGenerator(model, provider, this, inner).render() + StructureGenerator(model, provider, this, struct).render() + BuilderGenerator(model, provider, struct).also { builderGen -> + builderGen.render(this) + implBlock(struct, provider) { + builderGen.renderConvenienceMethod(this) + } + } + + unitTest("generate_builders") { + rust( + """ + let my_struct = MyStruct::builder().byte_value(4).foo("hello!").build(); + assert_eq!(my_struct.foo.unwrap(), "hello!"); + assert_eq!(my_struct.bar, 0); + """, + ) + } } - writer.compileAndTest( - """ - let my_struct = MyStruct::builder().byte_value(4).foo("hello!").build(); - assert_eq!(my_struct.foo.unwrap(), "hello!"); - assert_eq!(my_struct.bar, 0); - """, - ) + project.compileAndTest() } @Test fun `generate fallible builders`() { - val baseProvider: RustSymbolProvider = testSymbolProvider(StructureGeneratorTest.model) + val baseProvider = testSymbolProvider(StructureGeneratorTest.model) val provider = object : RustSymbolProvider { override fun config(): SymbolVisitorConfig { @@ -67,77 +77,86 @@ internal class BuilderGeneratorTest { return baseProvider.toSymbol(shape).toBuilder().setDefault(Default.NoDefault).build() } + override fun symbolForOperationError(operation: OperationShape): Symbol = PANIC() + override fun symbolForEventStreamError(eventStream: UnionShape): Symbol = PANIC() + override fun toMemberName(shape: MemberShape?): String { return baseProvider.toMemberName(shape) } } - val writer = RustWriter.forModule("model") - writer.rust("##![allow(deprecated)]") - val innerGenerator = StructureGenerator( - StructureGeneratorTest.model, provider, writer, - StructureGeneratorTest.inner, - ) - val generator = StructureGenerator( - StructureGeneratorTest.model, provider, writer, - StructureGeneratorTest.struct, - ) - generator.render() - innerGenerator.render() - val builderGenerator = BuilderGenerator(model, provider, struct) - builderGenerator.render(writer) - writer.implBlock(struct, provider) { - builderGenerator.renderConvenienceMethod(this) + val project = TestWorkspace.testProject(provider) + project.moduleFor(StructureGeneratorTest.struct) { + AllowDeprecated.render(this) + StructureGenerator(model, provider, this, inner).render() + StructureGenerator(model, provider, this, struct).render() + BuilderGenerator(model, provider, struct).also { builderGenerator -> + builderGenerator.render(this) + implBlock(struct, provider) { + builderGenerator.renderConvenienceMethod(this) + } + } + unitTest("generate_fallible_builders") { + rust( + """ + let my_struct = MyStruct::builder().byte_value(4).foo("hello!").bar(0).build().expect("required field was not provided"); + assert_eq!(my_struct.foo.unwrap(), "hello!"); + assert_eq!(my_struct.bar, 0); + """, + ) + } } - writer.compileAndTest( - """ - let my_struct = MyStruct::builder().byte_value(4).foo("hello!").bar(0).build().expect("required field was not provided"); - assert_eq!(my_struct.foo.unwrap(), "hello!"); - assert_eq!(my_struct.bar, 0); - """, - ) + project.compileAndTest() } @Test fun `builder for a struct with sensitive fields should implement the debug trait as such`() { val provider = testSymbolProvider(model) - val writer = RustWriter.forModule("model") - val credsGenerator = StructureGenerator(model, provider, writer, credentials) - val builderGenerator = BuilderGenerator(model, provider, credentials) - credsGenerator.render() - builderGenerator.render(writer) - writer.implBlock(credentials, provider) { - builderGenerator.renderConvenienceMethod(this) + val project = TestWorkspace.testProject(provider) + project.moduleFor(credentials) { + StructureGenerator(model, provider, this, credentials).render() + BuilderGenerator(model, provider, credentials).also { builderGen -> + builderGen.render(this) + implBlock(credentials, provider) { + builderGen.renderConvenienceMethod(this) + } + } + unitTest("sensitive_fields") { + rust( + """ + let builder = Credentials::builder() + .username("admin") + .password("pswd") + .secret_key("12345"); + assert_eq!(format!("{:?}", builder), "Builder { username: Some(\"admin\"), password: \"*** Sensitive Data Redacted ***\", secret_key: \"*** Sensitive Data Redacted ***\" }"); + """, + ) + } } - writer.compileAndTest( - """ - use super::*; - let builder = Credentials::builder() - .username("admin") - .password("pswd") - .secret_key("12345"); - assert_eq!(format!("{:?}", builder), "Builder { username: Some(\"admin\"), password: \"*** Sensitive Data Redacted ***\", secret_key: \"*** Sensitive Data Redacted ***\" }"); - """, - ) + project.compileAndTest() } @Test fun `builder for a sensitive struct should implement the debug trait as such`() { val provider = testSymbolProvider(model) - val writer = RustWriter.forModule("model") - val structGenerator = StructureGenerator(model, provider, writer, secretStructure) - val builderGenerator = BuilderGenerator(model, provider, secretStructure) - structGenerator.render() - builderGenerator.render(writer) - writer.implBlock(secretStructure, provider) { - builderGenerator.renderConvenienceMethod(this) + val project = TestWorkspace.testProject(provider) + project.moduleFor(secretStructure) { + StructureGenerator(model, provider, this, secretStructure).render() + BuilderGenerator(model, provider, secretStructure).also { builderGen -> + builderGen.render(this) + implBlock(secretStructure, provider) { + builderGen.renderConvenienceMethod(this) + } + } + unitTest("sensitive_struct") { + rust( + """ + let builder = SecretStructure::builder() + .secret_field("secret"); + assert_eq!(format!("{:?}", builder), "Builder { secret_field: \"*** Sensitive Data Redacted ***\" }"); + """, + ) + } } - writer.compileAndTest( - """ - use super::*; - let builder = SecretStructure::builder() - .secret_field("secret"); - assert_eq!(format!("{:?}", builder), "Builder { secret_field: \"*** Sensitive Data Redacted ***\" }"); - """, - ) + project.compileAndTest() } } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGeneratorTest.kt index e2fb34b461..480342e78d 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/EnumGeneratorTest.kt @@ -13,7 +13,7 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.traits.EnumTrait -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule +import software.amazon.smithy.rust.codegen.core.rustlang.Attribute.Companion.AllowDeprecated import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.rust @@ -128,7 +128,7 @@ class EnumGeneratorTest { val shape = model.lookup("test#InstanceType") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { rust("##![allow(deprecated)]") renderEnum(model, provider, shape) unitTest( @@ -139,12 +139,13 @@ class EnumGeneratorTest { assert_eq!(InstanceType::from("t2.nano"), InstanceType::T2Nano); """, ) - val output = toString() - output.shouldContain("#[non_exhaustive]") - // on enum variant `T2Micro` - output.shouldContain("#[deprecated]") - // on enum itself - output.shouldContain("#[deprecated(since = \"1.2.3\")]") + toString().also { output -> + output.shouldContain("#[non_exhaustive]") + // on enum variant `T2Micro` + output.shouldContain("#[deprecated]") + // on enum itself + output.shouldContain("#[deprecated(since = \"1.2.3\")]") + } } project.compileAndTest() } @@ -168,7 +169,7 @@ class EnumGeneratorTest { val shape = model.lookup("test#FooEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { renderEnum(model, provider, shape) unitTest( "named_enums_implement_eq_and_hash", @@ -201,8 +202,8 @@ class EnumGeneratorTest { val shape = model.lookup("test#FooEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { - rust("##![allow(deprecated)]") + project.moduleFor(shape) { + AllowDeprecated.render(this) renderEnum(model, provider, shape) unitTest( "unnamed_enums_implement_eq_and_hash", @@ -244,8 +245,8 @@ class EnumGeneratorTest { val shape = model.lookup("test#FooEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { - rust("##![allow(deprecated)]") + project.moduleFor(shape) { + AllowDeprecated.render(this) renderEnum(model, provider, shape) unitTest( "it_generates_unnamed_enums", @@ -274,7 +275,7 @@ class EnumGeneratorTest { val shape = model.lookup("test#SomeEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { renderEnum(model, provider, shape) val rendered = toString() rendered shouldContain @@ -303,7 +304,7 @@ class EnumGeneratorTest { val shape = model.lookup("test#SomeEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { renderEnum(model, provider, shape) val rendered = toString() rendered shouldContain @@ -328,7 +329,7 @@ class EnumGeneratorTest { val shape = model.lookup("test#SomeEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { renderEnum(model, provider, shape) unitTest( "it_handles_variants_that_clash_with_rust_reserved_words", @@ -352,7 +353,7 @@ class EnumGeneratorTest { val shape = model.lookup("test#SomeEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { renderEnum(model, provider, shape) unitTest( "impl_debug_for_non_sensitive_enum_should_implement_the_derived_debug_trait", @@ -380,7 +381,7 @@ class EnumGeneratorTest { val shape = model.lookup("test#SomeEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { renderEnum(model, provider, shape) unitTest( "impl_debug_for_sensitive_enum_should_redact_text", @@ -407,7 +408,7 @@ class EnumGeneratorTest { val shape = model.lookup("test#SomeEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { renderEnum(model, provider, shape) unitTest( "impl_debug_for_non_sensitive_unnamed_enum_should_implement_the_derived_debug_trait", @@ -439,7 +440,7 @@ class EnumGeneratorTest { val shape = model.lookup("test#SomeEnum") val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { renderEnum(model, provider, shape) unitTest( "impl_debug_for_sensitive_unnamed_enum_should_redact_text", @@ -505,7 +506,7 @@ class EnumGeneratorTest { output shouldContain "// additional docs" val project = TestWorkspace.testProject(provider) - project.withModule(RustModule.Model) { + project.moduleFor(shape) { renderEnum(model, provider, shape, CustomizingEnumType()) } project.compileAndTest() diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/InstantiatorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/InstantiatorTest.kt index c55ec2ea2a..10c61e125b 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/InstantiatorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/InstantiatorTest.kt @@ -14,7 +14,6 @@ import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.shapes.UnionShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.writable @@ -109,8 +108,8 @@ class InstantiatorTest { Instantiator(symbolProvider, model, runtimeConfig, BuilderKindBehavior(codegenContext), ::enumFromStringFn) val data = Node.parse("""{ "stringVariant": "ok!" }""") - val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + val project = TestWorkspace.testProject(model) + project.moduleFor(union) { UnionGenerator(model, symbolProvider, this, union).render() unitTest("generate_unions") { withBlock("let result = ", ";") { @@ -129,8 +128,8 @@ class InstantiatorTest { Instantiator(symbolProvider, model, runtimeConfig, BuilderKindBehavior(codegenContext), ::enumFromStringFn) val data = Node.parse("""{ "bar": 10, "foo": "hello" }""") - val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + val project = TestWorkspace.testProject(model) + project.moduleFor(structure) { structure.renderWithModelBuilder(model, symbolProvider, this) unitTest("generate_struct_builders") { withBlock("let result = ", ";") { @@ -163,8 +162,8 @@ class InstantiatorTest { """, ) - val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + val project = TestWorkspace.testProject(model) + project.moduleFor(structure) { structure.renderWithModelBuilder(model, symbolProvider, this) unitTest("generate_builders_for_boxed_structs") { withBlock("let result = ", ";") { @@ -193,7 +192,7 @@ class InstantiatorTest { Instantiator(symbolProvider, model, runtimeConfig, BuilderKindBehavior(codegenContext), ::enumFromStringFn) val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + project.lib { unitTest("generate_lists") { withBlock("let result = ", ";") { sut.render(this, model.lookup("com.test#MyList"), data) @@ -214,8 +213,8 @@ class InstantiatorTest { ::enumFromStringFn, ) - val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + val project = TestWorkspace.testProject(model) + project.lib { unitTest("generate_sparse_lists") { withBlock("let result = ", ";") { sut.render(this, model.lookup("com.test#MySparseList"), data) @@ -246,8 +245,8 @@ class InstantiatorTest { ) val inner = model.lookup("com.test#Inner") - val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + val project = TestWorkspace.testProject(model) + project.moduleFor(inner) { inner.renderWithModelBuilder(model, symbolProvider, this) unitTest("generate_maps_of_maps") { withBlock("let result = ", ";") { @@ -278,7 +277,7 @@ class InstantiatorTest { ::enumFromStringFn, ) - val project = TestWorkspace.testProject() + val project = TestWorkspace.testProject(model) project.testModule { unitTest("blob_inputs_are_binary_data") { withBlock("let blob = ", ";") { diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGeneratorTest.kt index 37d73291ef..6959b1a3b0 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGeneratorTest.kt @@ -15,7 +15,6 @@ 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.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.smithy.transformers.RecursiveShapeBoxer import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel @@ -111,11 +110,11 @@ class StructureGeneratorTest { @Test fun `generate structures with public fields`() { - val project = TestWorkspace.testProject() val provider = testSymbolProvider(model) + val project = TestWorkspace.testProject(provider) project.lib { Attribute.AllowDeprecated.render(this) } - project.withModule(ModelsModule) { + project.moduleFor(inner) { val innerGenerator = StructureGenerator(model, provider, this, inner) innerGenerator.render() } @@ -239,7 +238,7 @@ class StructureGeneratorTest { project.lib { Attribute.DenyMissingDocs.render(this) } - project.withModule(ModelsModule) { + project.moduleFor(model.lookup("com.test#Inner")) { StructureGenerator(model, provider, this, model.lookup("com.test#Inner")).render() StructureGenerator(model, provider, this, model.lookup("com.test#MyStruct")).render() } @@ -283,7 +282,7 @@ class StructureGeneratorTest { val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) project.lib { rust("##![allow(deprecated)]") } - project.withModule(ModelsModule) { + project.moduleFor(model.lookup("test#Foo")) { StructureGenerator(model, provider, this, model.lookup("test#Foo")).render() StructureGenerator(model, provider, this, model.lookup("test#Bar")).render() StructureGenerator(model, provider, this, model.lookup("test#Baz")).render() @@ -316,7 +315,7 @@ class StructureGeneratorTest { val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) project.lib { rust("##![allow(deprecated)]") } - project.withModule(ModelsModule) { + project.moduleFor(model.lookup("test#Nested")) { StructureGenerator(model, provider, this, model.lookup("test#Nested")).render() StructureGenerator(model, provider, this, model.lookup("test#Foo")).render() StructureGenerator(model, provider, this, model.lookup("test#Bar")).render() @@ -369,7 +368,7 @@ class StructureGeneratorTest { StructureGenerator(testModel, provider, this, testModel.lookup("test#One")).render() StructureGenerator(testModel, provider, this, testModel.lookup("test#Two")).render() - rustBlock("fn compile_test_one(one: &crate::model::One)") { + rustBlock("fn compile_test_one(one: &crate::test_model::One)") { rust( """ let _: Option<&str> = one.field_string(); @@ -390,17 +389,17 @@ class StructureGeneratorTest { let _: f32 = one.field_primitive_float(); let _: Option = one.field_double(); let _: f64 = one.field_primitive_double(); - let _: Option<&crate::model::Two> = one.two(); + let _: Option<&crate::test_model::Two> = one.two(); let _: Option = one.build_value(); let _: Option = one.builder_value(); let _: Option = one.default_value(); """, ) } - rustBlock("fn compile_test_two(two: &crate::model::Two)") { + rustBlock("fn compile_test_two(two: &crate::test_model::Two)") { rust( """ - let _: Option<&crate::model::One> = two.one(); + let _: Option<&crate::test_model::One> = two.one(); """, ) } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGeneratorTest.kt index 8a66ad112e..8b6778890f 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/UnionGeneratorTest.kt @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.codegen.core.SymbolProvider import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.rust -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest @@ -117,7 +116,7 @@ class UnionGeneratorTest { val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) project.lib { rust("##![allow(deprecated)]") } - project.withModule(ModelsModule) { + project.moduleFor(model.lookup("test#Nested")) { UnionGenerator(model, provider, this, model.lookup("test#Nested")).render() UnionGenerator(model, provider, this, model.lookup("test#Foo")).render() UnionGenerator(model, provider, this, model.lookup("test#Bar")).render() diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGeneratorTest.kt index 38b27ecf4f..f6f815a443 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/OperationErrorGeneratorTest.kt @@ -7,7 +7,6 @@ package software.amazon.smithy.rust.codegen.core.smithy.generators.error 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.transformers.OperationNormalizer import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel @@ -50,13 +49,11 @@ class OperationErrorGeneratorTest { @Test fun `generates combined error enums`() { val project = TestWorkspace.testProject(symbolProvider) - project.withModule(ErrorsModule) { + project.moduleFor(model.lookup("error#FooException")) { listOf("FooException", "ComplexError", "InvalidGreeting", "Deprecated").forEach { model.lookup("error#$it").renderWithModelBuilder(model, symbolProvider, this) } - val errors = listOf("FooException", "ComplexError", "InvalidGreeting").map { model.lookup("error#$it") } - val generator = OperationErrorGenerator(model, symbolProvider, symbolProvider.toSymbol(model.lookup("error#Greeting")), errors) - generator.render(this) + OperationErrorGenerator(model, symbolProvider, model.lookup("error#Greeting")).render(this) unitTest( name = "generates_combined_error_enums", diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGeneratorTest.kt index 746927d134..d1f1cc9a57 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ServiceErrorGeneratorTest.kt @@ -8,16 +8,14 @@ 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.AttributeKind -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule 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.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.smithy.module 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 @@ -83,19 +81,16 @@ internal class ServiceErrorGeneratorTest { rustCrate.lib { Attribute.AllowDeprecated.render(this, AttributeKind.Inner) } - 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 (operation in model.operationShapes) { + if (operation.id.namespace == "com.example") { + rustCrate.withModule(symbolProvider.symbolForOperationError(operation).module()) { + OperationErrorGenerator(model, symbolProvider, operation).render(this) } } - for (shape in model.structureShapes) { - if (shape.id.namespace == "com.example") { + } + for (shape in model.structureShapes) { + if (shape.id.namespace == "com.example") { + rustCrate.moduleFor(shape) { StructureGenerator(model, symbolProvider, this, shape).render(CodegenTarget.CLIENT) } } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/InlineFunctionNamerTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/InlineFunctionNamerTest.kt index a988872b8b..1685f66a83 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/InlineFunctionNamerTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/InlineFunctionNamerTest.kt @@ -102,12 +102,12 @@ class InlineFunctionNamerTest { symbolProvider.deserializeFunctionName(testModel.lookup(shapeId)) shouldBe "deser_$suffix" } - test("test#Op1", "operation_crate_operation_op1") + test("test#Op1", "operation_crate_test_operation_op1") test("test#SomeList1", "list_test_some_list1") test("test#SomeMap1", "map_test_some_map1") test("test#SomeSet1", "set_test_some_set1") - test("test#SomeStruct1", "structure_crate_model_some_struct1") - test("test#SomeUnion1", "union_crate_model_some_union1") + test("test#SomeStruct1", "structure_crate_test_model_some_struct1") + test("test#SomeUnion1", "union_crate_test_model_some_union1") test("test#SomeStruct1\$some_string", "member_test_some_struct1_some_string") } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGeneratorTest.kt index b90543bea3..b2c5195478 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGeneratorTest.kt @@ -8,7 +8,6 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols.parse import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbolFn import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer @@ -65,20 +64,21 @@ class AwsQueryParserGeneratorTest { "#; - let output = ${format(operationParser)}(xml, output::some_operation_output::Builder::default()).unwrap().build(); + let output = ${format(operationParser)}(xml, test_output::some_operation_output::Builder::default()).unwrap().build(); assert_eq!(output.some_attribute, Some(5)); assert_eq!(output.some_val, Some("Some value".to_string())); """, ) } - - project.withModule(RustModule.public("model")) { - model.lookup("test#SomeOutput").renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#SomeOutput").also { struct -> + project.moduleFor(struct) { + struct.renderWithModelBuilder(model, symbolProvider, this) + } } - - project.withModule(RustModule.public("output")) { - model.lookup("test#SomeOperation").outputShape(model) - .renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#SomeOperation").outputShape(model).also { output -> + project.moduleFor(output) { + output.renderWithModelBuilder(model, symbolProvider, this) + } } project.compileAndTest() } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGeneratorTest.kt index 7b835d8223..2532a0ceec 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGeneratorTest.kt @@ -8,7 +8,6 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols.parse import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbolFn import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer @@ -63,20 +62,23 @@ class Ec2QueryParserGeneratorTest { Some value "#; - let output = ${format(operationParser)}(xml, output::some_operation_output::Builder::default()).unwrap().build(); + let output = ${format(operationParser)}(xml, test_output::some_operation_output::Builder::default()).unwrap().build(); assert_eq!(output.some_attribute, Some(5)); assert_eq!(output.some_val, Some("Some value".to_string())); """, ) } - project.withModule(RustModule.public("model")) { - model.lookup("test#SomeOutput").renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#SomeOutput").also { struct -> + project.moduleFor(struct) { + struct.renderWithModelBuilder(model, symbolProvider, this) + } } - project.withModule(RustModule.public("output")) { - model.lookup("test#SomeOperation").outputShape(model) - .renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#SomeOperation").outputShape(model).also { output -> + project.moduleFor(output) { + output.renderWithModelBuilder(model, symbolProvider, this) + } } project.compileAndTest() } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt index 36bb07b9a4..ceca4a75b9 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGeneratorTest.kt @@ -10,7 +10,6 @@ import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.TestEnumType import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator @@ -136,7 +135,7 @@ class JsonParserGeneratorTest { unitTest( "json_parser", """ - use model::Choice; + use test_model::Choice; // Generate the document serializer even though it's not tested directly // ${format(payloadGenerator)} @@ -151,7 +150,7 @@ class JsonParserGeneratorTest { } "#; - let output = ${format(operationGenerator!!)}(json, output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationGenerator!!)}(json, test_output::op_output::Builder::default()).unwrap().build(); let top = output.top.expect("top"); assert_eq!(Some(45), top.extra); assert_eq!(Some("something".to_string()), top.field); @@ -162,7 +161,7 @@ class JsonParserGeneratorTest { "empty_body", """ // empty body - let output = ${format(operationGenerator)}(b"", output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationGenerator)}(b"", test_output::op_output::Builder::default()).unwrap().build(); assert_eq!(output.top, None); """, ) @@ -171,7 +170,7 @@ class JsonParserGeneratorTest { """ // unknown variant let input = br#"{ "top": { "choice": { "somenewvariant": "data" } } }"#; - let output = ${format(operationGenerator)}(input, output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationGenerator)}(input, test_output::op_output::Builder::default()).unwrap().build(); assert!(output.top.unwrap().choice.unwrap().is_unknown()); """, ) @@ -180,7 +179,7 @@ class JsonParserGeneratorTest { "empty_error", """ // empty error - let error_output = ${format(errorParser!!)}(b"", error::error::Builder::default()).unwrap().build(); + let error_output = ${format(errorParser!!)}(b"", test_error::error::Builder::default()).unwrap().build(); assert_eq!(error_output.message, None); """, ) @@ -189,24 +188,29 @@ class JsonParserGeneratorTest { "error_with_message", """ // error with message - let error_output = ${format(errorParser)}(br#"{"message": "hello"}"#, error::error::Builder::default()).unwrap().build(); + let error_output = ${format(errorParser)}(br#"{"message": "hello"}"#, test_error::error::Builder::default()).unwrap().build(); assert_eq!(error_output.message.expect("message should be set"), "hello"); """, ) } - project.withModule(RustModule.public("model")) { - model.lookup("test#Top").renderWithModelBuilder(model, symbolProvider, this) - model.lookup("test#EmptyStruct").renderWithModelBuilder(model, symbolProvider, this) - UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice")).render() - val enum = model.lookup("test#FooEnum") - EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + model.lookup("test#Top").also { top -> + project.moduleFor(top) { + top.renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#EmptyStruct").renderWithModelBuilder(model, symbolProvider, this) + UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice")).render() + val enum = model.lookup("test#FooEnum") + EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + } } - - project.withModule(RustModule.public("output")) { - model.lookup("test#Op").outputShape(model).renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#Op").outputShape(model).also { output -> + project.moduleFor(output) { + output.renderWithModelBuilder(model, symbolProvider, this) + } } - project.withModule(RustModule.public("error")) { - model.lookup("test#Error").renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#Error").also { error -> + project.moduleFor(error) { + error.renderWithModelBuilder(model, symbolProvider, this) + } } project.compileAndTest() } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGeneratorTest.kt index d9ce8c5828..253a5c5916 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGeneratorTest.kt @@ -9,7 +9,8 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule +import software.amazon.smithy.model.shapes.UnionShape +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.TestEnumType @@ -102,12 +103,14 @@ internal class XmlBindingTraitParserGeneratorTest { builderSymbolFn(symbolProvider), ) { _, inner -> inner("decoder") } val operationParser = parserGenerator.operationParser(model.lookup("test#Op"))!! + + val choiceShape = model.lookup("test#Choice") val project = TestWorkspace.testProject(testSymbolProvider(model)) project.lib { - unitTest( - name = "valid_input", - test = """ - let xml = br#" + unitTest(name = "valid_input") { + rustTemplate( + """ + let xml = br##" some key @@ -118,19 +121,21 @@ internal class XmlBindingTraitParserGeneratorTest { hey - "#; - let output = ${format(operationParser)}(xml, output::op_output::Builder::default()).unwrap().build(); + "##; + let output = ${format(operationParser)}(xml, test_output::op_output::Builder::default()).unwrap().build(); let mut map = std::collections::HashMap::new(); - map.insert("some key".to_string(), model::Choice::S("hello".to_string())); - assert_eq!(output.choice, Some(model::Choice::FlatMap(map))); + map.insert("some key".to_string(), #{Choice}::S("hello".to_string())); + assert_eq!(output.choice, Some(#{Choice}::FlatMap(map))); assert_eq!(output.renamed_with_prefix.as_deref(), Some("hey")); - """, - ) - - unitTest( - name = "ignore_extras", - test = """ - let xml = br#" + """, + "Choice" to symbolProvider.toSymbol(choiceShape), + ) + } + + unitTest(name = "ignore_extras") { + rustTemplate( + """ + let xml = br##" @@ -146,13 +151,15 @@ internal class XmlBindingTraitParserGeneratorTest { - "#; - let output = ${format(operationParser)}(xml, output::op_output::Builder::default()).unwrap().build(); + "##; + let output = ${format(operationParser)}(xml, test_output::op_output::Builder::default()).unwrap().build(); let mut map = std::collections::HashMap::new(); - map.insert("some key".to_string(), model::Choice::S("hello".to_string())); - assert_eq!(output.choice, Some(model::Choice::FlatMap(map))); - """, - ) + map.insert("some key".to_string(), #{Choice}::S("hello".to_string())); + assert_eq!(output.choice, Some(#{Choice}::FlatMap(map))); + """, + "Choice" to symbolProvider.toSymbol(choiceShape), + ) + } unitTest( name = "nopanics_on_invalid", @@ -174,7 +181,7 @@ internal class XmlBindingTraitParserGeneratorTest { "#; - ${format(operationParser)}(xml, output::op_output::Builder::default()).expect("unknown union variant does not cause failure"); + ${format(operationParser)}(xml, test_output::op_output::Builder::default()).expect("unknown union variant does not cause failure"); """, ) unitTest( @@ -191,20 +198,26 @@ internal class XmlBindingTraitParserGeneratorTest { "#; - let output = ${format(operationParser)}(xml, output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationParser)}(xml, test_output::op_output::Builder::default()).unwrap().build(); assert!(output.choice.unwrap().is_unknown()); """, ) } - project.withModule(RustModule.public("model")) { - model.lookup("test#Top").renderWithModelBuilder(model, symbolProvider, this) - UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice")).render() - val enum = model.lookup("test#FooEnum") - EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + model.lookup("test#Top").also { top -> + project.moduleFor(top) { + top.renderWithModelBuilder(model, symbolProvider, this) + + UnionGenerator(model, symbolProvider, this, choiceShape).render() + model.lookup("test#FooEnum").also { enum -> + EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + } + } } - project.withModule(RustModule.public("output")) { - model.lookup("test#Op").outputShape(model).renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#Op").outputShape(model).also { out -> + project.moduleFor(out) { + out.renderWithModelBuilder(model, symbolProvider, this) + } } project.compileAndTest() } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/AwsQuerySerializerGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/AwsQuerySerializerGeneratorTest.kt index fe8160504a..963383b67c 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/AwsQuerySerializerGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/AwsQuerySerializerGeneratorTest.kt @@ -10,7 +10,6 @@ import org.junit.jupiter.params.provider.CsvSource import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.TestEnumType @@ -104,9 +103,9 @@ class AwsQuerySerializerGeneratorTest { unitTest( "query_serializer", """ - use model::Top; + use test_model::Top; - let input = crate::input::OpInput::builder() + let input = crate::test_input::OpInput::builder() .top( Top::builder() .field("hello!") @@ -133,15 +132,25 @@ class AwsQuerySerializerGeneratorTest { """, ) } - project.withModule(RustModule.public("model")) { - model.lookup("test#Top").renderWithModelBuilder(model, symbolProvider, this) - UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice"), renderUnknownVariant = generateUnknownVariant).render() - val enum = model.lookup("test#FooEnum") - EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + model.lookup("test#Top").also { top -> + project.moduleFor(top) { + top.renderWithModelBuilder(model, symbolProvider, this) + UnionGenerator( + model, + symbolProvider, + this, + model.lookup("test#Choice"), + renderUnknownVariant = generateUnknownVariant, + ).render() + val enum = model.lookup("test#FooEnum") + EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + } } - project.withModule(RustModule.public("input")) { - model.lookup("test#Op").inputShape(model).renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#Op").inputShape(model).also { input -> + project.moduleFor(input) { + input.renderWithModelBuilder(model, symbolProvider, this) + } } project.compileAndTest() } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/Ec2QuerySerializerGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/Ec2QuerySerializerGeneratorTest.kt index 67ebaff51f..9d784b9a2b 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/Ec2QuerySerializerGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/Ec2QuerySerializerGeneratorTest.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.TestEnumType import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator @@ -97,9 +96,9 @@ class Ec2QuerySerializerGeneratorTest { unitTest( "ec2query_serializer", """ - use model::Top; + use test_model::Top; - let input = crate::input::OpInput::builder() + let input = crate::test_input::OpInput::builder() .top( Top::builder() .field("hello!") @@ -126,15 +125,19 @@ class Ec2QuerySerializerGeneratorTest { """, ) } - project.withModule(RustModule.public("model")) { - model.lookup("test#Top").renderWithModelBuilder(model, symbolProvider, this) - UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice")).render() - val enum = model.lookup("test#FooEnum") - EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + model.lookup("test#Top").also { top -> + project.moduleFor(top) { + top.renderWithModelBuilder(model, symbolProvider, this) + UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice")).render() + val enum = model.lookup("test#FooEnum") + EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + } } - project.withModule(RustModule.public("input")) { - model.lookup("test#Op").inputShape(model).renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#Op").inputShape(model).also { input -> + project.moduleFor(input) { + input.renderWithModelBuilder(model, symbolProvider, this) + } } project.compileAndTest() } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/JsonSerializerGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/JsonSerializerGeneratorTest.kt index 5aea8c4c8a..c56385057b 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/JsonSerializerGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/JsonSerializerGeneratorTest.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.TestEnumType import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator @@ -117,12 +116,12 @@ class JsonSerializerGeneratorTest { unitTest( "json_serializers", """ - use model::{Top, Choice}; + use test_model::{Top, Choice}; // Generate the document serializer even though it's not tested directly // ${format(documentGenerator)} - let input = crate::input::OpInput::builder().top( + let input = crate::test_input::OpInput::builder().top( Top::builder() .field("hello!") .extra(45) @@ -133,7 +132,7 @@ class JsonSerializerGeneratorTest { let output = std::str::from_utf8(serialized.bytes().unwrap()).unwrap(); assert_eq!(output, r#"{"top":{"field":"hello!","extra":45,"rec":[{"extra":55}]}}"#); - let input = crate::input::OpInput::builder().top( + let input = crate::test_input::OpInput::builder().top( Top::builder() .choice(Choice::Unknown) .build() @@ -142,15 +141,19 @@ class JsonSerializerGeneratorTest { """, ) } - project.withModule(RustModule.public("model")) { - model.lookup("test#Top").renderWithModelBuilder(model, symbolProvider, this) - UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice")).render() - val enum = model.lookup("test#FooEnum") - EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + model.lookup("test#Top").also { top -> + project.moduleFor(top) { + top.renderWithModelBuilder(model, symbolProvider, this) + UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice")).render() + val enum = model.lookup("test#FooEnum") + EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + } } - project.withModule(RustModule.public("input")) { - model.lookup("test#Op").inputShape(model).renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#Op").inputShape(model).also { input -> + project.moduleFor(input) { + input.renderWithModelBuilder(model, symbolProvider, this) + } } project.compileAndTest() } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/XmlBindingTraitSerializerGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/XmlBindingTraitSerializerGeneratorTest.kt index b2040b8527..e753b9e166 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/XmlBindingTraitSerializerGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/XmlBindingTraitSerializerGeneratorTest.kt @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.TestEnumType import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator @@ -120,8 +119,8 @@ internal class XmlBindingTraitSerializerGeneratorTest { unitTest( "serialize_xml", """ - use model::Top; - let inp = crate::input::OpInput::builder().payload( + use test_model::Top; + let inp = crate::test_input::OpInput::builder().payload( Top::builder() .field("hello!") .extra(45) @@ -136,8 +135,8 @@ internal class XmlBindingTraitSerializerGeneratorTest { unitTest( "unknown_variants", """ - use model::{Top, Choice}; - let input = crate::input::OpInput::builder().payload( + use test_model::{Top, Choice}; + let input = crate::test_input::OpInput::builder().payload( Top::builder() .choice(Choice::Unknown) .build() @@ -146,15 +145,18 @@ internal class XmlBindingTraitSerializerGeneratorTest { """, ) } - project.withModule(RustModule.public("model")) { - model.lookup("test#Top").renderWithModelBuilder(model, symbolProvider, this) - UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice")).render() - val enum = model.lookup("test#FooEnum") - EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + model.lookup("test#Top").also { top -> + project.moduleFor(top) { + top.renderWithModelBuilder(model, symbolProvider, this) + UnionGenerator(model, symbolProvider, this, model.lookup("test#Choice")).render() + val enum = model.lookup("test#FooEnum") + EnumGenerator(model, symbolProvider, enum, TestEnumType).render(this) + } } - - project.withModule(RustModule.public("input")) { - model.lookup("test#Op").inputShape(model).renderWithModelBuilder(model, symbolProvider, this) + model.lookup("test#Op").inputShape(model).also { input -> + project.moduleFor(input) { + input.renderWithModelBuilder(model, symbolProvider, this) + } } project.compileAndTest() } diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/transformers/RecursiveShapesIntegrationTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/transformers/RecursiveShapesIntegrationTest.kt index bea21fd083..3bb485ebd1 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/transformers/RecursiveShapesIntegrationTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/transformers/RecursiveShapesIntegrationTest.kt @@ -10,9 +10,10 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter +import software.amazon.smithy.model.shapes.UnionShape 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.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.testSymbolProvider @@ -42,23 +43,30 @@ class RecursiveShapesIntegrationTest { third: SecondTree } """.asSmithyModel() + val check = { input: Model -> + val symbolProvider = testSymbolProvider(model) + val project = TestWorkspace.testProject(symbolProvider) val structures = listOf("Expr", "SecondTree").map { input.lookup("com.example#$it") } - val writer = RustWriter.forModule("model") - val symbolProvider = testSymbolProvider(input) - structures.forEach { - StructureGenerator(input, symbolProvider, writer, it).render() + structures.forEach { struct -> + project.moduleFor(struct) { + StructureGenerator(input, symbolProvider, this, struct).render() + } + } + input.lookup("com.example#Atom").also { atom -> + project.moduleFor(atom) { + UnionGenerator(input, symbolProvider, this, atom).render() + } } - UnionGenerator(input, symbolProvider, writer, input.lookup("com.example#Atom")).render() - writer + project } - val unmodifiedWriter = check(model) + val unmodifiedProject = check(model) val output = assertThrows { - unmodifiedWriter.compileAndTest(expectFailure = true) + unmodifiedProject.compileAndTest(expectFailure = true) } output.message shouldContain "has infinite size" - val fixedWriter = check(RecursiveShapeBoxer.transform(model)) - fixedWriter.compileAndTest() + val fixedProject = check(RecursiveShapeBoxer.transform(model)) + fixedProject.compileAndTest() } } 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 27442578af..48e7082cc7 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 @@ -26,6 +26,7 @@ import software.amazon.smithy.rust.codegen.server.python.smithy.generators.Pytho import software.amazon.smithy.rust.codegen.server.python.smithy.generators.PythonServerStructureGenerator import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenVisitor +import software.amazon.smithy.rust.codegen.server.smithy.ServerModuleProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerSymbolProviders import software.amazon.smithy.rust.codegen.server.smithy.customize.ServerCodegenDecorator import software.amazon.smithy.rust.codegen.server.smithy.generators.protocol.ServerProtocol @@ -49,6 +50,7 @@ class PythonServerCodegenVisitor( runtimeConfig = settings.runtimeConfig, renameExceptions = false, nullabilityCheckMode = NullableIndex.CheckMode.SERVER, + moduleProvider = ServerModuleProvider, ) val baseModel = baselineTransform(context.model) val service = settings.getService(baseModel) diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonApplicationGenerator.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonApplicationGenerator.kt index dfddfe9b8a..f52b8fc760 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonApplicationGenerator.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonApplicationGenerator.kt @@ -12,9 +12,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust 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.ErrorsModule -import software.amazon.smithy.rust.codegen.core.smithy.InputsModule -import software.amazon.smithy.rust.codegen.core.smithy.OutputsModule import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.util.getTrait import software.amazon.smithy.rust.codegen.core.util.inputShape @@ -26,6 +23,9 @@ import software.amazon.smithy.rust.codegen.server.python.smithy.PythonType import software.amazon.smithy.rust.codegen.server.python.smithy.renderAsDocstring import software.amazon.smithy.rust.codegen.server.smithy.ServerCargoDependency import software.amazon.smithy.rust.codegen.server.smithy.generators.protocol.ServerProtocol +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Error as ErrorModule +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Input as InputModule +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Output as OutputModule /** * Generates a Python compatible application and server that can be configured from Python. @@ -390,12 +390,12 @@ class PythonApplicationGenerator( ) writer.rust( """ - /// from $libName import ${InputsModule.name} - /// from $libName import ${OutputsModule.name} + /// from $libName import ${InputModule.name} + /// from $libName import ${OutputModule.name} """.trimIndent(), ) if (operations.any { it.errors.isNotEmpty() }) { - writer.rust("""/// from $libName import ${ErrorsModule.name}""".trimIndent()) + writer.rust("""/// from $libName import ${ErrorModule.name}""".trimIndent()) } writer.rust( """ @@ -449,8 +449,8 @@ class PythonApplicationGenerator( private fun OperationShape.signature(): String { val inputSymbol = symbolProvider.toSymbol(inputShape(model)) val outputSymbol = symbolProvider.toSymbol(outputShape(model)) - val inputT = "${InputsModule.name}::${inputSymbol.name}" - val outputT = "${OutputsModule.name}::${outputSymbol.name}" + val inputT = "${InputModule.name}::${inputSymbol.name}" + val outputT = "${OutputModule.name}::${outputSymbol.name}" val operationName = symbolProvider.toSymbol(this).name.toSnakeCase() return "@app.$operationName\n/// def $operationName(input: $inputT, ctx: Context) -> $outputT" } diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerOperationErrorGenerator.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerOperationErrorGenerator.kt index 65e53adb6c..e2f66a8368 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerOperationErrorGenerator.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerOperationErrorGenerator.kt @@ -15,7 +15,6 @@ 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.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider -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 @@ -27,13 +26,11 @@ class PythonServerOperationErrorGenerator( private val model: Model, private val symbolProvider: RustSymbolProvider, private val operation: OperationShape, -) : ServerOperationErrorGenerator(model, symbolProvider, symbolProvider.toSymbol(operation), listOf()) { - +) { private val operationIndex = OperationIndex.of(model) private val errors = operationIndex.getErrors(operation) - override fun render(writer: RustWriter) { - super.render(writer) + fun render(writer: RustWriter) { renderFromPyErr(writer) } @@ -52,7 +49,7 @@ class PythonServerOperationErrorGenerator( """, "pyo3" to PythonServerCargoDependency.PyO3.toType(), - "Error" to operation.errorSymbol(symbolProvider), + "Error" to symbolProvider.symbolForOperationError(operation), "From" to RuntimeType.From, "CastPyErrToRustError" to castPyErrToRustError(), ) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt index 5d37c465a0..a2e1fdb709 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt @@ -21,7 +21,6 @@ import software.amazon.smithy.model.shapes.ShortShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.traits.LengthTrait import software.amazon.smithy.rust.codegen.core.rustlang.RustType -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.contextName @@ -64,7 +63,7 @@ class ConstrainedShapeSymbolProvider( check(shape is MapShape || shape is CollectionShape) val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) - return symbolBuilder(shape, rustType).locatedIn(ModelsModule).build() + return symbolBuilder(shape, rustType).locatedIn(ServerRustModule.Model).build() } override fun toSymbol(shape: Shape): Symbol { @@ -107,7 +106,7 @@ class ConstrainedShapeSymbolProvider( is StringShape, is IntegerShape, is ShortShape, is LongShape, is ByteShape, is BlobShape -> { if (shape.isDirectlyConstrained(base)) { val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) - symbolBuilder(shape, rustType).locatedIn(ModelsModule).build() + symbolBuilder(shape, rustType).locatedIn(ServerRustModule.Model).build() } else { base.toSymbol(shape) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt index 845150c5cc..12d838db54 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt @@ -23,7 +23,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWords import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.Visibility -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.contextName @@ -88,7 +87,7 @@ class ConstraintViolationSymbolProvider( // Need to use the context name so we get the correct name for maps. name = RustReservedWords.escapeIfNeeded(this.contextName(serviceShape)).toSnakeCase(), visibility = visibility, - parent = ModelsModule, + parent = ServerRustModule.Model, inline = true, documentation = documentation, ) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/PubCrateConstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/PubCrateConstrainedShapeSymbolProvider.kt index 800dc6c730..59697a481e 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/PubCrateConstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/PubCrateConstrainedShapeSymbolProvider.kt @@ -20,7 +20,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustModule import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWords import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.Visibility -import software.amazon.smithy.rust.codegen.core.smithy.ConstrainedModule import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.handleOptionality @@ -74,7 +73,7 @@ class PubCrateConstrainedShapeSymbolProvider( val module = RustModule.new( RustReservedWords.escapeIfNeeded(name.toSnakeCase()), visibility = Visibility.PUBCRATE, - parent = ConstrainedModule, + parent = ServerRustModule.ConstrainedModule, inline = true, ) val rustType = RustType.Opaque(name, module.fullyQualifiedPath()) 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 a5a13820e9..728dd3728d 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 @@ -29,27 +29,20 @@ 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 import software.amazon.smithy.rust.codegen.core.smithy.CoreRustSettings import software.amazon.smithy.rust.codegen.core.smithy.DirectedWalker -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.smithy.RustCrate 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.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.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.hasEventStreamMember import software.amazon.smithy.rust.codegen.core.util.hasTrait @@ -107,12 +100,12 @@ open class ServerCodegenVisitor( protected var validationExceptionConversionGenerator: ValidationExceptionConversionGenerator init { - val symbolVisitorConfig = - SymbolVisitorConfig( - runtimeConfig = settings.runtimeConfig, - renameExceptions = false, - nullabilityCheckMode = NullableIndex.CheckMode.SERVER, - ) + val symbolVisitorConfig = SymbolVisitorConfig( + runtimeConfig = settings.runtimeConfig, + renameExceptions = false, + nullabilityCheckMode = NullableIndex.CheckMode.SERVER, + moduleProvider = ServerModuleProvider, + ) val baseModel = baselineTransform(context.model) val service = settings.getService(baseModel) @@ -312,7 +305,7 @@ open class ServerCodegenVisitor( if (renderUnconstrainedList) { logger.info("[rust-server-codegen] Generating an unconstrained type for collection shape $shape") - rustCrate.withModule(UnconstrainedModule) { + rustCrate.withModule(ServerRustModule.UnconstrainedModule) { UnconstrainedCollectionGenerator( codegenContext, this, @@ -322,7 +315,7 @@ open class ServerCodegenVisitor( if (!isDirectlyConstrained) { logger.info("[rust-server-codegen] Generating a constrained type for collection shape $shape") - rustCrate.withModule(ConstrainedModule) { + rustCrate.withModule(ServerRustModule.ConstrainedModule) { PubCrateConstrainedCollectionGenerator(codegenContext, this, shape).render() } } @@ -330,7 +323,7 @@ open class ServerCodegenVisitor( val constraintsInfo = CollectionTraitInfo.fromShape(shape, codegenContext.constrainedShapeSymbolProvider) if (isDirectlyConstrained) { - rustCrate.withModule(ModelsModule) { + rustCrate.withModule(ServerRustModule.Model) { ConstrainedCollectionGenerator( codegenContext, this, @@ -342,7 +335,7 @@ open class ServerCodegenVisitor( } if (isDirectlyConstrained || renderUnconstrainedList) { - rustCrate.withModule(ModelsModule) { + rustCrate.withModule(ServerRustModule.Model) { CollectionConstraintViolationGenerator( codegenContext, this, @@ -364,20 +357,20 @@ open class ServerCodegenVisitor( if (renderUnconstrainedMap) { logger.info("[rust-server-codegen] Generating an unconstrained type for map $shape") - rustCrate.withModule(UnconstrainedModule) { + rustCrate.withModule(ServerRustModule.UnconstrainedModule) { UnconstrainedMapGenerator(codegenContext, this, shape).render() } if (!isDirectlyConstrained) { logger.info("[rust-server-codegen] Generating a constrained type for map $shape") - rustCrate.withModule(ConstrainedModule) { + rustCrate.withModule(ServerRustModule.ConstrainedModule) { PubCrateConstrainedMapGenerator(codegenContext, this, shape).render() } } } if (isDirectlyConstrained) { - rustCrate.withModule(ModelsModule) { + rustCrate.withModule(ServerRustModule.Model) { ConstrainedMapGenerator( codegenContext, this, @@ -388,7 +381,7 @@ open class ServerCodegenVisitor( } if (isDirectlyConstrained || renderUnconstrainedMap) { - rustCrate.withModule(ModelsModule) { + rustCrate.withModule(ServerRustModule.Model) { MapConstraintViolationGenerator( codegenContext, this, @@ -417,7 +410,7 @@ open class ServerCodegenVisitor( private fun integralShape(shape: NumberShape) { if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained integral $shape") - rustCrate.withModule(ModelsModule) { + rustCrate.withModule(ServerRustModule.Model) { ConstrainedNumberGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() } } @@ -446,7 +439,7 @@ open class ServerCodegenVisitor( ) } else if (!shape.hasTrait() && shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained string $shape") - rustCrate.withModule(ModelsModule) { + rustCrate.withModule(ServerRustModule.Model) { ConstrainedStringGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() } } @@ -471,8 +464,8 @@ open class ServerCodegenVisitor( ) ) { logger.info("[rust-server-codegen] Generating an unconstrained type for union shape $shape") - rustCrate.withModule(UnconstrainedModule) unconstrainedModuleWriter@{ - rustCrate.withModule(ModelsModule) modelsModuleWriter@{ + rustCrate.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ + rustCrate.withModule(ServerRustModule.Model) modelsModuleWriter@{ UnconstrainedUnionGenerator( codegenContext, this@unconstrainedModuleWriter, @@ -484,15 +477,8 @@ open class ServerCodegenVisitor( } if (shape.isEventStream()) { - val errors = shape.eventStreamErrors() - .map { model.expectShape(it.asMemberShape().get().target, StructureShape::class.java) } - if (errors.isNotEmpty()) { - rustCrate.withModule(RustModule.Error) { - val symbol = codegenContext.symbolProvider.toSymbol(shape) - val errorSymbol = shape.eventStreamErrorSymbol(codegenContext.symbolProvider) - ServerOperationErrorGenerator(model, codegenContext.symbolProvider, symbol, errors) - .renderErrors(this, errorSymbol, symbol) - } + rustCrate.withModule(ServerRustModule.Error) { + ServerOperationErrorGenerator(model, codegenContext.symbolProvider, shape).render(this) } } } @@ -522,14 +508,8 @@ open class ServerCodegenVisitor( * 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) + rustCrate.withModule(ServerRustModule.Error) { + ServerOperationErrorGenerator(model, codegenContext.symbolProvider, shape).render(this) } } @@ -540,7 +520,7 @@ open class ServerCodegenVisitor( } if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { - rustCrate.withModule(ModelsModule) { + rustCrate.withModule(ServerRustModule.Model) { ConstrainedBlobGenerator(codegenContext, this, shape, validationExceptionConversionGenerator).render() } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerRustModule.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerRustModule.kt new file mode 100644 index 0000000000..674b2eaea2 --- /dev/null +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerRustModule.kt @@ -0,0 +1,50 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.server.smithy + +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.shapes.StructureShape +import software.amazon.smithy.model.shapes.UnionShape +import software.amazon.smithy.model.traits.ErrorTrait +import software.amazon.smithy.rust.codegen.core.rustlang.RustModule +import software.amazon.smithy.rust.codegen.core.smithy.ModuleProvider +import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait +import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticOutputTrait +import software.amazon.smithy.rust.codegen.core.util.hasTrait + +object ServerRustModule { + val Error = RustModule.public("error", documentation = "All error types that operations can return. Documentation on these types is copied from the model.") + val Operation = RustModule.public("operation", documentation = "All operations that this crate can perform.") + val Model = RustModule.public("model", documentation = "Data structures used by operation inputs/outputs. Documentation on these types is copied from the model.") + val Input = RustModule.public("input", documentation = "Input structures for operations. Documentation on these types is copied from the model.") + val Output = RustModule.public("output", documentation = "Output structures for operations. Documentation on these types is copied from the model.") + val Types = RustModule.public("types", documentation = "Data primitives referenced by other data types.") + + val UnconstrainedModule = + software.amazon.smithy.rust.codegen.core.smithy.UnconstrainedModule + val ConstrainedModule = + software.amazon.smithy.rust.codegen.core.smithy.ConstrainedModule +} + +object ServerModuleProvider : ModuleProvider { + override fun moduleForShape(shape: Shape): RustModule.LeafModule = when (shape) { + is OperationShape -> ServerRustModule.Operation + is StructureShape -> when { + shape.hasTrait() -> ServerRustModule.Error + shape.hasTrait() -> ServerRustModule.Input + shape.hasTrait() -> ServerRustModule.Output + else -> ServerRustModule.Model + } + else -> ServerRustModule.Model + } + + override fun moduleForOperationError(operation: OperationShape): RustModule.LeafModule = + ServerRustModule.Error + + override fun moduleForEventStreamError(eventStream: UnionShape): RustModule.LeafModule = + ServerRustModule.Error +} diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt index 3da3129387..a134bbb9e9 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnconstrainedShapeSymbolProvider.kt @@ -22,7 +22,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.smithy.Default import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider -import software.amazon.smithy.rust.codegen.core.smithy.UnconstrainedModule import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.contextName import software.amazon.smithy.rust.codegen.core.smithy.handleOptionality @@ -104,7 +103,7 @@ class UnconstrainedShapeSymbolProvider( val module = RustModule.new( RustReservedWords.escapeIfNeeded(name.toSnakeCase()), visibility = Visibility.PUBCRATE, - parent = UnconstrainedModule, + parent = ServerRustModule.UnconstrainedModule, inline = true, ) val rustType = RustType.Opaque(name, module.fullyQualifiedPath()) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/ServerRequiredCustomizations.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/ServerRequiredCustomizations.kt index 90b3550b98..d7f06864bf 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/ServerRequiredCustomizations.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/ServerRequiredCustomizations.kt @@ -12,6 +12,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.customizations.CrateVersi import software.amazon.smithy.rust.codegen.core.smithy.customizations.pubUseSmithyTypes import software.amazon.smithy.rust.codegen.core.smithy.generators.LibRsCustomization import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customize.ServerCodegenDecorator /** @@ -35,6 +36,8 @@ class ServerRequiredCustomizations : ServerCodegenDecorator { // Add rt-tokio feature for `ByteStream::from_path` rustCrate.mergeFeature(Feature("rt-tokio", true, listOf("aws-smithy-http/rt-tokio"))) - pubUseSmithyTypes(codegenContext.runtimeConfig, codegenContext.model, rustCrate) + rustCrate.withModule(ServerRustModule.Types) { + pubUseSmithyTypes(codegenContext.runtimeConfig, codegenContext.model)(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 759f887088..a0dcf07ba9 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,12 +12,11 @@ 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.ErrorsModule -import software.amazon.smithy.rust.codegen.core.smithy.InputsModule -import software.amazon.smithy.rust.codegen.core.smithy.OutputsModule -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.errorSymbol import software.amazon.smithy.rust.codegen.core.util.inputShape import software.amazon.smithy.rust.codegen.core.util.outputShape +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Error as ErrorModule +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Input as InputModule +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Output as OutputModule /** * Generates a handler implementation stub for use within documentation. @@ -33,22 +32,22 @@ class DocHandlerGenerator( private val inputSymbol = symbolProvider.toSymbol(operation.inputShape(model)) private val outputSymbol = symbolProvider.toSymbol(operation.outputShape(model)) - private val errorSymbol = operation.errorSymbol(symbolProvider) + private val errorSymbol = symbolProvider.symbolForOperationError(operation) /** * Returns the function signature for an operation handler implementation. Used in the documentation. */ fun docSignature(): Writable { val outputT = if (operation.errors.isEmpty()) { - "${OutputsModule.name}::${outputSymbol.name}" + "${OutputModule.name}::${outputSymbol.name}" } else { - "Result<${OutputsModule.name}::${outputSymbol.name}, ${ErrorsModule.name}::${errorSymbol.name}>" + "Result<${OutputModule.name}::${outputSymbol.name}, ${ErrorModule.name}::${errorSymbol.name}>" } return writable { rust( """ - $commentToken async fn $handlerName(input: ${InputsModule.name}::${inputSymbol.name}) -> $outputT { + $commentToken async fn $handlerName(input: ${InputModule.name}::${inputSymbol.name}) -> $outputT { $commentToken todo!() $commentToken } """.trimIndent(), diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGenerator.kt index 44048276d8..68e80f7acb 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGenerator.kt @@ -7,7 +7,10 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators 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.Shape import software.amazon.smithy.model.shapes.StructureShape +import software.amazon.smithy.model.shapes.UnionShape import software.amazon.smithy.rust.codegen.core.rustlang.RustMetadata import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Visibility @@ -18,6 +21,9 @@ 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.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider +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.UNREACHABLE import software.amazon.smithy.rust.codegen.core.util.toSnakeCase /** @@ -27,28 +33,32 @@ import software.amazon.smithy.rust.codegen.core.util.toSnakeCase open class ServerOperationErrorGenerator( private val model: Model, private val symbolProvider: RustSymbolProvider, - private val operationSymbol: Symbol, - private val errors: List, + private val operationOrEventStream: Shape, ) { - open fun render(writer: RustWriter) { - val symbol = RuntimeType("crate::error::${operationSymbol.name}Error") - if (errors.isNotEmpty()) { - renderErrors(writer, symbol, operationSymbol) - } - } + private val symbol = symbolProvider.toSymbol(operationOrEventStream) - fun renderErrors( - writer: RustWriter, - errorSymbol: RuntimeType, - operationSymbol: Symbol, - ) { + private fun operationErrors(): List = + (operationOrEventStream as OperationShape).operationErrors(model).map { it.asStructureShape().get() } + private fun eventStreamErrors(): List = + (operationOrEventStream as UnionShape).eventStreamErrors() + .map { model.expectShape(it.asMemberShape().get().target, StructureShape::class.java) } + + fun render(writer: RustWriter) { + val (errorSymbol, errors) = when (operationOrEventStream) { + is OperationShape -> symbolProvider.symbolForOperationError(operationOrEventStream) to operationErrors() + is UnionShape -> symbolProvider.symbolForEventStreamError(operationOrEventStream) to eventStreamErrors() + else -> UNREACHABLE("OperationErrorGenerator only supports operation or event stream shapes") + } + if (errors.isEmpty()) { + return + } val meta = RustMetadata( derives = setOf(RuntimeType.Debug), visibility = Visibility.PUBLIC, ) - writer.rust("/// Error type for the `${operationSymbol.name}` operation.") - writer.rust("/// Each variant represents an error that can occur for the `${operationSymbol.name}` operation.") + writer.rust("/// Error type for the `${symbol.name}` operation.") + writer.rust("/// Each variant represents an error that can occur for the `${symbol.name}` operation.") meta.render(writer) writer.rustBlock("enum ${errorSymbol.name}") { errors.forEach { errorVariant -> @@ -120,7 +130,7 @@ open class ServerOperationErrorGenerator( */ private fun RustWriter.delegateToVariants( errors: List, - symbol: RuntimeType, + symbol: Symbol, writable: Writable, ) { rustBlock("match &self") { diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGenerator.kt index cf405dc5e9..baf10e8b4b 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGenerator.kt @@ -15,9 +15,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.join 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.smithy.ErrorsModule -import software.amazon.smithy.rust.codegen.core.smithy.InputsModule -import software.amazon.smithy.rust.codegen.core.smithy.OutputsModule import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolSupport import software.amazon.smithy.rust.codegen.core.util.toSnakeCase @@ -26,6 +23,9 @@ import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.generators.protocol.ServerProtocol import software.amazon.smithy.rust.codegen.server.smithy.generators.protocol.ServerProtocolGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.protocol.ServerProtocolTestGenerator +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Error as ErrorModule +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Input as InputModule +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Output as OutputModule /** * ServerServiceGenerator @@ -68,7 +68,7 @@ open class ServerServiceGenerator( //! //! The primary entrypoint is [`$serviceName`]: it satisfies the [`Service`](#{Tower}::Service) //! trait and therefore can be handed to a [`hyper` server](https://github.com/hyperium/hyper) via [`$serviceName::into_make_service`] or used in Lambda via [`LambdaHandler`](#{SmithyHttpServer}::routing::LambdaHandler). - //! The [`crate::${InputsModule.name}`], ${if (!hasErrors) "and " else ""}[`crate::${OutputsModule.name}`], ${if (hasErrors) "and [`crate::${ErrorsModule.name}`]" else "" } + //! The [`crate::${InputModule.name}`], ${if (!hasErrors) "and " else ""}[`crate::${OutputModule.name}`], ${if (hasErrors) "and [`crate::${ErrorModule.name}`]" else "" } //! modules provide the types used in each operation. //! //! ###### Running on Hyper @@ -248,7 +248,7 @@ open class ServerServiceGenerator( for (operation in operations) { if (operation.errors.isNotEmpty()) { - rustCrate.withModule(RustModule.Error) { + rustCrate.withModule(ErrorModule) { renderCombinedErrors(this, operation) } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt index e8483f4a20..3b7d09c3ce 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt @@ -18,9 +18,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.join 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.ErrorsModule -import software.amazon.smithy.rust.codegen.core.smithy.InputsModule -import software.amazon.smithy.rust.codegen.core.smithy.OutputsModule import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf @@ -29,6 +26,9 @@ import software.amazon.smithy.rust.codegen.core.util.toSnakeCase import software.amazon.smithy.rust.codegen.server.smithy.ServerCargoDependency import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.generators.protocol.ServerProtocol +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Error as ErrorModule +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Input as InputModule +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Output as OutputModule class ServerServiceGeneratorV2( private val codegenContext: ServerCodegenContext, @@ -540,8 +540,8 @@ class ServerServiceGeneratorV2( */ fun handlerImports(crateName: String, operations: Collection, commentToken: String = "///") = writable { val hasErrors = operations.any { it.errors.isNotEmpty() } - val errorImport = if (hasErrors) ", ${ErrorsModule.name}" else "" + val errorImport = if (hasErrors) ", ${ErrorModule.name}" else "" if (operations.isNotEmpty()) { - rust("$commentToken use $crateName::{${InputsModule.name}, ${OutputsModule.name}$errorImport};") + rust("$commentToken use $crateName::{${InputModule.name}, ${OutputModule.name}$errorImport};") } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerRequestBindingGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerRequestBindingGenerator.kt index b01c2f633e..d12813cf19 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerRequestBindingGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerRequestBindingGenerator.kt @@ -54,11 +54,11 @@ class ServerRequestBindingGenerator( fun generateDeserializePayloadFn( binding: HttpBindingDescriptor, - errorT: RuntimeType, + errorSymbol: Symbol, structuredHandler: RustWriter.(String) -> Unit, ): RuntimeType = httpBindingGenerator.generateDeserializePayloadFn( binding, - errorT, + errorSymbol, structuredHandler, HttpMessageType.REQUEST, ) 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 ffa5fb424f..50721990b4 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 @@ -44,7 +44,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable 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 -import software.amazon.smithy.rust.codegen.core.smithy.generators.error.errorSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.http.HttpMessageType import software.amazon.smithy.rust.codegen.core.smithy.generators.protocol.ProtocolTraitImplGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName @@ -254,7 +253,7 @@ private class ServerHttpBoundProtocolTraitImplGenerator( ) // Implement `into_response` for output types. - val errorSymbol = operationShape.errorSymbol(symbolProvider) + val errorSymbol = symbolProvider.symbolForOperationError(operationShape) rustTemplate( """ @@ -366,7 +365,7 @@ private class ServerHttpBoundProtocolTraitImplGenerator( private fun serverSerializeError(operationShape: OperationShape): RuntimeType { val fnName = "serialize_${operationShape.id.name.toSnakeCase()}_error" - val errorSymbol = operationShape.errorSymbol(symbolProvider) + val errorSymbol = symbolProvider.symbolForOperationError(operationShape) return RuntimeType.forInlineFun(fnName, operationSerModule) { Attribute.AllowClippyUnnecessaryWraps.render(this) rustBlockTemplate( @@ -386,7 +385,7 @@ private class ServerHttpBoundProtocolTraitImplGenerator( private fun RustWriter.serverRenderErrorShapeResponseSerializer( operationShape: OperationShape, - errorSymbol: RuntimeType, + errorSymbol: Symbol, ) { val operationName = symbolProvider.toSymbol(operationShape).name val structuredDataSerializer = protocol.structuredDataSerializer(operationShape) @@ -1154,18 +1153,18 @@ private class ServerHttpBoundProtocolTraitImplGenerator( * Returns the error type of the function that deserializes a non-streaming HTTP payload (a byte slab) into the * shape targeted by the `httpPayload` trait. */ - private fun getDeserializePayloadErrorSymbol(binding: HttpBindingDescriptor): RuntimeType { + private fun getDeserializePayloadErrorSymbol(binding: HttpBindingDescriptor): Symbol { check(binding.location == HttpLocation.PAYLOAD) if (model.expectShape(binding.member.target) is StringShape) { - return ServerRuntimeType.requestRejection(runtimeConfig) + return ServerRuntimeType.requestRejection(runtimeConfig).toSymbol() } return when (codegenContext.protocol) { RestJson1Trait.ID, AwsJson1_0Trait.ID, AwsJson1_1Trait.ID -> { - RuntimeType.smithyJson(runtimeConfig).resolve("deserialize::error::DeserializeError") + RuntimeType.smithyJson(runtimeConfig).resolve("deserialize::error::DeserializeError").toSymbol() } RestXmlTrait.ID -> { - RuntimeType.smithyXml(runtimeConfig).resolve("decode::XmlDecodeError") + RuntimeType.smithyXml(runtimeConfig).resolve("decode::XmlDecodeError").toSymbol() } else -> { TODO("Protocol ${codegenContext.protocol} not supported yet") 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 e1e4f3bd52..0b1660b010 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 @@ -22,6 +22,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.TestRuntimeConfig import software.amazon.smithy.rust.codegen.server.smithy.RustServerCodegenPlugin 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.ServerModuleProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerRustSettings import software.amazon.smithy.rust.codegen.server.smithy.ServerSymbolProviders import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator @@ -32,6 +33,7 @@ val ServerTestSymbolVisitorConfig = SymbolVisitorConfig( runtimeConfig = TestRuntimeConfig, renameExceptions = false, nullabilityCheckMode = NullableIndex.CheckMode.SERVER, + moduleProvider = ServerModuleProvider, ) private fun testServiceShapeFor(model: Model) = diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt index 52d9008ebf..0cabbac74d 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGeneratorTest.kt @@ -15,7 +15,6 @@ import org.junit.jupiter.params.provider.ArgumentsSource import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.BlobShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel @@ -23,6 +22,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import java.util.stream.Stream @@ -67,7 +67,7 @@ class ConstrainedBlobGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { addDependency(RuntimeType.blob(codegenContext.runtimeConfig).toSymbol()) ConstrainedBlobGenerator( codegenContext, @@ -125,7 +125,7 @@ class ConstrainedBlobGeneratorTest { val codegenContext = serverTestCodegenContext(model) - val writer = RustWriter.forModule(ModelsModule.name) + val writer = RustWriter.forModule(ServerRustModule.Model.name) ConstrainedBlobGenerator( codegenContext, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt index 0916fceae2..5d0e19cbc0 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt @@ -25,7 +25,6 @@ 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.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.writable -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest @@ -33,6 +32,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.transformers.ShapesReachableFromOperationInputTagger @@ -175,7 +175,7 @@ class ConstrainedCollectionGeneratorTest { else -> UNREACHABLE("Shape is either list or set.") } - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { render(codegenContext, this, shape) val instantiator = serverInstantiator(codegenContext) @@ -269,7 +269,7 @@ class ConstrainedCollectionGeneratorTest { """.asSmithyModel().let(ShapesReachableFromOperationInputTagger::transform) val constrainedCollectionShape = model.lookup("test#ConstrainedList") - val writer = RustWriter.forModule(ModelsModule.name) + val writer = RustWriter.forModule(ServerRustModule.Model.name) val codegenContext = serverTestCodegenContext(model) render(codegenContext, writer, constrainedCollectionShape) diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt index 93f6676d47..f9c84b7db8 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt @@ -17,13 +17,13 @@ import software.amazon.smithy.model.node.ObjectNode import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.transformers.ShapesReachableFromOperationInputTagger @@ -77,7 +77,7 @@ class ConstrainedMapGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { render(codegenContext, this, constrainedMapShape) val instantiator = serverInstantiator(codegenContext) @@ -139,7 +139,7 @@ class ConstrainedMapGeneratorTest { """.asSmithyModel().let(ShapesReachableFromOperationInputTagger::transform) val constrainedMapShape = model.lookup("test#ConstrainedMap") - val writer = RustWriter.forModule(ModelsModule.name) + val writer = RustWriter.forModule(ServerRustModule.Model.name) val codegenContext = serverTestCodegenContext(model) render(codegenContext, writer, constrainedMapShape) diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index 44e08a8fc8..0f26bdaaee 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -14,12 +14,12 @@ import org.junit.jupiter.params.provider.ArgumentsSource import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.NumberShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import java.util.stream.Stream @@ -71,7 +71,7 @@ class ConstrainedNumberGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { ConstrainedNumberGenerator( codegenContext, this, @@ -137,7 +137,7 @@ class ConstrainedNumberGeneratorTest { val codegenContext = serverTestCodegenContext(model) - val writer = RustWriter.forModule(ModelsModule.name) + val writer = RustWriter.forModule(ServerRustModule.Model.name) ConstrainedNumberGenerator( codegenContext, writer, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt index 63fafa4a13..6c8ddd8d67 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt @@ -16,13 +16,13 @@ import org.junit.jupiter.params.provider.ArgumentsSource import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.CommandFailed import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext import java.util.stream.Stream @@ -82,7 +82,7 @@ class ConstrainedStringGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { ConstrainedStringGenerator( codegenContext, this, @@ -140,7 +140,7 @@ class ConstrainedStringGeneratorTest { val codegenContext = serverTestCodegenContext(model) - val writer = RustWriter.forModule(ModelsModule.name) + val writer = RustWriter.forModule(ServerRustModule.Model.name) ConstrainedStringGenerator( codegenContext, @@ -172,7 +172,7 @@ class ConstrainedStringGeneratorTest { val project = TestWorkspace.testProject(codegenContext.symbolProvider) - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { val validationExceptionConversionGenerator = SmithyValidationExceptionConversionGenerator(codegenContext) ConstrainedStringGenerator( codegenContext, @@ -222,7 +222,7 @@ class ConstrainedStringGeneratorTest { val codegenContext = serverTestCodegenContext(model) val project = TestWorkspace.testProject(codegenContext.symbolProvider) - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { ConstrainedStringGenerator( codegenContext, this, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt index 851a44e00b..a65192d609 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiatorTest.kt @@ -21,6 +21,7 @@ import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -137,7 +138,7 @@ class ServerInstantiatorTest { val data = Node.parse("{}") val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + project.withModule(ServerRustModule.Model) { structure.serverRenderWithModelBuilder(model, symbolProvider, this) inner.serverRenderWithModelBuilder(model, symbolProvider, this) nestedStruct.serverRenderWithModelBuilder(model, symbolProvider, this) @@ -189,7 +190,7 @@ class ServerInstantiatorTest { val data = Node.parse("t2.nano".dq()) val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + project.withModule(ServerRustModule.Model) { ServerEnumGenerator( codegenContext, shape, @@ -212,7 +213,7 @@ class ServerInstantiatorTest { val data = Node.parse("t2.nano".dq()) val project = TestWorkspace.testProject() - project.withModule(RustModule.Model) { + project.withModule(ServerRustModule.Model) { ServerEnumGenerator( codegenContext, shape, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt index 32f565feba..31acf95b47 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerOperationErrorGeneratorTest.kt @@ -7,13 +7,13 @@ 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.transformers.OperationNormalizer import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestSymbolProvider @@ -51,16 +51,14 @@ class ServerOperationErrorGeneratorTest { @Test fun `generates combined error enums`() { val project = TestWorkspace.testProject(symbolProvider) - project.withModule(ErrorsModule) { + project.withModule(ServerRustModule.Error) { listOf("FooException", "ComplexError", "InvalidGreeting", "Deprecated").forEach { model.lookup("error#$it").serverRenderWithModelBuilder(model, symbolProvider, this) } - val errors = listOf("FooException", "ComplexError", "InvalidGreeting").map { model.lookup("error#$it") } ServerOperationErrorGenerator( model, symbolProvider, - symbolProvider.toSymbol(model.lookup("error#Greeting")), - errors, + model.lookup("error#Greeting"), ).render(this) unitTest( diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt index a0d608d7c7..64117fd0b7 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedCollectionGeneratorTest.kt @@ -8,14 +8,12 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.ListShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.smithy.ConstrainedModule -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule -import software.amazon.smithy.rust.codegen.core.smithy.UnconstrainedModule import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -51,17 +49,17 @@ class UnconstrainedCollectionGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { model.lookup("test#StructureC").serverRenderWithModelBuilder(model, symbolProvider, this) } - project.withModule(ConstrainedModule) { + project.withModule(ServerRustModule.ConstrainedModule) { listOf(listA, listB).forEach { PubCrateConstrainedCollectionGenerator(codegenContext, this, it).render() } } - project.withModule(UnconstrainedModule) unconstrainedModuleWriter@{ - project.withModule(ModelsModule) modelsModuleWriter@{ + project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ + project.withModule(ServerRustModule.Model) modelsModuleWriter@{ listOf(listA, listB).forEach { UnconstrainedCollectionGenerator( codegenContext, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt index ea2a6907a3..b091d7a38d 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt @@ -8,14 +8,13 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.core.smithy.ConstrainedModule -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule -import software.amazon.smithy.rust.codegen.core.smithy.UnconstrainedModule import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule.Model import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -53,17 +52,17 @@ class UnconstrainedMapGeneratorTest { val project = TestWorkspace.testProject(symbolProvider, debugMode = true) - project.withModule(ModelsModule) { + project.withModule(Model) { model.lookup("test#StructureC").serverRenderWithModelBuilder(model, symbolProvider, this) } - project.withModule(ConstrainedModule) { + project.withModule(ServerRustModule.ConstrainedModule) { listOf(mapA, mapB).forEach { PubCrateConstrainedMapGenerator(codegenContext, this, it).render() } } - project.withModule(UnconstrainedModule) unconstrainedModuleWriter@{ - project.withModule(ModelsModule) modelsModuleWriter@{ + project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ + project.withModule(Model) modelsModuleWriter@{ listOf(mapA, mapB).forEach { UnconstrainedMapGenerator(codegenContext, this@unconstrainedModuleWriter, it).render() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt index 4b5eca2d1e..2b745e270b 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt @@ -8,14 +8,13 @@ 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.model.shapes.UnionShape -import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule -import software.amazon.smithy.rust.codegen.core.smithy.UnconstrainedModule import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverRenderWithModelBuilder import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestCodegenContext @@ -42,15 +41,15 @@ class UnconstrainedUnionGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { model.lookup("test#Structure").serverRenderWithModelBuilder(model, symbolProvider, this) } - project.withModule(ModelsModule) { + project.withModule(ServerRustModule.Model) { UnionGenerator(model, symbolProvider, this, unionShape, renderUnknownVariant = false).render() } - project.withModule(UnconstrainedModule) unconstrainedModuleWriter@{ - project.withModule(ModelsModule) modelsModuleWriter@{ + project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ + project.withModule(ServerRustModule.Model) modelsModuleWriter@{ UnconstrainedUnionGenerator(codegenContext, this@unconstrainedModuleWriter, this@modelsModuleWriter, unionShape).render() this@unconstrainedModuleWriter.unitTest( 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 2eae338e6b..d9fca2df9f 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,9 +8,9 @@ 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.Shape import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter @@ -91,9 +91,8 @@ abstract class ServerEventStreamBaseRequirements : EventStreamTestRequirements, + operationOrEventStream: Shape, ) { - ServerOperationErrorGenerator(model, symbolProvider, operationSymbol, errors).render(writer) + ServerOperationErrorGenerator(model, symbolProvider, operationOrEventStream).render(writer) } }