From 14bd80920cabb273c1c35107dc12aaa348469191 Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Thu, 23 Feb 2023 09:19:27 -0800 Subject: [PATCH] Add builder symbol/module resolution to symbol providers (#2395) * Add builder symbol/module resolution to symbol providers * Back out breaking changes * Reduce codegen diff * Fix server example clippy lints * Associate #2396 with TODO comments * Improve doc comment * Revert doc hidden change --- .../src/profile/credentials/exec.rs | 14 +- aws/rust-runtime/aws-config/src/sso.rs | 2 +- .../aws-config/src/sts/assume_role.rs | 9 +- .../aws-config/src/web_identity_token.rs | 2 +- .../client/smithy/ClientCodegenVisitor.kt | 54 ++++---- .../codegen/client/smithy/ClientRustModule.kt | 17 +++ .../client/smithy/RustClientCodegenPlugin.kt | 9 +- .../smithy/generators/PaginatorGenerator.kt | 3 +- .../client/FluentClientGenerator.kt | 3 +- .../smithy/generators/error/ErrorGenerator.kt | 125 +++++++++--------- .../http/RequestBindingGenerator.kt | 6 +- .../http/ResponseBindingGenerator.kt | 8 +- .../protocol/ClientProtocolGenerator.kt | 9 +- .../protocols/HttpBoundProtocolGenerator.kt | 3 +- .../codegen/client/testutil/TestHelpers.kt | 1 + .../customizations/ApiKeyAuthDecoratorTest.kt | 6 +- .../HttpVersionListGeneratorTest.kt | 6 +- .../client/endpoint/EndpointsDecoratorTest.kt | 2 +- .../smithy/EventStreamSymbolProviderTest.kt | 13 +- .../generators/EndpointTraitBindingsTest.kt | 4 +- .../error/OperationErrorGeneratorTest.kt | 91 ++++++------- .../http/RequestBindingGeneratorTest.kt | 89 +++++++------ .../http/ResponseBindingGeneratorTest.kt | 36 ++--- .../ClientEventStreamBaseRequirements.kt | 8 +- ...entEventStreamUnmarshallerGeneratorTest.kt | 5 - .../codegen/core/smithy/CodegenDelegator.kt | 25 ++-- .../codegen/core/smithy/RustSymbolProvider.kt | 14 +- .../rust/codegen/core/smithy/SymbolVisitor.kt | 8 +- .../smithy/generators/BuilderGenerator.kt | 53 +++----- .../generators/http/HttpBindingGenerator.kt | 3 - .../codegen/core/smithy/protocols/AwsJson.kt | 2 - .../codegen/core/smithy/protocols/AwsQuery.kt | 10 +- .../codegen/core/smithy/protocols/Ec2Query.kt | 7 +- .../codegen/core/smithy/protocols/RestJson.kt | 6 +- .../codegen/core/smithy/protocols/RestXml.kt | 7 +- .../parse/AwsQueryParserGenerator.kt | 4 - .../parse/Ec2QueryParserGenerator.kt | 4 - .../parse/EventStreamUnmarshallerGenerator.kt | 8 +- .../protocols/parse/JsonParserGenerator.kt | 15 ++- .../protocols/parse/RestXmlParserGenerator.kt | 4 - .../parse/XmlBindingTraitParserGenerator.kt | 8 +- .../core/testutil/EventStreamTestTools.kt | 11 +- .../rust/codegen/core/testutil/TestHelpers.kt | 33 ++++- .../core/rustlang/RustReservedWordsTest.kt | 3 +- .../smithy/generators/BuilderGeneratorTest.kt | 42 +++--- .../smithy/generators/InstantiatorTest.kt | 6 +- .../error/ErrorImplGeneratorTest.kt | 12 +- .../parse/AwsQueryParserGeneratorTest.kt | 12 +- .../parse/Ec2QueryParserGeneratorTest.kt | 12 +- .../parse/JsonParserGeneratorTest.kt | 27 ++-- .../XmlBindingTraitParserGeneratorTest.kt | 17 +-- .../AwsQuerySerializerGeneratorTest.kt | 6 +- .../Ec2QuerySerializerGeneratorTest.kt | 6 +- .../serialize/JsonSerializerGeneratorTest.kt | 6 +- .../XmlBindingTraitSerializerGeneratorTest.kt | 6 +- .../smithy/PythonServerCodegenVisitor.kt | 5 +- .../smithy/PythonServerSymbolProvider.kt | 4 +- .../smithy/RustServerCodegenPythonPlugin.kt | 4 +- .../PythonServerSymbolProviderTest.kt | 7 +- .../server/smithy/RustServerCodegenPlugin.kt | 3 +- .../server/smithy/ServerCodegenVisitor.kt | 1 + .../codegen/server/smithy/ServerRustModule.kt | 20 +++ .../server/smithy/ServerSymbolProviders.kt | 7 +- .../smithy/generators/ServerBuilderSymbol.kt | 3 + .../http/ServerRequestBindingGenerator.kt | 9 +- .../http/ServerResponseBindingGenerator.kt | 1 - .../generators/protocol/ServerProtocol.kt | 4 - .../smithy/testutil/ServerTestHelpers.kt | 2 + ...verEventStreamUnmarshallerGeneratorTest.kt | 12 +- .../examples/pokemon-service/src/lib.rs | 5 +- 70 files changed, 484 insertions(+), 505 deletions(-) diff --git a/aws/rust-runtime/aws-config/src/profile/credentials/exec.rs b/aws/rust-runtime/aws-config/src/profile/credentials/exec.rs index 51449f22ef..f930b1a8d8 100644 --- a/aws/rust-runtime/aws-config/src/profile/credentials/exec.rs +++ b/aws/rust-runtime/aws-config/src/profile/credentials/exec.rs @@ -3,14 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -use std::sync::Arc; - -use aws_sdk_sts::operation::AssumeRole; -use aws_sdk_sts::{Config, Credentials}; -use aws_types::region::Region; - use super::repr::{self, BaseProvider}; - use crate::credential_process::CredentialProcessProvider; use crate::profile::credentials::ProfileFileError; use crate::provider_config::ProviderConfig; @@ -18,10 +11,13 @@ use crate::sso::{SsoConfig, SsoCredentialsProvider}; use crate::sts; use crate::web_identity_token::{StaticConfiguration, WebIdentityTokenCredentialsProvider}; use aws_credential_types::provider::{self, error::CredentialsError, ProvideCredentials}; +use aws_sdk_sts::input::AssumeRoleInput; use aws_sdk_sts::middleware::DefaultMiddleware; +use aws_sdk_sts::{Config, Credentials}; use aws_smithy_client::erase::DynConnector; - +use aws_types::region::Region; use std::fmt::Debug; +use std::sync::Arc; #[derive(Debug)] pub(super) struct AssumeRoleProvider { @@ -51,7 +47,7 @@ impl AssumeRoleProvider { .as_ref() .cloned() .unwrap_or_else(|| sts::util::default_session_name("assume-role-from-profile")); - let operation = AssumeRole::builder() + let operation = AssumeRoleInput::builder() .role_arn(&self.role_arn) .set_external_id(self.external_id.clone()) .role_session_name(session_name) diff --git a/aws/rust-runtime/aws-config/src/sso.rs b/aws/rust-runtime/aws-config/src/sso.rs index 0f58264645..3881a217ab 100644 --- a/aws/rust-runtime/aws-config/src/sso.rs +++ b/aws/rust-runtime/aws-config/src/sso.rs @@ -211,7 +211,7 @@ async fn load_sso_credentials( let config = aws_sdk_sso::Config::builder() .region(sso_config.region.clone()) .build(); - let operation = aws_sdk_sso::operation::GetRoleCredentials::builder() + let operation = aws_sdk_sso::input::GetRoleCredentialsInput::builder() .role_name(&sso_config.role_name) .access_token(&*token.access_token) .account_id(&sso_config.account_id) diff --git a/aws/rust-runtime/aws-config/src/sts/assume_role.rs b/aws/rust-runtime/aws-config/src/sts/assume_role.rs index 9561909ed3..ad24b11bb5 100644 --- a/aws/rust-runtime/aws-config/src/sts/assume_role.rs +++ b/aws/rust-runtime/aws-config/src/sts/assume_role.rs @@ -5,19 +5,18 @@ //! Assume credentials for a role through the AWS Security Token Service (STS). +use crate::provider_config::ProviderConfig; use aws_credential_types::cache::CredentialsCache; use aws_credential_types::provider::{self, error::CredentialsError, future, ProvideCredentials}; use aws_sdk_sts::error::AssumeRoleError; +use aws_sdk_sts::input::AssumeRoleInput; use aws_sdk_sts::middleware::DefaultMiddleware; use aws_sdk_sts::model::PolicyDescriptorType; -use aws_sdk_sts::operation::AssumeRole; use aws_smithy_client::erase::DynConnector; use aws_smithy_http::result::SdkError; +use aws_smithy_types::error::display::DisplayErrorContext; use aws_types::region::Region; use std::time::Duration; - -use crate::provider_config::ProviderConfig; -use aws_smithy_types::error::display::DisplayErrorContext; use tracing::Instrument; /// Credentials provider that uses credentials provided by another provider to assume a role @@ -225,7 +224,7 @@ impl AssumeRoleProviderBuilder { .session_name .unwrap_or_else(|| super::util::default_session_name("assume-role-provider")); - let operation = AssumeRole::builder() + let operation = AssumeRoleInput::builder() .set_role_arn(Some(self.role_arn)) .set_external_id(self.external_id) .set_role_session_name(Some(session_name)) diff --git a/aws/rust-runtime/aws-config/src/web_identity_token.rs b/aws/rust-runtime/aws-config/src/web_identity_token.rs index e3c45c7bb8..82c184897f 100644 --- a/aws/rust-runtime/aws-config/src/web_identity_token.rs +++ b/aws/rust-runtime/aws-config/src/web_identity_token.rs @@ -236,7 +236,7 @@ async fn load_credentials( .region(region.clone()) .build(); - let operation = aws_sdk_sts::operation::AssumeRoleWithWebIdentity::builder() + let operation = aws_sdk_sts::input::AssumeRoleWithWebIdentityInput::builder() .role_arn(role_arn) .role_session_name(session_name) .web_identity_token(token) 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 39cb33d4c5..6dd1b03c1f 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 @@ -36,7 +36,6 @@ 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.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 @@ -75,6 +74,12 @@ class ClientCodegenVisitor( true -> ClientModuleProvider else -> OldModuleSchemeClientModuleProvider }, + nameBuilderFor = { symbol -> + when (settings.codegenConfig.enableNewCrateOrganizationScheme) { + true -> "${symbol.name}Builder" + else -> "Builder" + } + }, ) val baseModel = baselineTransform(context.model) val untransformedService = settings.getService(baseModel) @@ -85,7 +90,7 @@ class ClientCodegenVisitor( model = codegenDecorator.transformModel(untransformedService, baseModel) // the model transformer _might_ change the service shape val service = settings.getService(model) - symbolProvider = RustClientCodegenPlugin.baseSymbolProvider(model, service, rustSymbolProviderConfig) + symbolProvider = RustClientCodegenPlugin.baseSymbolProvider(settings, model, service, rustSymbolProviderConfig) codegenContext = ClientCodegenContext(model, symbolProvider, service, protocol, settings, codegenDecorator) @@ -187,9 +192,9 @@ class ClientCodegenVisitor( * This function _does not_ generate any serializers */ override fun structureShape(shape: StructureShape) { - rustCrate.useShapeWriter(shape) { - when (val errorTrait = shape.getTrait()) { - null -> { + when (val errorTrait = shape.getTrait()) { + null -> { + rustCrate.useShapeWriter(shape) { StructureGenerator( model, symbolProvider, @@ -198,31 +203,30 @@ class ClientCodegenVisitor( codegenDecorator.structureCustomizations(codegenContext, emptyList()), ).render() - if (!shape.hasTrait()) { - val builderGenerator = - BuilderGenerator( - codegenContext.model, - codegenContext.symbolProvider, - shape, - codegenDecorator.builderCustomizations(codegenContext, emptyList()), - ) - builderGenerator.render(this) - implBlock(symbolProvider.toSymbol(shape)) { - builderGenerator.renderConvenienceMethod(this) - } + implBlock(symbolProvider.toSymbol(shape)) { + BuilderGenerator.renderConvenienceMethod(this, symbolProvider, shape) } } - else -> { - ErrorGenerator( - model, - symbolProvider, - this, + + rustCrate.withModule(symbolProvider.moduleForBuilder(shape)) { + BuilderGenerator( + codegenContext.model, + codegenContext.symbolProvider, shape, - errorTrait, - codegenDecorator.errorImplCustomizations(codegenContext, emptyList()), - ).render() + codegenDecorator.builderCustomizations(codegenContext, emptyList()), + ).render(this) } } + else -> { + ErrorGenerator( + rustCrate, + model, + symbolProvider, + shape, + errorTrait, + codegenDecorator.errorImplCustomizations(codegenContext, emptyList()), + ).render() + } } } 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 index 18f80be311..fbb26fede5 100644 --- 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 @@ -5,6 +5,7 @@ package software.amazon.smithy.rust.codegen.client.smithy +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 @@ -13,10 +14,12 @@ 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.RustReservedWords +import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.smithy.ModuleProvider import software.amazon.smithy.rust.codegen.core.smithy.ModuleProviderContext import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.contextName +import software.amazon.smithy.rust.codegen.core.smithy.module 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.UNREACHABLE @@ -75,6 +78,9 @@ object ClientModuleProvider : ModuleProvider { eventStream: UnionShape, ): RustModule.LeafModule = ClientRustModule.Error + override fun moduleForBuilder(context: ModuleProviderContext, shape: Shape, symbol: Symbol): RustModule.LeafModule = + RustModule.public("builders", parent = symbol.module(), documentation = "Builders") + private fun Shape.findOperation(model: Model): OperationShape { val inputTrait = getTrait() val outputTrait = getTrait() @@ -122,6 +128,17 @@ object OldModuleSchemeClientModuleProvider : ModuleProvider { context: ModuleProviderContext, eventStream: UnionShape, ): RustModule.LeafModule = ClientRustModule.Error + + override fun moduleForBuilder(context: ModuleProviderContext, shape: Shape, symbol: Symbol): RustModule.LeafModule { + val builderNamespace = RustReservedWords.escapeIfNeeded(symbol.name.toSnakeCase()) + return RustModule.new( + builderNamespace, + visibility = Visibility.PUBLIC, + parent = symbol.module(), + inline = true, + documentation = "See [`${symbol.name}`](${symbol.module().fullyQualifiedPath()}::${symbol.name}).", + ) + } } // TODO(CrateReorganization): Remove when cleaning up `enableNewCrateOrganizationScheme` diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/RustClientCodegenPlugin.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/RustClientCodegenPlugin.kt index c1b35d10bd..38af758ad0 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/RustClientCodegenPlugin.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/RustClientCodegenPlugin.kt @@ -74,8 +74,13 @@ class RustClientCodegenPlugin : ClientDecoratableBuildPlugin() { * The Symbol provider is composed of a base [SymbolVisitor] which handles the core functionality, then is layered * with other symbol providers, documented inline, to handle the full scope of Smithy types. */ - fun baseSymbolProvider(model: Model, serviceShape: ServiceShape, rustSymbolProviderConfig: RustSymbolProviderConfig) = - SymbolVisitor(model, serviceShape = serviceShape, config = rustSymbolProviderConfig) + fun baseSymbolProvider( + settings: ClientRustSettings, + model: Model, + serviceShape: ServiceShape, + rustSymbolProviderConfig: RustSymbolProviderConfig, + ) = + SymbolVisitor(settings, model, serviceShape = serviceShape, config = rustSymbolProviderConfig) // Generate different types for EventStream shapes (e.g. transcribe streaming) .let { EventStreamSymbolProvider(rustSymbolProviderConfig.runtimeConfig, it, CodegenTarget.CLIENT) } // Generate `ByteStream` instead of `Blob` for streaming binary shapes (e.g. S3 GetObject) 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 851553d317..d87c2d1483 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/PaginatorGenerator.kt @@ -21,7 +21,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol 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 @@ -98,7 +97,7 @@ class PaginatorGenerator private constructor( "Input" to inputType, "Output" to outputType, "Error" to errorType, - "Builder" to operation.inputShape(model).builderSymbol(symbolProvider), + "Builder" to symbolProvider.symbolForBuilder(operation.inputShape(model)), // SDK Types "SdkError" to RuntimeType.sdkError(runtimeConfig), 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 a1a000ffe1..ead062c345 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 @@ -45,7 +45,6 @@ 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.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.setterName import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.util.inputShape @@ -255,7 +254,7 @@ class FluentClientGenerator( inner: #{Inner} } """, - "Inner" to input.builderSymbol(symbolProvider), + "Inner" to symbolProvider.symbolForBuilder(input), "client" to RuntimeType.smithyClient(runtimeConfig), "generics" to generics.decl, "operation" to operationSymbol, diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/ErrorGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/ErrorGenerator.kt index 65c1f3ce05..bdc8518d92 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/ErrorGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/ErrorGenerator.kt @@ -8,7 +8,6 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.error import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.traits.ErrorTrait -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.implBlock import software.amazon.smithy.rust.codegen.core.rustlang.rust @@ -18,6 +17,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.errorMetadata +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.generators.BuilderCustomization import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerator @@ -29,9 +29,9 @@ import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ErrorImp import software.amazon.smithy.rust.codegen.core.smithy.generators.error.ErrorImplGenerator class ErrorGenerator( + private val rustCrate: RustCrate, private val model: Model, private val symbolProvider: RustSymbolProvider, - private val writer: RustWriter, private val shape: StructureShape, private val error: ErrorTrait, private val implCustomizations: List, @@ -41,73 +41,78 @@ class ErrorGenerator( fun render() { val symbol = symbolProvider.toSymbol(shape) - StructureGenerator( - model, symbolProvider, writer, shape, - listOf(object : StructureCustomization() { - override fun section(section: StructureSection): Writable = writable { - when (section) { - is StructureSection.AdditionalFields -> { - rust("pub(crate) meta: #T,", errorMetadata(runtimeConfig)) - } - is StructureSection.AdditionalDebugFields -> { - rust("""${section.formatterName}.field("meta", &self.meta);""") - } - else -> {} - } - } - }, - ), - ).render() + rustCrate.useShapeWriter(shape) { + StructureGenerator( + model, symbolProvider, this, shape, + listOf( + object : StructureCustomization() { + override fun section(section: StructureSection): Writable = writable { + when (section) { + is StructureSection.AdditionalFields -> { + rust("pub(crate) meta: #T,", errorMetadata(runtimeConfig)) + } - BuilderGenerator( - model, symbolProvider, shape, - listOf( - object : BuilderCustomization() { - override fun section(section: BuilderSection): Writable = writable { - when (section) { - is BuilderSection.AdditionalFields -> { - rust("meta: Option<#T>,", errorMetadata(runtimeConfig)) + is StructureSection.AdditionalDebugFields -> { + rust("""${section.formatterName}.field("meta", &self.meta);""") + } + else -> {} } + } + }, + ), + ).render() - is BuilderSection.AdditionalMethods -> { - rustTemplate( - """ - /// Sets error metadata - pub fn meta(mut self, meta: #{error_metadata}) -> Self { - self.meta = Some(meta); - self - } + ErrorImplGenerator(model, symbolProvider, this, shape, error, implCustomizations).render(CodegenTarget.CLIENT) - /// Sets error metadata - pub fn set_meta(&mut self, meta: Option<#{error_metadata}>) -> &mut Self { - self.meta = meta; - self - } - """, - "error_metadata" to errorMetadata(runtimeConfig), - ) - } - - is BuilderSection.AdditionalFieldsInBuild -> { - rust("meta: self.meta.unwrap_or_default(),") - } + rustBlock("impl #T for ${symbol.name}", RuntimeType.provideErrorMetadataTrait(runtimeConfig)) { + rust("fn meta(&self) -> &#T { &self.meta }", errorMetadata(runtimeConfig)) + } - else -> {} - } - } - }, - ), - ).let { builderGen -> - writer.implBlock(symbol) { - builderGen.renderConvenienceMethod(this) + implBlock(symbol) { + BuilderGenerator.renderConvenienceMethod(this, symbolProvider, shape) } - builderGen.render(writer) } - ErrorImplGenerator(model, symbolProvider, writer, shape, error, implCustomizations).render(CodegenTarget.CLIENT) + rustCrate.withModule(symbolProvider.moduleForBuilder(shape)) { + BuilderGenerator( + model, symbolProvider, shape, + listOf( + object : BuilderCustomization() { + override fun section(section: BuilderSection): Writable = writable { + when (section) { + is BuilderSection.AdditionalFields -> { + rust("meta: Option<#T>,", errorMetadata(runtimeConfig)) + } + + is BuilderSection.AdditionalMethods -> { + rustTemplate( + """ + /// Sets error metadata + pub fn meta(mut self, meta: #{error_metadata}) -> Self { + self.meta = Some(meta); + self + } + + /// Sets error metadata + pub fn set_meta(&mut self, meta: Option<#{error_metadata}>) -> &mut Self { + self.meta = meta; + self + } + """, + "error_metadata" to errorMetadata(runtimeConfig), + ) + } - writer.rustBlock("impl #T for ${symbol.name}", RuntimeType.provideErrorMetadataTrait(runtimeConfig)) { - rust("fn meta(&self) -> &#T { &self.meta }", errorMetadata(runtimeConfig)) + is BuilderSection.AdditionalFieldsInBuild -> { + rust("meta: self.meta.unwrap_or_default(),") + } + + else -> {} + } + } + }, + ), + ).render(this) } } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGenerator.kt index 9ec7173d03..ae725af304 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGenerator.kt @@ -5,7 +5,6 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.http -import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.knowledge.HttpBinding import software.amazon.smithy.model.knowledge.HttpBindingIndex import software.amazon.smithy.model.pattern.SmithyPattern @@ -13,7 +12,6 @@ import software.amazon.smithy.model.shapes.MapShape 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.StructureShape import software.amazon.smithy.model.traits.EnumTrait import software.amazon.smithy.model.traits.HttpTrait import software.amazon.smithy.rust.codegen.core.rustlang.Attribute @@ -26,7 +24,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.generators.OperationBuildError -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.http.HttpBindingGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.operationBuildError import software.amazon.smithy.rust.codegen.core.smithy.isOptional @@ -68,9 +65,8 @@ class RequestBindingGenerator( private val symbolProvider = codegenContext.symbolProvider private val runtimeConfig = codegenContext.runtimeConfig private val httpTrait = protocol.httpBindingResolver.httpTrait(operationShape) - private fun builderSymbol(shape: StructureShape): Symbol = shape.builderSymbol(symbolProvider) private val httpBindingGenerator = - HttpBindingGenerator(protocol, codegenContext, codegenContext.symbolProvider, operationShape, ::builderSymbol) + HttpBindingGenerator(protocol, codegenContext, codegenContext.symbolProvider, operationShape) private val index = HttpBindingIndex.of(model) private val encoder = RuntimeType.smithyTypes(runtimeConfig).resolve("primitive::Encoder") 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 210715c3eb..911028ea5a 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 @@ -7,24 +7,20 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.http import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.OperationShape -import software.amazon.smithy.model.shapes.StructureShape 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.RuntimeType -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol import software.amazon.smithy.rust.codegen.core.smithy.generators.http.HttpBindingGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.HttpBindingDescriptor import software.amazon.smithy.rust.codegen.core.smithy.protocols.Protocol class ResponseBindingGenerator( protocol: Protocol, - private val codegenContext: CodegenContext, + codegenContext: CodegenContext, operationShape: OperationShape, ) { - private fun builderSymbol(shape: StructureShape): Symbol = shape.builderSymbol(codegenContext.symbolProvider) - private val httpBindingGenerator = - HttpBindingGenerator(protocol, codegenContext, codegenContext.symbolProvider, operationShape, ::builderSymbol) + HttpBindingGenerator(protocol, codegenContext, codegenContext.symbolProvider, operationShape) fun generateDeserializeHeaderFn(binding: HttpBindingDescriptor): RuntimeType = httpBindingGenerator.generateDeserializeHeaderFn(binding) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ClientProtocolGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ClientProtocolGenerator.kt index d011039b19..07b92099b6 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ClientProtocolGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ClientProtocolGenerator.kt @@ -50,8 +50,6 @@ open class ClientProtocolGenerator( customizations: List, ) { val inputShape = operationShape.inputShape(model) - val builderGenerator = BuilderGenerator(model, symbolProvider, operationShape.inputShape(model), emptyList()) - builderGenerator.render(inputWriter) // impl OperationInputShape { ... } val operationName = symbolProvider.toSymbol(operationShape).name @@ -61,9 +59,6 @@ open class ClientProtocolGenerator( OperationSection.InputImpl(customizations, operationShape, inputShape, protocol), ) makeOperationGenerator.generateMakeOperation(this, operationShape, customizations) - - // pub fn builder() -> ... { } - builderGenerator.renderConvenienceMethod(this) } // pub struct Operation { ... } @@ -75,7 +70,7 @@ open class ClientProtocolGenerator( /// This is usually constructed for you using the the fluent builder returned by /// [`$fluentBuilderName`](${docLink("crate::client::Client::$fluentBuilderName")}). /// - /// See [`crate::client::fluent_builders::$operationName`] for more details about the operation. + /// `ParseStrictResponse` impl for `$operationName`. """, ) Attribute(derive(RuntimeType.Clone, RuntimeType.Default, RuntimeType.Debug)).render(operationWriter) @@ -83,7 +78,7 @@ open class ClientProtocolGenerator( write("_private: ()") } operationWriter.implBlock(symbolProvider.toSymbol(operationShape)) { - builderGenerator.renderConvenienceMethod(this) + BuilderGenerator.renderConvenienceMethod(this, symbolProvider, inputShape) rust("/// Creates a new `$operationName` operation.") rustBlock("pub fn new() -> Self") { 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 d69c864d65..fae7fa62bb 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 @@ -29,7 +29,6 @@ import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationCustom import software.amazon.smithy.rust.codegen.core.smithy.customize.OperationSection 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.protocol.ProtocolTraitImplGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName import software.amazon.smithy.rust.codegen.core.smithy.protocols.HttpBindingDescriptor @@ -318,7 +317,7 @@ class HttpBoundProtocolTraitImplGenerator( val httpBindingGenerator = ResponseBindingGenerator(protocol, codegenContext, operationShape) val structuredDataParser = protocol.structuredDataParser(operationShape) Attribute.AllowUnusedMut.render(this) - rust("let mut output = #T::default();", outputShape.builderSymbol(symbolProvider)) + rust("let mut output = #T::default();", symbolProvider.symbolForBuilder(outputShape)) // avoid non-usage warnings for response rust("let _ = response;") if (outputShape.id == operationShape.output.get()) { 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 a381bc8af3..0f065a2d18 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 @@ -58,6 +58,7 @@ val ClientTestRustSymbolProviderConfig = RustSymbolProviderConfig( fun testSymbolProvider(model: Model, serviceShape: ServiceShape? = null): RustSymbolProvider = RustClientCodegenPlugin.baseSymbolProvider( + clientTestRustSettings(), model, serviceShape ?: ServiceShape.builder().version("test").id("test#Service").build(), ClientTestRustSymbolProviderConfig, diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/customizations/ApiKeyAuthDecoratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/customizations/ApiKeyAuthDecoratorTest.kt index 7e309287df..41e3ebae7a 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/customizations/ApiKeyAuthDecoratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/customizations/ApiKeyAuthDecoratorTest.kt @@ -59,7 +59,7 @@ internal class ApiKeyAuthDecoratorTest { let conf = $moduleName::Config::builder() .api_key(AuthApiKey::new(api_key_value)) .build(); - let operation = $moduleName::operation::SomeOperation::builder() + let operation = $moduleName::input::SomeOperationInput::builder() .build() .expect("input is valid") .make_operation(&conf) @@ -87,7 +87,7 @@ internal class ApiKeyAuthDecoratorTest { let conf = $moduleName::Config::builder() .api_key(AuthApiKey::new(api_key_value)) .build(); - let operation = $moduleName::operation::SomeOperation::builder() + let operation = $moduleName::input::SomeOperationInput::builder() .build() .expect("input is valid") .make_operation(&conf) @@ -149,7 +149,7 @@ internal class ApiKeyAuthDecoratorTest { let conf = $moduleName::Config::builder() .api_key(AuthApiKey::new(api_key_value)) .build(); - let operation = $moduleName::operation::SomeOperation::builder() + let operation = $moduleName::input::SomeOperationInput::builder() .build() .expect("input is valid") .make_operation(&conf) diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/customizations/HttpVersionListGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/customizations/HttpVersionListGeneratorTest.kt index 32236c8f79..eb166ae1c6 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/customizations/HttpVersionListGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/customizations/HttpVersionListGeneratorTest.kt @@ -62,7 +62,7 @@ internal class HttpVersionListGeneratorTest { """ async fn test_http_version_list_defaults() { let conf = $moduleName::Config::builder().build(); - let op = $moduleName::operation::SayHello::builder() + let op = $moduleName::input::SayHelloInput::builder() .greeting("hello") .build().expect("valid operation") .make_operation(&conf).await.expect("hello is a valid prefix"); @@ -113,7 +113,7 @@ internal class HttpVersionListGeneratorTest { """ async fn test_http_version_list_defaults() { let conf = $moduleName::Config::builder().build(); - let op = $moduleName::operation::SayHello::builder() + let op = $moduleName::input::SayHelloInput::builder() .greeting("hello") .build().expect("valid operation") .make_operation(&conf).await.expect("hello is a valid prefix"); @@ -181,7 +181,7 @@ internal class HttpVersionListGeneratorTest { """ async fn test_http_version_list_defaults() { let conf = $moduleName::Config::builder().build(); - let op = $moduleName::operation::SayHello::builder() + let op = $moduleName::input::SayHelloInput::builder() .build().expect("valid operation") .make_operation(&conf).await.unwrap(); let properties = op.properties(); diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/endpoint/EndpointsDecoratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/endpoint/EndpointsDecoratorTest.kt index d9b398f0ca..2b9e75f403 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/endpoint/EndpointsDecoratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/endpoint/EndpointsDecoratorTest.kt @@ -134,7 +134,7 @@ class EndpointsDecoratorTest { """ async fn endpoint_params_are_set() { let conf = $moduleName::Config::builder().a_string_param("hello").a_bool_param(false).build(); - let operation = $moduleName::operation::TestOperation::builder() + let operation = $moduleName::input::TestOperationInput::builder() .bucket("bucket-name").build().expect("input is valid") .make_operation(&conf).await.expect("valid operation"); use $moduleName::endpoint::{Params}; 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 15e40ae838..0870572f0f 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 @@ -11,6 +11,7 @@ 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.ClientTestRustSymbolProviderConfig +import software.amazon.smithy.rust.codegen.client.testutil.clientTestRustSettings 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 @@ -46,7 +47,11 @@ class EventStreamSymbolProviderTest { ) val service = model.expectShape(ShapeId.from("test#TestService")) as ServiceShape - val provider = EventStreamSymbolProvider(TestRuntimeConfig, SymbolVisitor(model, service, ClientTestRustSymbolProviderConfig), CodegenTarget.CLIENT) + val provider = EventStreamSymbolProvider( + TestRuntimeConfig, + SymbolVisitor(clientTestRustSettings(), model, service, ClientTestRustSymbolProviderConfig), + 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 +87,11 @@ class EventStreamSymbolProviderTest { ) val service = model.expectShape(ShapeId.from("test#TestService")) as ServiceShape - val provider = EventStreamSymbolProvider(TestRuntimeConfig, SymbolVisitor(model, service, ClientTestRustSymbolProviderConfig), CodegenTarget.CLIENT) + val provider = EventStreamSymbolProvider( + TestRuntimeConfig, + SymbolVisitor(clientTestRustSettings(), model, service, ClientTestRustSymbolProviderConfig), + 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/generators/EndpointTraitBindingsTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/EndpointTraitBindingsTest.kt index 12285e4364..2e3f6d6a2d 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/EndpointTraitBindingsTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/EndpointTraitBindingsTest.kt @@ -145,10 +145,10 @@ internal class EndpointTraitBindingsTest { """ async fn test_endpoint_prefix() { let conf = $moduleName::Config::builder().build(); - $moduleName::operation::SayHello::builder() + $moduleName::input::SayHelloInput::builder() .greeting("hey there!").build().expect("input is valid") .make_operation(&conf).await.expect_err("no spaces or exclamation points in ep prefixes"); - let op = $moduleName::operation::SayHello::builder() + let op = $moduleName::input::SayHelloInput::builder() .greeting("hello") .build().expect("valid operation") .make_operation(&conf).await.expect("hello is a valid prefix"); diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/OperationErrorGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/OperationErrorGeneratorTest.kt index f9faae87f2..b81de4010c 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/OperationErrorGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/OperationErrorGeneratorTest.kt @@ -7,19 +7,20 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.error import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.StructureShape -import software.amazon.smithy.rust.codegen.client.testutil.testSymbolProvider -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.client.testutil.clientIntegrationTest 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.renderWithModelBuilder import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup class OperationErrorGeneratorTest { - private val baseModel = """ + private val model = """ namespace error + @aws.protocols#awsJson1_0 + service TestService { + operations: [Greeting], + } + operation Greeting { errors: [InvalidGreeting, ComplexError, FooException, Deprecated] } @@ -43,51 +44,47 @@ class OperationErrorGeneratorTest { @deprecated structure Deprecated { } """.asSmithyModel() - private val model = OperationNormalizer.transform(baseModel) - private val symbolProvider = testSymbolProvider(model) @Test fun `generates combined error enums`() { - val project = TestWorkspace.testProject(symbolProvider) - project.moduleFor(model.lookup("error#FooException")) { - listOf("FooException", "ComplexError", "InvalidGreeting", "Deprecated").forEach { - model.lookup("error#$it").renderWithModelBuilder(model, symbolProvider, this) + clientIntegrationTest(model) { _, rustCrate -> + rustCrate.moduleFor(model.lookup("error#FooException")) { + unitTest( + name = "generates_combined_error_enums", + test = """ + let error = GreetingError::InvalidGreeting( + InvalidGreeting::builder() + .message("an error") + .meta(aws_smithy_types::Error::builder().code("InvalidGreeting").message("an error").build()) + .build() + ); + assert_eq!(format!("{}", error), "InvalidGreeting: an error"); + assert_eq!(error.meta().message(), Some("an error")); + assert_eq!(error.meta().code(), Some("InvalidGreeting")); + use aws_smithy_types::retry::ProvideErrorKind; + assert_eq!(error.retryable_error_kind(), Some(aws_smithy_types::retry::ErrorKind::ClientError)); + + // Generate is_xyz methods for errors. + assert_eq!(error.is_invalid_greeting(), true); + assert_eq!(error.is_complex_error(), false); + + // Unhandled variants properly delegate message. + let error = GreetingError::generic(aws_smithy_types::Error::builder().message("hello").build()); + assert_eq!(error.meta().message(), Some("hello")); + + let error = GreetingError::unhandled("some other error"); + assert_eq!(error.meta().message(), None); + assert_eq!(error.meta().code(), None); + + // Indicate the original name in the display output. + let error = FooError::builder().build(); + assert_eq!(format!("{}", error), "FooError [FooException]"); + + let error = Deprecated::builder().build(); + assert_eq!(error.to_string(), "Deprecated"); + """, + ) } - OperationErrorGenerator(model, symbolProvider, model.lookup("error#Greeting"), emptyList()).render(this) - - unitTest( - name = "generates_combined_error_enums", - test = """ - let kind = GreetingErrorKind::InvalidGreeting(InvalidGreeting::builder().message("an error").build()); - let error = GreetingError::new(kind, aws_smithy_types::Error::builder().code("InvalidGreeting").message("an error").build()); - assert_eq!(format!("{}", error), "InvalidGreeting: an error"); - assert_eq!(error.message(), Some("an error")); - assert_eq!(error.code(), Some("InvalidGreeting")); - use aws_smithy_types::retry::ProvideErrorKind; - assert_eq!(error.retryable_error_kind(), Some(aws_smithy_types::retry::ErrorKind::ClientError)); - - // Generate is_xyz methods for errors. - assert_eq!(error.is_invalid_greeting(), true); - assert_eq!(error.is_complex_error(), false); - - // Unhandled variants properly delegate message. - let error = GreetingError::generic(aws_smithy_types::Error::builder().message("hello").build()); - assert_eq!(error.message(), Some("hello")); - - let error = GreetingError::unhandled("some other error"); - assert_eq!(error.message(), None); - assert_eq!(error.code(), None); - - // Indicate the original name in the display output. - let error = FooError::builder().build(); - assert_eq!(format!("{}", error), "FooError [FooException]"); - - let error = Deprecated::builder().build(); - assert_eq!(error.to_string(), "Deprecated"); - """, - ) - - project.compileAndTest() } } } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGeneratorTest.kt index 6f214e3540..960662214e 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/RequestBindingGeneratorTest.kt @@ -11,13 +11,13 @@ import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.traits.HttpTrait +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule import software.amazon.smithy.rust.codegen.client.testutil.testCodegenContext 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.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.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.generators.operationBuildError import software.amazon.smithy.rust.codegen.core.smithy.protocols.RestJson import software.amazon.smithy.rust.codegen.core.smithy.transformers.OperationNormalizer @@ -127,45 +127,47 @@ class RequestBindingGeneratorTest { private val operationShape = model.expectShape(ShapeId.from("smithy.example#PutObject"), OperationShape::class.java) private val inputShape = model.expectShape(operationShape.input.get(), StructureShape::class.java) - private fun renderOperation(writer: RustWriter) { - inputShape.renderWithModelBuilder(model, symbolProvider, writer) - val codegenContext = testCodegenContext(model) - val bindingGen = RequestBindingGenerator( - codegenContext, - // Any protocol is fine for this test. - RestJson(codegenContext), - operationShape, - ) - writer.rustBlock("impl PutObjectInput") { - // RequestBindingGenerator's functions expect to be rendered inside a function, - // but the unit test needs to call some of these functions individually. This generates - // some wrappers that can be called directly from the tests. The functions will get duplicated, - // but that's not a problem. - - rustBlock( - "pub fn test_uri_query(&self, mut output: &mut String) -> Result<(), #T>", - TestRuntimeConfig.operationBuildError(), - ) { - bindingGen.renderUpdateHttpBuilder(this) - rust("uri_query(self, output)") - } - - rustBlock( - "pub fn test_uri_base(&self, mut output: &mut String) -> Result<(), #T>", - TestRuntimeConfig.operationBuildError(), - ) { - bindingGen.renderUpdateHttpBuilder(this) - rust("uri_base(self, output)") - } - - rustBlock( - "pub fn test_request_builder_base(&self) -> Result<#T, #T>", - RuntimeType.HttpRequestBuilder, - TestRuntimeConfig.operationBuildError(), - ) { - bindingGen.renderUpdateHttpBuilder(this) - rust("let builder = #T::new();", RuntimeType.HttpRequestBuilder) - rust("update_http_builder(self, builder)") + private fun renderOperation(rustCrate: RustCrate) { + inputShape.renderWithModelBuilder(model, symbolProvider, rustCrate) + rustCrate.withModule(ClientRustModule.Input) { + val codegenContext = testCodegenContext(model) + val bindingGen = RequestBindingGenerator( + codegenContext, + // Any protocol is fine for this test. + RestJson(codegenContext), + operationShape, + ) + rustBlock("impl PutObjectInput") { + // RequestBindingGenerator's functions expect to be rendered inside a function, + // but the unit test needs to call some of these functions individually. This generates + // some wrappers that can be called directly from the tests. The functions will get duplicated, + // but that's not a problem. + + rustBlock( + "pub fn test_uri_query(&self, mut output: &mut String) -> Result<(), #T>", + TestRuntimeConfig.operationBuildError(), + ) { + bindingGen.renderUpdateHttpBuilder(this) + rust("uri_query(self, output)") + } + + rustBlock( + "pub fn test_uri_base(&self, mut output: &mut String) -> Result<(), #T>", + TestRuntimeConfig.operationBuildError(), + ) { + bindingGen.renderUpdateHttpBuilder(this) + rust("uri_base(self, output)") + } + + rustBlock( + "pub fn test_request_builder_base(&self) -> Result<#T, #T>", + RuntimeType.HttpRequestBuilder, + TestRuntimeConfig.operationBuildError(), + ) { + bindingGen.renderUpdateHttpBuilder(this) + rust("let builder = #T::new();", RuntimeType.HttpRequestBuilder) + rust("update_http_builder(self, builder)") + } } } } @@ -179,9 +181,8 @@ class RequestBindingGeneratorTest { @Test fun `generates valid request bindings`() { val project = TestWorkspace.testProject(symbolProvider) - project.withModule(RustModule.public("input")) { // Currently rendering the operation renders the protocols—I want to separate that at some point. - renderOperation(this) - + renderOperation(project) + project.withModule(ClientRustModule.Input) { // Currently rendering the operation renders the protocols—I want to separate that at some point. unitTest( name = "generate_uris", test = """ diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/ResponseBindingGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/ResponseBindingGeneratorTest.kt index 19ab23102f..fb0cf688ab 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/ResponseBindingGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/http/ResponseBindingGeneratorTest.kt @@ -8,12 +8,12 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.http import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.ShapeId +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule 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.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.CodegenContext +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.protocols.HttpLocation import software.amazon.smithy.rust.codegen.core.smithy.protocols.HttpTraitHttpBindingResolver import software.amazon.smithy.rust.codegen.core.smithy.protocols.ProtocolContentTypes @@ -70,20 +70,22 @@ class ResponseBindingGeneratorTest { private val codegenContext: CodegenContext = testCodegenContext(model) private val symbolProvider = codegenContext.symbolProvider - private fun RustWriter.renderOperation() { + private fun RustCrate.renderOperation() { operationShape.outputShape(model).renderWithModelBuilder(model, symbolProvider, this) - rustBlock("impl PutObjectOutput") { - val bindings = HttpTraitHttpBindingResolver(model, ProtocolContentTypes.consistent("dont-care")) - .responseBindings(operationShape) - .filter { it.location == HttpLocation.HEADER } - bindings.forEach { binding -> - val runtimeType = ResponseBindingGenerator( - RestJson(codegenContext), - codegenContext, - operationShape, - ).generateDeserializeHeaderFn(binding) - // little hack to force these functions to be generated - rust("// use #T;", runtimeType) + withModule(ClientRustModule.Output) { + rustBlock("impl PutObjectOutput") { + val bindings = HttpTraitHttpBindingResolver(model, ProtocolContentTypes.consistent("dont-care")) + .responseBindings(operationShape) + .filter { it.location == HttpLocation.HEADER } + bindings.forEach { binding -> + val runtimeType = ResponseBindingGenerator( + RestJson(codegenContext), + codegenContext, + operationShape, + ).generateDeserializeHeaderFn(binding) + // little hack to force these functions to be generated + rust("// use #T;", runtimeType) + } } } } @@ -91,8 +93,8 @@ class ResponseBindingGeneratorTest { @Test fun deserializeHeadersIntoOutputShape() { val testProject = TestWorkspace.testProject(symbolProvider) - testProject.withModule(RustModule.public("output")) { - renderOperation() + testProject.renderOperation() + testProject.withModule(ClientRustModule.Output) { unitTest( "http_header_deser", """ 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 7cb08314c2..88c80a4330 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 @@ -59,9 +59,9 @@ abstract class ClientEventStreamBaseRequirements : EventStreamTestRequirements() ErrorGenerator( + rustCrate, codegenContext.model, codegenContext.symbolProvider, - writer, shape, errorTrait, emptyList(), diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt index b20810ef97..11a253ceef 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/protocols/eventstream/ClientEventStreamUnmarshallerGeneratorTest.kt @@ -7,12 +7,9 @@ package software.amazon.smithy.rust.codegen.client.smithy.protocols.eventstream import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ArgumentsSource -import software.amazon.smithy.codegen.core.Symbol -import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext 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.builderSymbol import software.amazon.smithy.rust.codegen.core.smithy.protocols.Protocol import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.EventStreamUnmarshallerGenerator import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestModels @@ -33,13 +30,11 @@ class ClientEventStreamUnmarshallerGeneratorTest { project: TestEventStreamProject, protocol: Protocol, ): RuntimeType { - fun builderSymbol(shape: StructureShape): Symbol = shape.builderSymbol(codegenContext.symbolProvider) return EventStreamUnmarshallerGenerator( protocol, codegenContext, project.operationShape, project.streamShape, - ::builderSymbol, ).render() } }, 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 1c6ee0d02b..0e79249739 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 @@ -147,15 +147,22 @@ open class RustCrate( is RustModule.LibRs -> lib { moduleWriter(this) } is RustModule.LeafModule -> { checkDups(module) - // Create a dependency which adds the mod statement for this module. This will be added to the writer - // so that _usage_ of this module will generate _exactly one_ `mod ` with the correct modifiers. - val modStatement = RuntimeType.forInlineFun("mod_" + module.fullyQualifiedPath(), module.parent) { - module.renderModStatement(this) - } - val path = module.fullyQualifiedPath().split("::").drop(1).joinToString("/") - inner.useFileWriter("src/$path.rs", module.fullyQualifiedPath()) { writer -> - moduleWriter(writer) - writer.addDependency(modStatement.dependency) + + if (module.isInline()) { + withModule(module.parent) { + withInlineModule(module, moduleWriter) + } + } else { + // Create a dependency which adds the mod statement for this module. This will be added to the writer + // so that _usage_ of this module will generate _exactly one_ `mod ` with the correct modifiers. + val modStatement = RuntimeType.forInlineFun("mod_" + module.fullyQualifiedPath(), module.parent) { + module.renderModStatement(this) + } + val path = module.fullyQualifiedPath().split("::").drop(1).joinToString("/") + inner.useFileWriter("src/$path.rs", module.fullyQualifiedPath()) { writer -> + moduleWriter(writer) + writer.addDependency(modStatement.dependency) + } } } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RustSymbolProvider.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RustSymbolProvider.kt index 87df2d344b..2314007aa9 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RustSymbolProvider.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RustSymbolProvider.kt @@ -30,12 +30,17 @@ interface RustSymbolProvider : SymbolProvider { config.moduleProvider.moduleForOperationError(moduleProviderContext, operation) fun moduleForEventStreamError(eventStream: UnionShape): RustModule.LeafModule = config.moduleProvider.moduleForEventStreamError(moduleProviderContext, eventStream) + fun moduleForBuilder(shape: Shape): RustModule.LeafModule = + config.moduleProvider.moduleForBuilder(moduleProviderContext, shape, toSymbol(shape)) /** 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 + + /** Returns the symbol for a builder */ + fun symbolForBuilder(shape: Shape): Symbol } /** @@ -43,11 +48,13 @@ interface RustSymbolProvider : SymbolProvider { * inside the SymbolVisitor, which is created before CodegenContext is created. */ data class ModuleProviderContext( + val settings: CoreRustSettings, val model: Model, val serviceShape: ServiceShape?, ) -fun CodegenContext.toModuleProviderContext(): ModuleProviderContext = ModuleProviderContext(model, serviceShape) +fun CodegenContext.toModuleProviderContext(): ModuleProviderContext = + ModuleProviderContext(settings, model, serviceShape) /** * Provider for RustModules so that the symbol provider knows where to organize things. @@ -61,6 +68,9 @@ interface ModuleProvider { /** Returns the module for an event stream error */ fun moduleForEventStreamError(context: ModuleProviderContext, eventStream: UnionShape): RustModule.LeafModule + + /** Returns the module for a builder */ + fun moduleForBuilder(context: ModuleProviderContext, shape: Shape, symbol: Symbol): RustModule.LeafModule } /** @@ -71,6 +81,7 @@ data class RustSymbolProviderConfig( val renameExceptions: Boolean, val nullabilityCheckMode: NullableIndex.CheckMode, val moduleProvider: ModuleProvider, + val nameBuilderFor: (Symbol) -> String = { _ -> "Builder" }, ) /** @@ -86,4 +97,5 @@ open class WrappingSymbolProvider(private val base: RustSymbolProvider) : RustSy override fun symbolForOperationError(operation: OperationShape): Symbol = base.symbolForOperationError(operation) override fun symbolForEventStreamError(eventStream: UnionShape): Symbol = base.symbolForEventStreamError(eventStream) + override fun symbolForBuilder(shape: Shape): Symbol = base.symbolForBuilder(shape) } 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 08f6e3576c..fbab905dad 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 @@ -108,11 +108,12 @@ fun Shape.contextName(serviceShape: ServiceShape?): String { * derives for a given shape. */ open class SymbolVisitor( + settings: CoreRustSettings, override val model: Model, private val serviceShape: ServiceShape?, override val config: RustSymbolProviderConfig, ) : RustSymbolProvider, ShapeVisitor { - override val moduleProviderContext = ModuleProviderContext(model, serviceShape) + override val moduleProviderContext = ModuleProviderContext(settings, model, serviceShape) private val nullableIndex = NullableIndex.of(model) override fun toSymbol(shape: Shape): Symbol { @@ -131,6 +132,11 @@ open class SymbolVisitor( module.toType().resolve("${symbol.name}Error").toSymbol().toBuilder().locatedIn(module).build() } + override fun symbolForBuilder(shape: Shape): Symbol = toSymbol(shape).let { symbol -> + val module = moduleForBuilder(shape) + module.toType().resolve(config.nameBuilderFor(symbol)).toSymbol().toBuilder().locatedIn(module).build() + } + override fun toMemberName(shape: MemberShape): String { val container = model.expectShape(shape.container) return when { diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt index 18700df815..16cb28b803 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderGenerator.kt @@ -12,11 +12,8 @@ import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.Attribute import software.amazon.smithy.rust.codegen.core.rustlang.Attribute.Companion.derive -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.RustWriter -import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.asArgument import software.amazon.smithy.rust.codegen.core.rustlang.asOptional @@ -42,9 +39,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizat import software.amazon.smithy.rust.codegen.core.smithy.defaultValue import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.isOptional -import software.amazon.smithy.rust.codegen.core.smithy.locatedIn import software.amazon.smithy.rust.codegen.core.smithy.makeOptional -import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticInputTrait import software.amazon.smithy.rust.codegen.core.util.dq @@ -76,22 +71,6 @@ sealed class BuilderSection(name: String) : Section(name) { /** Customizations for BuilderGenerator */ abstract class BuilderCustomization : NamedCustomization() -fun builderSymbolFn(symbolProvider: RustSymbolProvider): (StructureShape) -> Symbol = { structureShape -> - structureShape.builderSymbol(symbolProvider) -} - -fun StructureShape.builderSymbol(symbolProvider: RustSymbolProvider): Symbol { - val structureSymbol = symbolProvider.toSymbol(this) - val builderNamespace = RustReservedWords.escapeIfNeeded(structureSymbol.name.toSnakeCase()) - val module = RustModule.new(builderNamespace, visibility = Visibility.PUBLIC, parent = structureSymbol.module(), inline = true) - val rustType = RustType.Opaque("Builder", module.fullyQualifiedPath()) - return Symbol.builder() - .rustType(rustType) - .name(rustType.name) - .locatedIn(module) - .build() -} - fun RuntimeConfig.operationBuildError() = RuntimeType.operationModule(this).resolve("error::BuildError") fun RuntimeConfig.serializationError() = RuntimeType.operationModule(this).resolve("error::SerializationError") @@ -133,29 +112,34 @@ class BuilderGenerator( // generate a fallible builder. !it.isOptional() && !it.canUseDefault() } + + fun renderConvenienceMethod(implBlock: RustWriter, symbolProvider: RustSymbolProvider, shape: StructureShape) { + implBlock.docs("Creates a new builder-style object to manufacture #D.", symbolProvider.toSymbol(shape)) + symbolProvider.symbolForBuilder(shape).also { builderSymbol -> + implBlock.rustBlock("pub fn builder() -> #T", builderSymbol) { + write("#T::default()", builderSymbol) + } + } + } } private val runtimeConfig = symbolProvider.config.runtimeConfig private val members: List = shape.allMembers.values.toList() private val structureSymbol = symbolProvider.toSymbol(shape) - private val builderSymbol = shape.builderSymbol(symbolProvider) + private val builderSymbol = symbolProvider.symbolForBuilder(shape) private val metadata = structureSymbol.expectRustMetadata() // Filter out any derive that isn't Debug, PartialEq, or Clone. Then add a Default derive private val builderDerives = metadata.derives.filter { it == RuntimeType.Debug || it == RuntimeType.PartialEq || it == RuntimeType.Clone } + RuntimeType.Default - private val builderName = "Builder" + private val builderName = symbolProvider.symbolForBuilder(shape).name fun render(writer: RustWriter) { - val symbol = symbolProvider.toSymbol(shape) - writer.docs("See #D.", symbol) - writer.withInlineModule(shape.builderSymbol(symbolProvider).module()) { - // Matching derives to the main structure + `Default` since we are a builder and everything is optional. - renderBuilder(this) - if (!structureSymbol.expectRustMetadata().hasDebugDerive()) { - renderDebugImpl(this) - } + // Matching derives to the main structure + `Default` since we are a builder and everything is optional. + renderBuilder(writer) + if (!structureSymbol.expectRustMetadata().hasDebugDerive()) { + renderDebugImpl(writer) } } @@ -180,13 +164,6 @@ class BuilderGenerator( OperationBuildError(runtimeConfig).missingField(field, detailedMessage)(this) } - fun renderConvenienceMethod(implBlock: RustWriter) { - implBlock.docs("Creates a new builder-style object to manufacture #D.", structureSymbol) - implBlock.rustBlock("pub fn builder() -> #T", builderSymbol) { - write("#T::default()", builderSymbol) - } - } - // TODO(EventStream): [DX] Consider updating builders to take EventInputStream as Into private fun renderBuilderMember(writer: RustWriter, memberName: String, memberSymbol: Symbol) { // Builder members are crate-public to enable using them directly in serializers/deserializers. 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 6a66296c8f..c784e8d1e6 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 @@ -115,8 +115,6 @@ class HttpBindingGenerator( private val codegenContext: CodegenContext, private val symbolProvider: SymbolProvider, private val operationShape: OperationShape, - /** Function that maps a StructureShape into its builder symbol */ - private val builderSymbol: (StructureShape) -> Symbol, private val customizations: List = listOf(), ) { private val runtimeConfig = codegenContext.runtimeConfig @@ -256,7 +254,6 @@ class HttpBindingGenerator( codegenContext, operationShape, targetShape, - builderSymbol, ).render() rustTemplate( """ diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsJson.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsJson.kt index 6ed98c4de3..9bc32bfa5c 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsJson.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsJson.kt @@ -19,7 +19,6 @@ 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.RuntimeType -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbolFn import software.amazon.smithy.rust.codegen.core.smithy.generators.serializationError import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.JsonParserGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.StructuredDataParserGenerator @@ -152,7 +151,6 @@ open class AwsJson( codegenContext, httpBindingResolver, ::awsJsonFieldName, - builderSymbolFn(codegenContext.symbolProvider), ) } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQuery.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQuery.kt index f5728510e0..1914076175 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQuery.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQuery.kt @@ -6,11 +6,9 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols import software.amazon.smithy.aws.traits.protocols.AwsQueryErrorTrait -import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model import software.amazon.smithy.model.pattern.UriPattern import software.amazon.smithy.model.shapes.OperationShape -import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.shapes.ToShapeId import software.amazon.smithy.model.traits.HttpTrait import software.amazon.smithy.model.traits.TimestampFormatTrait @@ -19,7 +17,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.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.AwsQueryParserGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.StructuredDataParserGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.serialize.AwsQuerySerializerGenerator @@ -56,11 +53,8 @@ class AwsQueryProtocol(private val codegenContext: CodegenContext) : Protocol { override val defaultTimestampFormat: TimestampFormatTrait.Format = TimestampFormatTrait.Format.DATE_TIME - override fun structuredDataParser(operationShape: OperationShape): StructuredDataParserGenerator { - fun builderSymbol(shape: StructureShape): Symbol = - shape.builderSymbol(codegenContext.symbolProvider) - return AwsQueryParserGenerator(codegenContext, awsQueryErrors, ::builderSymbol) - } + override fun structuredDataParser(operationShape: OperationShape): StructuredDataParserGenerator = + AwsQueryParserGenerator(codegenContext, awsQueryErrors) override fun structuredDataSerializer(operationShape: OperationShape): StructuredDataSerializerGenerator = AwsQuerySerializerGenerator(codegenContext) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/Ec2Query.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/Ec2Query.kt index 473ec06f52..8e6c6c063c 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/Ec2Query.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/Ec2Query.kt @@ -5,10 +5,8 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols -import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.pattern.UriPattern import software.amazon.smithy.model.shapes.OperationShape -import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.traits.HttpTrait import software.amazon.smithy.model.traits.TimestampFormatTrait import software.amazon.smithy.rust.codegen.core.rustlang.RustModule @@ -16,7 +14,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.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.Ec2QueryParserGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.StructuredDataParserGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.serialize.Ec2QuerySerializerGenerator @@ -48,9 +45,7 @@ class Ec2QueryProtocol(private val codegenContext: CodegenContext) : Protocol { override val defaultTimestampFormat: TimestampFormatTrait.Format = TimestampFormatTrait.Format.DATE_TIME override fun structuredDataParser(operationShape: OperationShape): StructuredDataParserGenerator { - fun builderSymbol(shape: StructureShape): Symbol = - shape.builderSymbol(codegenContext.symbolProvider) - return Ec2QueryParserGenerator(codegenContext, ec2QueryErrors, ::builderSymbol) + return Ec2QueryParserGenerator(codegenContext, ec2QueryErrors) } override fun structuredDataSerializer(operationShape: OperationShape): StructuredDataSerializerGenerator = diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestJson.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestJson.kt index 665d9dee85..0bbb1c5f5c 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestJson.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestJson.kt @@ -5,7 +5,6 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols -import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.OperationShape @@ -20,7 +19,6 @@ 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.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.JsonParserGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.StructuredDataParserGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.serialize.JsonSerializerGenerator @@ -94,9 +92,7 @@ open class RestJson(val codegenContext: CodegenContext) : Protocol { listOf("x-amzn-errortype" to errorShape.id.toString()) override fun structuredDataParser(operationShape: OperationShape): StructuredDataParserGenerator { - fun builderSymbol(shape: StructureShape): Symbol = - shape.builderSymbol(codegenContext.symbolProvider) - return JsonParserGenerator(codegenContext, httpBindingResolver, ::restJsonFieldName, ::builderSymbol) + return JsonParserGenerator(codegenContext, httpBindingResolver, ::restJsonFieldName) } override fun structuredDataSerializer(operationShape: OperationShape): StructuredDataSerializerGenerator = diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt index 3b4d10ddbf..eba2358999 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt @@ -6,16 +6,13 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols import software.amazon.smithy.aws.traits.protocols.RestXmlTrait -import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.OperationShape -import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.traits.TimestampFormatTrait 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.rustBlockTemplate 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.generators.builderSymbol import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.RestXmlParserGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.StructuredDataParserGenerator import software.amazon.smithy.rust.codegen.core.smithy.protocols.serialize.StructuredDataSerializerGenerator @@ -46,9 +43,7 @@ open class RestXml(val codegenContext: CodegenContext) : Protocol { TimestampFormatTrait.Format.DATE_TIME override fun structuredDataParser(operationShape: OperationShape): StructuredDataParserGenerator { - fun builderSymbol(shape: StructureShape): Symbol = - shape.builderSymbol(codegenContext.symbolProvider) - return RestXmlParserGenerator(codegenContext, restXmlErrors, ::builderSymbol) + return RestXmlParserGenerator(codegenContext, restXmlErrors) } override fun structuredDataSerializer(operationShape: OperationShape): StructuredDataSerializerGenerator { diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGenerator.kt index 2dbe6d72fb..2fc1f5c649 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGenerator.kt @@ -5,8 +5,6 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols.parse -import software.amazon.smithy.codegen.core.Symbol -import software.amazon.smithy.model.shapes.StructureShape 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 @@ -29,12 +27,10 @@ import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType class AwsQueryParserGenerator( codegenContext: CodegenContext, xmlErrors: RuntimeType, - builderSymbol: (shape: StructureShape) -> Symbol, private val xmlBindingTraitParserGenerator: XmlBindingTraitParserGenerator = XmlBindingTraitParserGenerator( codegenContext, xmlErrors, - builderSymbol, ) { context, inner -> val operationName = codegenContext.symbolProvider.toSymbol(context.shape).name val responseWrapperName = operationName + "Response" diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGenerator.kt index e7be46f3bd..00cdc784d1 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGenerator.kt @@ -5,8 +5,6 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols.parse -import software.amazon.smithy.codegen.core.Symbol -import software.amazon.smithy.model.shapes.StructureShape 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 @@ -27,12 +25,10 @@ import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType class Ec2QueryParserGenerator( codegenContext: CodegenContext, xmlErrors: RuntimeType, - builderSymbol: (shape: StructureShape) -> Symbol, private val xmlBindingTraitParserGenerator: XmlBindingTraitParserGenerator = XmlBindingTraitParserGenerator( codegenContext, xmlErrors, - builderSymbol, ) { context, inner -> val operationName = codegenContext.symbolProvider.toSymbol(context.shape).name val responseWrapperName = operationName + "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 253a5d2410..ae80c72c06 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 @@ -48,8 +48,6 @@ class EventStreamUnmarshallerGenerator( codegenContext: CodegenContext, private val operationShape: OperationShape, private val unionShape: UnionShape, - /** Function that maps a StructureShape into its builder symbol */ - private val builderSymbol: (StructureShape) -> Symbol, ) { private val model = codegenContext.model private val symbolProvider = codegenContext.symbolProvider @@ -192,7 +190,7 @@ class EventStreamUnmarshallerGenerator( ) } else -> { - rust("let mut builder = #T::default();", builderSymbol(unionStruct)) + rust("let mut builder = #T::default();", symbolProvider.symbolForBuilder(unionStruct)) val payloadMember = unionStruct.members().firstOrNull { it.hasTrait() } if (payloadMember != null) { renderUnmarshallEventPayload(payloadMember) @@ -335,7 +333,7 @@ class EventStreamUnmarshallerGenerator( val target = model.expectShape(member.target, StructureShape::class.java) val parser = protocol.structuredDataParser(operationShape).errorParser(target) if (parser != null) { - rust("let mut builder = #T::default();", builderSymbol(target)) + rust("let mut builder = #T::default();", symbolProvider.symbolForBuilder(target)) rustTemplate( """ builder = #{parser}(&message.payload()[..], builder) @@ -356,7 +354,7 @@ class EventStreamUnmarshallerGenerator( val target = model.expectShape(member.target, StructureShape::class.java) val parser = protocol.structuredDataParser(operationShape).errorParser(target) val mut = if (parser != null) { " mut" } else { "" } - rust("let$mut builder = #T::default();", builderSymbol(target)) + rust("let$mut builder = #T::default();", symbolProvider.symbolForBuilder(target)) if (parser != null) { rustTemplate( """ diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt index f13c1d4821..f7a38f0fb2 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/JsonParserGenerator.kt @@ -28,7 +28,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.Writable import software.amazon.smithy.rust.codegen.core.rustlang.escape -import software.amazon.smithy.rust.codegen.core.rustlang.render import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate @@ -77,8 +76,6 @@ class JsonParserGenerator( private val httpBindingResolver: HttpBindingResolver, /** Function that maps a MemberShape into a JSON field name */ private val jsonName: (MemberShape) -> String, - /** Function that maps a StructureShape into its builder symbol */ - private val builderSymbol: (StructureShape) -> Symbol, /** * Whether we should parse a value for a shape into its associated unconstrained type. For example, when the shape * is a `StructureShape`, we should construct and return a builder instead of building into the final `struct` the @@ -193,7 +190,7 @@ class JsonParserGenerator( } val outputShape = operationShape.outputShape(model) val fnName = symbolProvider.deserializeFunctionName(operationShape) - return structureParser(fnName, builderSymbol(outputShape), httpDocumentMembers) + return structureParser(fnName, symbolProvider.symbolForBuilder(outputShape), httpDocumentMembers) } override fun errorParser(errorShape: StructureShape): RuntimeType? { @@ -201,7 +198,7 @@ class JsonParserGenerator( return null } val fnName = symbolProvider.deserializeFunctionName(errorShape) + "_json_err" - return structureParser(fnName, builderSymbol(errorShape), errorShape.members().toList()) + return structureParser(fnName, symbolProvider.symbolForBuilder(errorShape), errorShape.members().toList()) } private fun orEmptyJson(): RuntimeType = RuntimeType.forInlineFun("or_empty_doc", jsonDeserModule) { @@ -225,7 +222,7 @@ class JsonParserGenerator( } val inputShape = operationShape.inputShape(model) val fnName = symbolProvider.deserializeFunctionName(operationShape) - return structureParser(fnName, builderSymbol(inputShape), includedMembers) + return structureParser(fnName, symbolProvider.symbolForBuilder(inputShape), includedMembers) } private fun RustWriter.expectEndOfTokenStream() { @@ -495,7 +492,11 @@ class JsonParserGenerator( ) { startObjectOrNull { Attribute.AllowUnusedMut.render(this) - rustTemplate("let mut builder = #{Builder}::default();", *codegenScope, "Builder" to builderSymbol(shape)) + rustTemplate( + "let mut builder = #{Builder}::default();", + *codegenScope, + "Builder" to symbolProvider.symbolForBuilder(shape), + ) deserializeStructInner(shape.members()) // Only call `build()` if the builder is not fallible. Otherwise, return the builder. if (returnSymbolToParse.isUnconstrained) { diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/RestXmlParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/RestXmlParserGenerator.kt index f09598e6f1..d37413f29f 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/RestXmlParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/RestXmlParserGenerator.kt @@ -5,8 +5,6 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols.parse -import software.amazon.smithy.codegen.core.Symbol -import software.amazon.smithy.model.shapes.StructureShape 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 @@ -19,12 +17,10 @@ import software.amazon.smithy.rust.codegen.core.util.orNull class RestXmlParserGenerator( codegenContext: CodegenContext, xmlErrors: RuntimeType, - builderSymbol: (shape: StructureShape) -> Symbol, private val xmlBindingTraitParserGenerator: XmlBindingTraitParserGenerator = XmlBindingTraitParserGenerator( codegenContext, xmlErrors, - builderSymbol, ) { context, inner -> val shapeName = context.outputShapeName // Get the non-synthetic version of the outputShape and check to see if it has the `AllowInvalidXmlRoot` trait diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt index 2615123874..1a05bfbf33 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt @@ -7,7 +7,6 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols.parse import software.amazon.smithy.aws.traits.customizations.S3UnwrappedXmlOutputTrait 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.knowledge.HttpBinding import software.amazon.smithy.model.knowledge.HttpBindingIndex @@ -71,7 +70,6 @@ data class OperationWrapperContext( class XmlBindingTraitParserGenerator( codegenContext: CodegenContext, private val xmlErrors: RuntimeType, - private val builderSymbol: (shape: StructureShape) -> Symbol, private val writeOperationWrapper: RustWriter.(OperationWrapperContext, OperationInnerWriteable) -> Unit, ) : StructuredDataParserGenerator { @@ -190,7 +188,7 @@ class XmlBindingTraitParserGenerator( Attribute.AllowUnusedMut.render(this) rustBlock( "pub fn $fnName(inp: &[u8], mut builder: #1T) -> Result<#1T, #2T>", - builderSymbol(outputShape), + symbolProvider.symbolForBuilder(outputShape), xmlDecodeError, ) { rustTemplate( @@ -223,7 +221,7 @@ class XmlBindingTraitParserGenerator( Attribute.AllowUnusedMut.render(this) rustBlock( "pub fn $fnName(inp: &[u8], mut builder: #1T) -> Result<#1T, #2T>", - builderSymbol(errorShape), + symbolProvider.symbolForBuilder(errorShape), xmlDecodeError, ) { val members = errorShape.errorXmlMembers() @@ -257,7 +255,7 @@ class XmlBindingTraitParserGenerator( Attribute.AllowUnusedMut.render(this) rustBlock( "pub fn $fnName(inp: &[u8], mut builder: #1T) -> Result<#1T, #2T>", - builderSymbol(inputShape), + symbolProvider.symbolForBuilder(inputShape), xmlDecodeError, ) { rustTemplate( 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 c038ff5d52..cfa92fb70c 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 @@ -140,12 +140,10 @@ object EventStreamTestTools { } val inputOutput = model.lookup("test#TestStreamInputOutput") project.withModule(codegenContext.symbolProvider.moduleForShape(inputOutput)) { - recursivelyGenerateModels(model, symbolProvider, inputOutput, this, codegenTarget) + recursivelyGenerateModels(project, model, symbolProvider, inputOutput, this, codegenTarget) } operationShape.outputShape(model).also { outputShape -> - project.moduleFor(outputShape) { - outputShape.renderWithModelBuilder(model, symbolProvider, this) - } + outputShape.renderWithModelBuilder(model, symbolProvider, project) } return TestEventStreamProject( model, @@ -158,6 +156,7 @@ object EventStreamTestTools { } private fun recursivelyGenerateModels( + rustCrate: RustCrate, model: Model, symbolProvider: RustSymbolProvider, shape: Shape, @@ -170,7 +169,7 @@ object EventStreamTestTools { } val target = model.expectShape(member.target) when (target) { - is StructureShape -> target.renderWithModelBuilder(model, symbolProvider, writer) + is StructureShape -> target.renderWithModelBuilder(model, symbolProvider, rustCrate) is UnionShape -> UnionGenerator( model, symbolProvider, @@ -180,7 +179,7 @@ object EventStreamTestTools { ).render() else -> TODO("EventStreamTestTools doesn't support rendering $target") } - recursivelyGenerateModels(model, symbolProvider, target, writer, mode) + recursivelyGenerateModels(rustCrate, model, symbolProvider, target, writer, mode) } } } 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 18c935d707..574e9daa04 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 @@ -5,6 +5,7 @@ package software.amazon.smithy.rust.codegen.core.testutil +import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model import software.amazon.smithy.model.knowledge.NullableIndex import software.amazon.smithy.model.shapes.OperationShape @@ -17,7 +18,8 @@ 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.rustlang.RustReservedWords +import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.rustlang.implBlock import software.amazon.smithy.rust.codegen.core.smithy.BaseSymbolMetadataProvider import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext @@ -28,16 +30,19 @@ import software.amazon.smithy.rust.codegen.core.smithy.ModuleProvider import software.amazon.smithy.rust.codegen.core.smithy.ModuleProviderContext 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.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProviderConfig import software.amazon.smithy.rust.codegen.core.smithy.SymbolVisitor 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.module 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 software.amazon.smithy.rust.codegen.core.util.toSnakeCase import java.io.File val TestRuntimeConfig = @@ -81,6 +86,16 @@ private object CodegenCoreTestModules { context: ModuleProviderContext, eventStream: UnionShape, ): RustModule.LeafModule = ErrorsTestModule + + override fun moduleForBuilder(context: ModuleProviderContext, shape: Shape, symbol: Symbol): RustModule.LeafModule { + val builderNamespace = RustReservedWords.escapeIfNeeded("test_" + symbol.name.toSnakeCase()) + return RustModule.new( + builderNamespace, + visibility = Visibility.PUBLIC, + parent = symbol.module(), + inline = true, + ) + } } } @@ -124,6 +139,7 @@ fun String.asSmithyModel(sourceLocation: String? = null, smithyVersion: String = // Intentionally only visible to codegen-core since the other modules have their own symbol providers internal fun testSymbolProvider(model: Model): RustSymbolProvider = SymbolVisitor( + testRustSettings(), model, ServiceShape.builder().version("test").id("test#Service").build(), TestRustSymbolProviderConfig, @@ -153,13 +169,16 @@ internal fun testCodegenContext( fun StructureShape.renderWithModelBuilder( model: Model, symbolProvider: RustSymbolProvider, - writer: RustWriter, + rustCrate: RustCrate, ) { - StructureGenerator(model, symbolProvider, writer, this, emptyList()).render() - BuilderGenerator(model, symbolProvider, this, emptyList()).also { builderGen -> - builderGen.render(writer) - writer.implBlock(symbolProvider.toSymbol(this)) { - builderGen.renderConvenienceMethod(this) + val struct = this + rustCrate.withModule(symbolProvider.moduleForShape(struct)) { + StructureGenerator(model, symbolProvider, this, struct, emptyList()).render() + implBlock(symbolProvider.toSymbol(struct)) { + BuilderGenerator.renderConvenienceMethod(this, symbolProvider, struct) } } + rustCrate.withModule(symbolProvider.moduleForBuilder(struct)) { + BuilderGenerator(model, symbolProvider, struct, emptyList()).render(this) + } } 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 563dc2f454..0cbd3fcbb1 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 @@ -16,11 +16,12 @@ import software.amazon.smithy.rust.codegen.core.smithy.WrappingSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.renamedFrom import software.amazon.smithy.rust.codegen.core.testutil.TestRustSymbolProviderConfig import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel +import software.amazon.smithy.rust.codegen.core.testutil.testRustSettings import software.amazon.smithy.rust.codegen.core.util.lookup internal class RustReservedWordSymbolProviderTest { private class TestSymbolProvider(model: Model) : - WrappingSymbolProvider(SymbolVisitor(model, null, TestRustSymbolProviderConfig)) + WrappingSymbolProvider(SymbolVisitor(testRustSettings(), model, null, TestRustSymbolProviderConfig)) @Test fun `structs are escaped`() { 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 d3f0232720..ec107f3fcb 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 @@ -34,13 +34,9 @@ internal class BuilderGeneratorTest { rust("##![allow(deprecated)]") StructureGenerator(model, provider, this, inner, emptyList()).render() StructureGenerator(model, provider, this, struct, emptyList()).render() - BuilderGenerator(model, provider, struct, emptyList()).also { builderGen -> - builderGen.render(this) - implBlock(provider.toSymbol(struct)) { - builderGen.renderConvenienceMethod(this) - } + implBlock(provider.toSymbol(struct)) { + BuilderGenerator.renderConvenienceMethod(this, provider, struct) } - unitTest("generate_builders") { rust( """ @@ -51,6 +47,9 @@ internal class BuilderGeneratorTest { ) } } + project.withModule(provider.moduleForBuilder(struct)) { + BuilderGenerator(model, provider, struct, emptyList()).render(this) + } project.compileAndTest() } @@ -63,15 +62,13 @@ internal class BuilderGeneratorTest { } } val project = TestWorkspace.testProject(provider) + project.moduleFor(StructureGeneratorTest.struct) { AllowDeprecated.render(this) StructureGenerator(model, provider, this, inner, emptyList()).render() StructureGenerator(model, provider, this, struct, emptyList()).render() - BuilderGenerator(model, provider, struct, emptyList()).also { builderGenerator -> - builderGenerator.render(this) - implBlock(provider.toSymbol(struct)) { - builderGenerator.renderConvenienceMethod(this) - } + implBlock(provider.toSymbol(struct)) { + BuilderGenerator.renderConvenienceMethod(this, provider, struct) } unitTest("generate_fallible_builders") { rust( @@ -83,6 +80,9 @@ internal class BuilderGeneratorTest { ) } } + project.withModule(provider.moduleForBuilder(struct)) { + BuilderGenerator(model, provider, struct, emptyList()).render(this) + } project.compileAndTest() } @@ -92,11 +92,8 @@ internal class BuilderGeneratorTest { val project = TestWorkspace.testProject(provider) project.moduleFor(credentials) { StructureGenerator(model, provider, this, credentials, emptyList()).render() - BuilderGenerator(model, provider, credentials, emptyList()).also { builderGen -> - builderGen.render(this) - implBlock(provider.toSymbol(credentials)) { - builderGen.renderConvenienceMethod(this) - } + implBlock(provider.toSymbol(credentials)) { + BuilderGenerator.renderConvenienceMethod(this, provider, credentials) } unitTest("sensitive_fields") { rust( @@ -110,6 +107,9 @@ internal class BuilderGeneratorTest { ) } } + project.withModule(provider.moduleForBuilder(credentials)) { + BuilderGenerator(model, provider, credentials, emptyList()).render(this) + } project.compileAndTest() } @@ -119,11 +119,8 @@ internal class BuilderGeneratorTest { val project = TestWorkspace.testProject(provider) project.moduleFor(secretStructure) { StructureGenerator(model, provider, this, secretStructure, emptyList()).render() - BuilderGenerator(model, provider, secretStructure, emptyList()).also { builderGen -> - builderGen.render(this) - implBlock(provider.toSymbol(secretStructure)) { - builderGen.renderConvenienceMethod(this) - } + implBlock(provider.toSymbol(secretStructure)) { + BuilderGenerator.renderConvenienceMethod(this, provider, secretStructure) } unitTest("sensitive_struct") { rust( @@ -135,6 +132,9 @@ internal class BuilderGeneratorTest { ) } } + project.withModule(provider.moduleForBuilder(secretStructure)) { + BuilderGenerator(model, provider, secretStructure, emptyList()).render(this) + } 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 efb37235a2..c5d877394f 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 @@ -129,8 +129,8 @@ class InstantiatorTest { val data = Node.parse("""{ "bar": 10, "foo": "hello" }""") val project = TestWorkspace.testProject(model) + structure.renderWithModelBuilder(model, symbolProvider, project) project.moduleFor(structure) { - structure.renderWithModelBuilder(model, symbolProvider, this) unitTest("generate_struct_builders") { withBlock("let result = ", ";") { sut.render(this, structure, data) @@ -163,8 +163,8 @@ class InstantiatorTest { ) val project = TestWorkspace.testProject(model) + structure.renderWithModelBuilder(model, symbolProvider, project) project.moduleFor(structure) { - structure.renderWithModelBuilder(model, symbolProvider, this) unitTest("generate_builders_for_boxed_structs") { withBlock("let result = ", ";") { sut.render(this, structure, data) @@ -246,8 +246,8 @@ class InstantiatorTest { val inner = model.lookup("com.test#Inner") val project = TestWorkspace.testProject(model) + inner.renderWithModelBuilder(model, symbolProvider, project) project.moduleFor(inner) { - inner.renderWithModelBuilder(model, symbolProvider, this) unitTest("generate_maps_of_maps") { withBlock("let result = ", ";") { sut.render(this, model.lookup("com.test#NestedMap"), data) diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorImplGeneratorTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorImplGeneratorTest.kt index 7f3772ed95..678cc808b5 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorImplGeneratorTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorImplGeneratorTest.kt @@ -9,13 +9,11 @@ import org.junit.jupiter.api.Test import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.traits.ErrorTrait -import software.amazon.smithy.rust.codegen.core.rustlang.implBlock import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget -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.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.renderWithModelBuilder import software.amazon.smithy.rust.codegen.core.testutil.testSymbolProvider import software.amazon.smithy.rust.codegen.core.util.getTrait @@ -36,15 +34,9 @@ class ErrorImplGeneratorTest { val provider = testSymbolProvider(model) val project = TestWorkspace.testProject(provider) val errorShape = model.expectShape(ShapeId.from("com.test#MyError")) as StructureShape + errorShape.renderWithModelBuilder(model, provider, project) project.moduleFor(errorShape) { val errorTrait = errorShape.getTrait()!! - StructureGenerator(model, provider, this, errorShape, emptyList()).render() - BuilderGenerator(model, provider, errorShape, emptyList()).let { builderGen -> - implBlock(provider.toSymbol(errorShape)) { - builderGen.renderConvenienceMethod(this) - } - builderGen.render(this) - } ErrorImplGenerator(model, provider, this, errorShape, errorTrait, emptyList()).render(CodegenTarget.CLIENT) compileAndTest( """ 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 1f092ba71c..38beea1e1b 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 @@ -9,7 +9,6 @@ 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.smithy.RuntimeType -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbolFn 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.testutil.TestRuntimeConfig @@ -48,7 +47,6 @@ class AwsQueryParserGeneratorTest { val parserGenerator = AwsQueryParserGenerator( codegenContext, RuntimeType.wrappedXmlErrors(TestRuntimeConfig), - builderSymbolFn(symbolProvider), ) val operationParser = parserGenerator.operationParser(model.lookup("test#SomeOperation"))!! val project = TestWorkspace.testProject(testSymbolProvider(model)) @@ -64,21 +62,17 @@ class AwsQueryParserGeneratorTest { "#; - let output = ${format(operationParser)}(xml, test_output::some_operation_output::Builder::default()).unwrap().build(); + let output = ${format(operationParser)}(xml, test_output::SomeOperationOutput::builder()).unwrap().build(); assert_eq!(output.some_attribute, Some(5)); assert_eq!(output.some_val, Some("Some value".to_string())); """, ) } model.lookup("test#SomeOutput").also { struct -> - project.moduleFor(struct) { - struct.renderWithModelBuilder(model, symbolProvider, this) - } + struct.renderWithModelBuilder(model, symbolProvider, project) } model.lookup("test#SomeOperation").outputShape(model).also { output -> - project.moduleFor(output) { - output.renderWithModelBuilder(model, symbolProvider, this) - } + output.renderWithModelBuilder(model, symbolProvider, project) } 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 04dab966b5..9a51b07253 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 @@ -9,7 +9,6 @@ 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.smithy.RuntimeType -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbolFn 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.testutil.TestRuntimeConfig @@ -48,7 +47,6 @@ class Ec2QueryParserGeneratorTest { val parserGenerator = Ec2QueryParserGenerator( codegenContext, RuntimeType.wrappedXmlErrors(TestRuntimeConfig), - builderSymbolFn(symbolProvider), ) val operationParser = parserGenerator.operationParser(model.lookup("test#SomeOperation"))!! val project = TestWorkspace.testProject(testSymbolProvider(model)) @@ -62,7 +60,7 @@ class Ec2QueryParserGeneratorTest { Some value "#; - let output = ${format(operationParser)}(xml, test_output::some_operation_output::Builder::default()).unwrap().build(); + let output = ${format(operationParser)}(xml, test_output::SomeOperationOutput::builder()).unwrap().build(); assert_eq!(output.some_attribute, Some(5)); assert_eq!(output.some_val, Some("Some value".to_string())); """, @@ -70,15 +68,11 @@ class Ec2QueryParserGeneratorTest { } model.lookup("test#SomeOutput").also { struct -> - project.moduleFor(struct) { - struct.renderWithModelBuilder(model, symbolProvider, this) - } + struct.renderWithModelBuilder(model, symbolProvider, project) } model.lookup("test#SomeOperation").outputShape(model).also { output -> - project.moduleFor(output) { - output.renderWithModelBuilder(model, symbolProvider, this) - } + output.renderWithModelBuilder(model, symbolProvider, project) } 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 2530947261..79435b5e9b 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 @@ -6,14 +6,12 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols.parse import org.junit.jupiter.api.Test -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.smithy.generators.EnumGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.TestEnumType import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbol import software.amazon.smithy.rust.codegen.core.smithy.protocols.HttpTraitHttpBindingResolver import software.amazon.smithy.rust.codegen.core.smithy.protocols.ProtocolContentTypes import software.amazon.smithy.rust.codegen.core.smithy.protocols.restJsonFieldName @@ -117,14 +115,11 @@ class JsonParserGeneratorTest { val model = RecursiveShapeBoxer().transform(OperationNormalizer.transform(baseModel)) val codegenContext = testCodegenContext(model) val symbolProvider = codegenContext.symbolProvider - fun builderSymbol(shape: StructureShape): Symbol = - shape.builderSymbol(symbolProvider) val parserGenerator = JsonParserGenerator( codegenContext, HttpTraitHttpBindingResolver(model, ProtocolContentTypes.consistent("application/json")), ::restJsonFieldName, - ::builderSymbol, ) val operationGenerator = parserGenerator.operationParser(model.lookup("test#Op")) val payloadGenerator = parserGenerator.payloadParser(model.lookup("test#OpOutput\$top")) @@ -150,7 +145,7 @@ class JsonParserGeneratorTest { } "#; - let output = ${format(operationGenerator!!)}(json, test_output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationGenerator!!)}(json, test_output::OpOutput::builder()).unwrap().build(); let top = output.top.expect("top"); assert_eq!(Some(45), top.extra); assert_eq!(Some("something".to_string()), top.field); @@ -161,7 +156,7 @@ class JsonParserGeneratorTest { "empty_body", """ // empty body - let output = ${format(operationGenerator)}(b"", test_output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationGenerator)}(b"", test_output::OpOutput::builder()).unwrap().build(); assert_eq!(output.top, None); """, ) @@ -170,7 +165,7 @@ class JsonParserGeneratorTest { """ // unknown variant let input = br#"{ "top": { "choice": { "somenewvariant": "data" } } }"#; - let output = ${format(operationGenerator)}(input, test_output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationGenerator)}(input, test_output::OpOutput::builder()).unwrap().build(); assert!(output.top.unwrap().choice.unwrap().is_unknown()); """, ) @@ -179,7 +174,7 @@ class JsonParserGeneratorTest { "empty_error", """ // empty error - let error_output = ${format(errorParser!!)}(b"", test_error::error::Builder::default()).unwrap().build(); + let error_output = ${format(errorParser!!)}(b"", test_error::Error::builder()).unwrap().build(); assert_eq!(error_output.message, None); """, ) @@ -188,29 +183,25 @@ class JsonParserGeneratorTest { "error_with_message", """ // error with message - let error_output = ${format(errorParser)}(br#"{"message": "hello"}"#, test_error::error::Builder::default()).unwrap().build(); + let error_output = ${format(errorParser)}(br#"{"message": "hello"}"#, test_error::Error::builder()).unwrap().build(); assert_eq!(error_output.message.expect("message should be set"), "hello"); """, ) } model.lookup("test#Top").also { top -> + top.renderWithModelBuilder(model, symbolProvider, project) + model.lookup("test#EmptyStruct").renderWithModelBuilder(model, symbolProvider, project) 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) } } model.lookup("test#Op").outputShape(model).also { output -> - project.moduleFor(output) { - output.renderWithModelBuilder(model, symbolProvider, this) - } + output.renderWithModelBuilder(model, symbolProvider, project) } model.lookup("test#Error").also { error -> - project.moduleFor(error) { - error.renderWithModelBuilder(model, symbolProvider, this) - } + error.renderWithModelBuilder(model, symbolProvider, project) } 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 ade2ab1c4b..47f310e83d 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 @@ -15,7 +15,6 @@ 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 import software.amazon.smithy.rust.codegen.core.smithy.generators.UnionGenerator -import software.amazon.smithy.rust.codegen.core.smithy.generators.builderSymbolFn 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.testutil.TestRuntimeConfig @@ -100,7 +99,6 @@ internal class XmlBindingTraitParserGeneratorTest { val parserGenerator = XmlBindingTraitParserGenerator( codegenContext, RuntimeType.wrappedXmlErrors(TestRuntimeConfig), - builderSymbolFn(symbolProvider), ) { _, inner -> inner("decoder") } val operationParser = parserGenerator.operationParser(model.lookup("test#Op"))!! @@ -122,7 +120,7 @@ internal class XmlBindingTraitParserGeneratorTest { hey "##; - let output = ${format(operationParser)}(xml, test_output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationParser)}(xml, test_output::OpOutput::builder()).unwrap().build(); let mut map = std::collections::HashMap::new(); map.insert("some key".to_string(), #{Choice}::S("hello".to_string())); assert_eq!(output.choice, Some(#{Choice}::FlatMap(map))); @@ -152,7 +150,7 @@ internal class XmlBindingTraitParserGeneratorTest { "##; - let output = ${format(operationParser)}(xml, test_output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationParser)}(xml, test_output::OpOutput::builder()).unwrap().build(); let mut map = std::collections::HashMap::new(); map.insert("some key".to_string(), #{Choice}::S("hello".to_string())); assert_eq!(output.choice, Some(#{Choice}::FlatMap(map))); @@ -181,7 +179,7 @@ internal class XmlBindingTraitParserGeneratorTest { "#; - ${format(operationParser)}(xml, test_output::op_output::Builder::default()).expect("unknown union variant does not cause failure"); + ${format(operationParser)}(xml, test_output::OpOutput::builder()).expect("unknown union variant does not cause failure"); """, ) unitTest( @@ -198,15 +196,14 @@ internal class XmlBindingTraitParserGeneratorTest { "#; - let output = ${format(operationParser)}(xml, test_output::op_output::Builder::default()).unwrap().build(); + let output = ${format(operationParser)}(xml, test_output::OpOutput::builder()).unwrap().build(); assert!(output.choice.unwrap().is_unknown()); """, ) } model.lookup("test#Top").also { top -> + top.renderWithModelBuilder(model, symbolProvider, project) 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) @@ -215,9 +212,7 @@ internal class XmlBindingTraitParserGeneratorTest { } model.lookup("test#Op").outputShape(model).also { out -> - project.moduleFor(out) { - out.renderWithModelBuilder(model, symbolProvider, this) - } + out.renderWithModelBuilder(model, symbolProvider, project) } 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 a7f2519f05..ad44554e36 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 @@ -133,8 +133,8 @@ class AwsQuerySerializerGeneratorTest { ) } model.lookup("test#Top").also { top -> + top.renderWithModelBuilder(model, symbolProvider, project) project.moduleFor(top) { - top.renderWithModelBuilder(model, symbolProvider, this) UnionGenerator( model, symbolProvider, @@ -148,9 +148,7 @@ class AwsQuerySerializerGeneratorTest { } model.lookup("test#Op").inputShape(model).also { input -> - project.moduleFor(input) { - input.renderWithModelBuilder(model, symbolProvider, this) - } + input.renderWithModelBuilder(model, symbolProvider, project) } 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 2663fd271b..2436aff706 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 @@ -126,8 +126,8 @@ class Ec2QuerySerializerGeneratorTest { ) } model.lookup("test#Top").also { top -> + top.renderWithModelBuilder(model, symbolProvider, project) 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) @@ -135,9 +135,7 @@ class Ec2QuerySerializerGeneratorTest { } model.lookup("test#Op").inputShape(model).also { input -> - project.moduleFor(input) { - input.renderWithModelBuilder(model, symbolProvider, this) - } + input.renderWithModelBuilder(model, symbolProvider, project) } 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 5e94e73432..23c27f331b 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 @@ -142,8 +142,8 @@ class JsonSerializerGeneratorTest { ) } model.lookup("test#Top").also { top -> + top.renderWithModelBuilder(model, symbolProvider, project) 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) @@ -151,9 +151,7 @@ class JsonSerializerGeneratorTest { } model.lookup("test#Op").inputShape(model).also { input -> - project.moduleFor(input) { - input.renderWithModelBuilder(model, symbolProvider, this) - } + input.renderWithModelBuilder(model, symbolProvider, project) } 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 1bff7855e9..a695d2a401 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 @@ -146,17 +146,15 @@ internal class XmlBindingTraitSerializerGeneratorTest { ) } model.lookup("test#Top").also { top -> + top.renderWithModelBuilder(model, symbolProvider, project) 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) } } model.lookup("test#Op").inputShape(model).also { input -> - project.moduleFor(input) { - input.renderWithModelBuilder(model, symbolProvider, this) - } + input.renderWithModelBuilder(model, symbolProvider, project) } project.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 7a3cff39d3..51fdb95c8c 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 @@ -30,6 +30,7 @@ import software.amazon.smithy.rust.codegen.server.python.smithy.generators.Pytho 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.ServerRustSettings 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 @@ -74,14 +75,16 @@ class PythonServerCodegenVisitor( settings = settings.copy(codegenConfig = settings.codegenConfig.copy(publicConstrainedTypes = false)) fun baseSymbolProviderFactory( + settings: ServerRustSettings, model: Model, serviceShape: ServiceShape, rustSymbolProviderConfig: RustSymbolProviderConfig, publicConstrainedTypes: Boolean, includeConstraintShapeProvider: Boolean, - ) = RustServerCodegenPythonPlugin.baseSymbolProvider(model, serviceShape, rustSymbolProviderConfig, publicConstrainedTypes) + ) = RustServerCodegenPythonPlugin.baseSymbolProvider(settings, model, serviceShape, rustSymbolProviderConfig, publicConstrainedTypes) val serverSymbolProviders = ServerSymbolProviders.from( + settings, model, service, rustSymbolProviderConfig, diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerSymbolProvider.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerSymbolProvider.kt index b7009623eb..51f1f3caac 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerSymbolProvider.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerSymbolProvider.kt @@ -31,6 +31,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.traits.SyntheticOutputTra import software.amazon.smithy.rust.codegen.core.util.hasStreamingMember import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.isStreaming +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustSettings /** * Symbol visitor allowing that recursively replace symbols in nested shapes. @@ -44,10 +45,11 @@ import software.amazon.smithy.rust.codegen.core.util.isStreaming * `aws_smithy_http_server_python::types`. */ class PythonServerSymbolVisitor( + settings: ServerRustSettings, model: Model, serviceShape: ServiceShape?, config: RustSymbolProviderConfig, -) : SymbolVisitor(model, serviceShape, config) { +) : SymbolVisitor(settings, model, serviceShape, config) { private val runtimeConfig = config.runtimeConfig override fun toSymbol(shape: Shape): Symbol { diff --git a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/RustServerCodegenPythonPlugin.kt b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/RustServerCodegenPythonPlugin.kt index 908e8416e4..b61bb725ae 100644 --- a/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/RustServerCodegenPythonPlugin.kt +++ b/codegen-server/python/src/main/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/RustServerCodegenPythonPlugin.kt @@ -19,6 +19,7 @@ import software.amazon.smithy.rust.codegen.server.python.smithy.customizations.D import software.amazon.smithy.rust.codegen.server.smithy.ConstrainedShapeSymbolMetadataProvider import software.amazon.smithy.rust.codegen.server.smithy.ConstrainedShapeSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.DeriveEqAndHashSymbolMetadataProvider +import software.amazon.smithy.rust.codegen.server.smithy.ServerRustSettings import software.amazon.smithy.rust.codegen.server.smithy.customizations.CustomValidationExceptionWithReasonDecorator import software.amazon.smithy.rust.codegen.server.smithy.customizations.ServerRequiredCustomizations import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionDecorator @@ -68,6 +69,7 @@ class RustServerCodegenPythonPlugin : SmithyBuildPlugin { * See [software.amazon.smithy.rust.codegen.client.smithy.RustClientCodegenPlugin]. */ fun baseSymbolProvider( + settings: ServerRustSettings, model: Model, serviceShape: ServiceShape, rustSymbolProviderConfig: RustSymbolProviderConfig, @@ -75,7 +77,7 @@ class RustServerCodegenPythonPlugin : SmithyBuildPlugin { ) = // Rename a set of symbols that do not implement `PyClass` and have been wrapped in // `aws_smithy_http_server_python::types`. - PythonServerSymbolVisitor(model, serviceShape = serviceShape, config = rustSymbolProviderConfig) + PythonServerSymbolVisitor(settings, model, serviceShape = serviceShape, config = rustSymbolProviderConfig) // Generate public constrained types for directly constrained shapes. // In the Python server project, this is only done to generate constrained types for simple shapes (e.g. // a `string` shape with the `length` trait), but these always remain `pub(crate)`. diff --git a/codegen-server/python/src/test/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerSymbolProviderTest.kt b/codegen-server/python/src/test/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerSymbolProviderTest.kt index 92f89bf5e6..c7467b58ed 100644 --- a/codegen-server/python/src/test/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerSymbolProviderTest.kt +++ b/codegen-server/python/src/test/kotlin/software/amazon/smithy/rust/codegen/server/python/smithy/generators/PythonServerSymbolProviderTest.kt @@ -13,6 +13,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.server.python.smithy.PythonServerSymbolVisitor import software.amazon.smithy.rust.codegen.server.smithy.testutil.ServerTestRustSymbolProviderConfig +import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverTestRustSettings internal class PythonServerSymbolProviderTest { private val pythonBlobType = RustType.Opaque("Blob", "aws_smithy_http_server_python::types") @@ -45,7 +46,8 @@ internal class PythonServerSymbolProviderTest { value: Timestamp } """.asSmithyModel() - val provider = PythonServerSymbolVisitor(model, null, ServerTestRustSymbolProviderConfig) + val provider = + PythonServerSymbolVisitor(serverTestRustSettings(), model, null, ServerTestRustSymbolProviderConfig) // Struct test val timestamp = provider.toSymbol(model.expectShape(ShapeId.from("test#TimestampStruct\$inner"))).rustType() @@ -95,7 +97,8 @@ internal class PythonServerSymbolProviderTest { value: Blob } """.asSmithyModel() - val provider = PythonServerSymbolVisitor(model, null, ServerTestRustSymbolProviderConfig) + val provider = + PythonServerSymbolVisitor(serverTestRustSettings(), model, null, ServerTestRustSymbolProviderConfig) // Struct test val blob = provider.toSymbol(model.expectShape(ShapeId.from("test#BlobStruct\$inner"))).rustType() diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustServerCodegenPlugin.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustServerCodegenPlugin.kt index 8df61342de..396ee17841 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustServerCodegenPlugin.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RustServerCodegenPlugin.kt @@ -63,13 +63,14 @@ class RustServerCodegenPlugin : ServerDecoratableBuildPlugin() { * See [software.amazon.smithy.rust.codegen.client.smithy.RustClientCodegenPlugin]. */ fun baseSymbolProvider( + settings: ServerRustSettings, model: Model, serviceShape: ServiceShape, rustSymbolProviderConfig: RustSymbolProviderConfig, constrainedTypes: Boolean = true, includeConstrainedShapeProvider: Boolean = true, ) = - SymbolVisitor(model, serviceShape = serviceShape, config = rustSymbolProviderConfig) + SymbolVisitor(settings, model, serviceShape = serviceShape, config = rustSymbolProviderConfig) // Generate public constrained types for directly constrained shapes. .let { if (includeConstrainedShapeProvider) ConstrainedShapeSymbolProvider(it, serviceShape, constrainedTypes) else it 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 3cffaea4aa..7c04c4904f 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 @@ -127,6 +127,7 @@ open class ServerCodegenVisitor( model = codegenDecorator.transformModel(service, baseModel) val serverSymbolProviders = ServerSymbolProviders.from( + settings, model, service, rustSymbolProviderConfig, 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 index bb8f501373..bd784a6ece 100644 --- 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 @@ -5,17 +5,22 @@ package software.amazon.smithy.rust.codegen.server.smithy +import software.amazon.smithy.codegen.core.Symbol 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.rustlang.RustReservedWords +import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.smithy.ModuleProvider import software.amazon.smithy.rust.codegen.core.smithy.ModuleProviderContext +import software.amazon.smithy.rust.codegen.core.smithy.module 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 +import software.amazon.smithy.rust.codegen.core.util.toSnakeCase object ServerRustModule { val root = RustModule.LibRs @@ -54,4 +59,19 @@ object ServerModuleProvider : ModuleProvider { context: ModuleProviderContext, eventStream: UnionShape, ): RustModule.LeafModule = ServerRustModule.Error + + override fun moduleForBuilder(context: ModuleProviderContext, shape: Shape, symbol: Symbol): RustModule.LeafModule { + val pubCrate = !(context.settings as ServerRustSettings).codegenConfig.publicConstrainedTypes + val builderNamespace = RustReservedWords.escapeIfNeeded(symbol.name.toSnakeCase()) + + if (pubCrate) { + "_internal" + } else { + "" + } + val visibility = when (pubCrate) { + true -> Visibility.PUBCRATE + false -> Visibility.PUBLIC + } + return RustModule.new(builderNamespace, visibility, parent = symbol.module(), inline = true) + } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt index d4d129026f..675b72b0b3 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerSymbolProviders.kt @@ -24,16 +24,18 @@ class ServerSymbolProviders private constructor( ) { companion object { fun from( + settings: ServerRustSettings, model: Model, service: ServiceShape, rustSymbolProviderConfig: RustSymbolProviderConfig, publicConstrainedTypes: Boolean, - baseSymbolProviderFactory: (model: Model, service: ServiceShape, rustSymbolProviderConfig: RustSymbolProviderConfig, publicConstrainedTypes: Boolean, includeConstraintShapeProvider: Boolean) -> RustSymbolProvider, + baseSymbolProviderFactory: (settings: ServerRustSettings, model: Model, service: ServiceShape, rustSymbolProviderConfig: RustSymbolProviderConfig, publicConstrainedTypes: Boolean, includeConstraintShapeProvider: Boolean) -> RustSymbolProvider, ): ServerSymbolProviders { - val baseSymbolProvider = baseSymbolProviderFactory(model, service, rustSymbolProviderConfig, publicConstrainedTypes, publicConstrainedTypes) + val baseSymbolProvider = baseSymbolProviderFactory(settings, model, service, rustSymbolProviderConfig, publicConstrainedTypes, publicConstrainedTypes) return ServerSymbolProviders( symbolProvider = baseSymbolProvider, constrainedShapeSymbolProvider = baseSymbolProviderFactory( + settings, model, service, rustSymbolProviderConfig, @@ -42,6 +44,7 @@ class ServerSymbolProviders private constructor( ), unconstrainedShapeSymbolProvider = UnconstrainedShapeSymbolProvider( baseSymbolProviderFactory( + settings, model, service, rustSymbolProviderConfig, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderSymbol.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderSymbol.kt index a605009ddf..948aea0d89 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderSymbol.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderSymbol.kt @@ -16,12 +16,14 @@ import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.util.toSnakeCase import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +// TODO(https://github.com/awslabs/smithy-rs/issues/2396): Replace this with `RustSymbolProvider.symbolForBuilder` fun StructureShape.serverBuilderSymbol(codegenContext: ServerCodegenContext): Symbol = this.serverBuilderSymbol( codegenContext.symbolProvider, !codegenContext.settings.codegenConfig.publicConstrainedTypes, ) +// TODO(https://github.com/awslabs/smithy-rs/issues/2396): Replace this with `RustSymbolProvider.moduleForBuilder` fun StructureShape.serverBuilderModule(symbolProvider: SymbolProvider, pubCrate: Boolean): RustModule.LeafModule { val structureSymbol = symbolProvider.toSymbol(this) val builderNamespace = RustReservedWords.escapeIfNeeded(structureSymbol.name.toSnakeCase()) + @@ -37,6 +39,7 @@ fun StructureShape.serverBuilderModule(symbolProvider: SymbolProvider, pubCrate: return RustModule.new(builderNamespace, visibility, parent = structureSymbol.module(), inline = true) } +// TODO(https://github.com/awslabs/smithy-rs/issues/2396): Replace this with `RustSymbolProvider.symbolForBuilder` fun StructureShape.serverBuilderSymbol(symbolProvider: SymbolProvider, pubCrate: Boolean): Symbol { val builderModule = serverBuilderModule(symbolProvider, pubCrate) val rustType = RustType.Opaque("Builder", builderModule.fullyQualifiedPath()) 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 d761be13e7..41201b8695 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 @@ -7,7 +7,6 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators.http import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.OperationShape -import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Writable @@ -23,25 +22,19 @@ import software.amazon.smithy.rust.codegen.core.smithy.mapRustType import software.amazon.smithy.rust.codegen.core.smithy.protocols.HttpBindingDescriptor import software.amazon.smithy.rust.codegen.core.smithy.protocols.Protocol import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext -import software.amazon.smithy.rust.codegen.server.smithy.generators.serverBuilderSymbol import software.amazon.smithy.rust.codegen.server.smithy.targetCanReachConstrainedShape class ServerRequestBindingGenerator( protocol: Protocol, - private val codegenContext: ServerCodegenContext, + codegenContext: ServerCodegenContext, operationShape: OperationShape, ) { - private fun serverBuilderSymbol(shape: StructureShape): Symbol = shape.serverBuilderSymbol( - codegenContext.symbolProvider, - !codegenContext.settings.codegenConfig.publicConstrainedTypes, - ) private val httpBindingGenerator = HttpBindingGenerator( protocol, codegenContext, codegenContext.unconstrainedShapeSymbolProvider, operationShape, - ::serverBuilderSymbol, listOf( ServerRequestAfterDeserializingIntoAHashMapOfHttpPrefixHeadersWrapInUnconstrainedMapHttpBindingCustomization( codegenContext, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerResponseBindingGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerResponseBindingGenerator.kt index e30d9cc633..33f062b6b9 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerResponseBindingGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerResponseBindingGenerator.kt @@ -41,7 +41,6 @@ class ServerResponseBindingGenerator( codegenContext, codegenContext.symbolProvider, operationShape, - ::builderSymbol, listOf( ServerResponseBeforeIteratingOverMapBoundWithHttpPrefixHeadersUnwrapConstrainedMapHttpBindingCustomization( codegenContext, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocol.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocol.kt index 09eb45a5e6..7df2a98c7f 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocol.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocol.kt @@ -87,8 +87,6 @@ class ServerAwsJsonProtocol( private val runtimeConfig = codegenContext.runtimeConfig override fun structuredDataParser(operationShape: OperationShape): StructuredDataParserGenerator { - fun builderSymbol(shape: StructureShape): Symbol = - shape.serverBuilderSymbol(serverCodegenContext) fun returnSymbolToParse(shape: Shape): ReturnSymbolToParse = if (shape.canReachConstrainedShape(codegenContext.model, serverCodegenContext.symbolProvider)) { ReturnSymbolToParse(serverCodegenContext.unconstrainedShapeSymbolProvider.toSymbol(shape), true) @@ -99,7 +97,6 @@ class ServerAwsJsonProtocol( codegenContext, httpBindingResolver, ::awsJsonFieldName, - ::builderSymbol, ::returnSymbolToParse, listOf( ServerRequestBeforeBoxingDeserializedMemberConvertToMaybeConstrainedJsonParserCustomization(serverCodegenContext), @@ -168,7 +165,6 @@ class ServerRestJsonProtocol( codegenContext, httpBindingResolver, ::restJsonFieldName, - ::builderSymbol, ::returnSymbolToParse, listOf( ServerRequestBeforeBoxingDeserializedMemberConvertToMaybeConstrainedJsonParserCustomization( 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 b225b555c5..d035c9c7fc 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 @@ -48,6 +48,7 @@ fun serverTestSymbolProviders( settings: ServerRustSettings? = null, ) = ServerSymbolProviders.from( + serverTestRustSettings(), model, serviceShape ?: testServiceShapeFor(model), ServerTestRustSymbolProviderConfig, @@ -97,6 +98,7 @@ fun serverTestCodegenContext( ?: ServiceShape.builder().version("test").id("test#Service").build() val protocol = protocolShapeId ?: ShapeId.from("test#Protocol") val serverSymbolProviders = ServerSymbolProviders.from( + settings, model, service, ServerTestRustSymbolProviderConfig, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt index fa16322fe9..11e9d65b4d 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/eventstream/ServerEventStreamUnmarshallerGeneratorTest.kt @@ -7,7 +7,6 @@ package software.amazon.smithy.rust.codegen.server.smithy.protocols.eventstream import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ArgumentsSource -import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.implBlock @@ -22,7 +21,6 @@ import software.amazon.smithy.rust.codegen.core.testutil.EventStreamTestVariety import software.amazon.smithy.rust.codegen.core.testutil.TestEventStreamProject import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext -import software.amazon.smithy.rust.codegen.server.smithy.generators.serverBuilderSymbol import software.amazon.smithy.rust.codegen.server.smithy.transformers.ConstrainedMemberTransform class ServerEventStreamUnmarshallerGeneratorTest { @@ -45,13 +43,11 @@ class ServerEventStreamUnmarshallerGeneratorTest { project: TestEventStreamProject, protocol: Protocol, ): RuntimeType { - fun builderSymbol(shape: StructureShape): Symbol = shape.serverBuilderSymbol(codegenContext) return EventStreamUnmarshallerGenerator( protocol, codegenContext, project.operationShape, project.streamShape, - ::builderSymbol, ).render() } @@ -62,10 +58,12 @@ class ServerEventStreamUnmarshallerGeneratorTest { codegenContext: ServerCodegenContext, shape: StructureShape, ) { - BuilderGenerator(codegenContext.model, codegenContext.symbolProvider, shape, emptyList()).apply { - render(writer) + rustCrate.withModule(codegenContext.symbolProvider.moduleForBuilder(shape)) { + BuilderGenerator(codegenContext.model, codegenContext.symbolProvider, shape, emptyList()).render(this) + } + rustCrate.moduleFor(shape) { writer.implBlock(codegenContext.symbolProvider.toSymbol(shape)) { - renderConvenienceMethod(writer) + BuilderGenerator.renderConvenienceMethod(this, codegenContext.symbolProvider, shape) } } } diff --git a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/lib.rs b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/lib.rs index f04050b72f..7a4d868da0 100644 --- a/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/lib.rs +++ b/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/lib.rs @@ -227,7 +227,7 @@ pub async fn capture_pokemon( let capturing_event = event.as_event(); if let Ok(attempt) = capturing_event { let payload = attempt.payload.clone().unwrap_or_else(|| CapturingPayload::builder().build()); - let pokeball = payload.pokeball.as_deref().unwrap_or(""); + let pokeball = payload.pokeball().unwrap_or(""); if ! matches!(pokeball, "Master Ball" | "Great Ball" | "Fast Ball") { yield Err( crate::error::CapturePokemonEventsError::InvalidPokeballError( @@ -249,8 +249,7 @@ pub async fn capture_pokemon( if captured { let shiny = rand::thread_rng().gen_range(0..4096) == 0; let pokemon = payload - .name - .as_deref() + .name() .unwrap_or("") .to_string(); let pokedex: Vec = (0..255).collect();