diff --git a/.changelog/fix-builder-accessor-naming.md b/.changelog/fix-builder-accessor-naming.md new file mode 100644 index 00000000000..9219e9dc6e0 --- /dev/null +++ b/.changelog/fix-builder-accessor-naming.md @@ -0,0 +1,9 @@ +--- +applies_to: ["client", "server"] +authors: ["haydenbaker", "nated0g"] +references: ["smithy-rs#4338"] +breaking: false +new_feature: false +bug_fix: true +--- +Fix builder accessor methods to use symbol provider for naming. This resolves conflicts when struct members are renamed due to reserved words (e.g., `meta` -> `meta_value`), ensuring setter and getter methods use the correct renamed field names. diff --git a/aws/codegen-aws-sdk/src/main/kotlin/software/amazon/smithy/rustsdk/SmokeTestsDecorator.kt b/aws/codegen-aws-sdk/src/main/kotlin/software/amazon/smithy/rustsdk/SmokeTestsDecorator.kt index dd2891a3b8b..08426ae24b9 100644 --- a/aws/codegen-aws-sdk/src/main/kotlin/software/amazon/smithy/rustsdk/SmokeTestsDecorator.kt +++ b/aws/codegen-aws-sdk/src/main/kotlin/software/amazon/smithy/rustsdk/SmokeTestsDecorator.kt @@ -154,7 +154,7 @@ class SmokeTestsBuilderKindBehavior(val codegenContext: CodegenContext) : Instan override fun hasFallibleBuilder(shape: StructureShape): Boolean = BuilderGenerator.hasFallibleBuilder(shape, codegenContext.symbolProvider) - override fun setterName(memberShape: MemberShape): String = memberShape.setterName() + override fun setterName(memberShape: MemberShape): String = memberShape.setterName(codegenContext.symbolProvider) override fun doesSetterTakeInOption(memberShape: MemberShape): Boolean = true } diff --git a/aws/codegen-aws-sdk/src/main/kotlin/software/amazon/smithy/rustsdk/endpoints/OperationInputTestGenerator.kt b/aws/codegen-aws-sdk/src/main/kotlin/software/amazon/smithy/rustsdk/endpoints/OperationInputTestGenerator.kt index 8d515e9bcc7..16c0448b098 100644 --- a/aws/codegen-aws-sdk/src/main/kotlin/software/amazon/smithy/rustsdk/endpoints/OperationInputTestGenerator.kt +++ b/aws/codegen-aws-sdk/src/main/kotlin/software/amazon/smithy/rustsdk/endpoints/OperationInputTestGenerator.kt @@ -186,7 +186,7 @@ class OperationInputTestGenerator(_ctx: ClientCodegenContext, private val test: testOperationInput.operationParams.members.forEach { (key, value) -> val member = operationInput.expectMember(key.value) rustTemplate( - ".${member.setterName()}(#{value})", + ".${member.setterName(ctx.symbolProvider)}(#{value})", "value" to instantiator.generate(member, value), ) } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientBuilderInstantiator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientBuilderInstantiator.kt index 15911fbcd0b..c1e4cfa5b5e 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientBuilderInstantiator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientBuilderInstantiator.kt @@ -15,6 +15,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderInstantiator +import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName class ClientBuilderInstantiator(private val clientCodegenContext: ClientCodegenContext) : BuilderInstantiator { override fun setField( @@ -25,6 +26,10 @@ class ClientBuilderInstantiator(private val clientCodegenContext: ClientCodegenC return setFieldWithSetter(builder, value, field) } + override fun setterProvider(field: MemberShape): String { + return field.setterName(clientCodegenContext.symbolProvider) + } + /** * For the client, we finalize builders with error correction enabled */ diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientInstantiator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientInstantiator.kt index 992d85dd72a..e9edecb7ea3 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientInstantiator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ClientInstantiator.kt @@ -23,7 +23,7 @@ class ClientBuilderKindBehavior(val codegenContext: CodegenContext) : Instantiat override fun hasFallibleBuilder(shape: StructureShape): Boolean = BuilderGenerator.hasFallibleBuilder(shape, codegenContext.symbolProvider) - override fun setterName(memberShape: MemberShape): String = memberShape.setterName() + override fun setterName(memberShape: MemberShape): String = memberShape.setterName(codegenContext.symbolProvider) override fun doesSetterTakeInOption(memberShape: MemberShape): Boolean = true } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentBuilderGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentBuilderGenerator.kt index fb0bd64cc1b..42de896b058 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentBuilderGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentBuilderGenerator.kt @@ -367,11 +367,11 @@ class FluentBuilderGenerator( else -> renderInputHelper(member, memberName, coreType) } // pure setter - val setterName = member.setterName() + val setterName = member.setterName(symbolProvider) val optionalInputType = outerType.asOptional() renderInputHelper(member, setterName, optionalInputType) - val getterName = member.getterName() + val getterName = member.getterName(symbolProvider) renderGetterHelper(member, getterName, optionalInputType) } } @@ -437,7 +437,7 @@ class FluentBuilderGenerator( """ Appends an item to `${member.memberName}`. - To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}). + To override the contents of this collection use [`${member.setterName(symbolProvider)}`](Self::${member.setterName(symbolProvider)}). """, ) documentShape(member, model) @@ -467,7 +467,7 @@ class FluentBuilderGenerator( """ Adds a key-value pair to `${member.memberName}`. - To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}). + To override the contents of this collection use [`${member.setterName(symbolProvider)}`](Self::${member.setterName(symbolProvider)}). """, ) documentShape(member, model) 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 3d28f4818d2..d00a1062f3c 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 @@ -359,7 +359,7 @@ private fun generateOperationShapeDocs( val builderInputDoc = memberShape.asFluentBuilderInputDoc(symbolProvider) val builderInputLink = docLink("$fluentBuilderFullyQualifiedName::${symbolProvider.toMemberName(memberShape)}") val builderSetterDoc = memberShape.asFluentBuilderSetterDoc(symbolProvider) - val builderSetterLink = docLink("$fluentBuilderFullyQualifiedName::${memberShape.setterName()}") + val builderSetterLink = docLink("$fluentBuilderFullyQualifiedName::${memberShape.setterName(symbolProvider)}") val docTrait = memberShape.getMemberTrait(model, DocumentationTrait::class.java).orNull() val docs = @@ -440,7 +440,7 @@ internal fun MemberShape.asFluentBuilderInputDoc(symbolProvider: SymbolProvider) * _NOTE: This function generates the setter type names that appear under **"The fluent builder is configurable:"**_ */ private fun MemberShape.asFluentBuilderSetterDoc(symbolProvider: SymbolProvider): String { - val memberName = this.setterName() + val memberName = this.setterName(symbolProvider) val outerType = symbolProvider.toSymbol(this).rustType() return "$memberName(${outerType.asArgumentType(fullyQualified = false)})" diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolParserGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolParserGenerator.kt index 6bcc00d84a5..34e7a39a943 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolParserGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/protocol/ProtocolParserGenerator.kt @@ -264,7 +264,7 @@ class ProtocolParserGenerator( val member = binding.member val parsedValue = renderBindingParser(binding, operationShape, httpBindingGenerator, structuredDataParser) if (parsedValue != null) { - withBlock("output = output.${member.setterName()}(", ");") { + withBlock("output = output.${member.setterName(symbolProvider)}(", ");") { parsedValue(this) } } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGeneratorTest.kt index 1b958727af1..bddbb9c7c58 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGeneratorTest.kt @@ -138,4 +138,60 @@ class FluentClientGeneratorTest { clientIntegrationTest(model) } + + @Test + fun `meta field gets renamed to meta_value with correct setter`() { + val model = + """ + namespace com.example + use aws.protocols#awsJson1_0 + + @awsJson1_0 + service TestService { + operations: [TestOperation], + version: "1" + } + + operation TestOperation { input: TestInput } + structure TestInput { + meta: String, + other: String + } + """.asSmithyModel() + + clientIntegrationTest(model) { codegenContext, rustCrate -> + rustCrate.integrationTest("meta_field_renamed") { + val moduleName = codegenContext.moduleUseName() + rustTemplate( + """ + ##[test] + fn test_meta_field_accessors() { + let config = $moduleName::Config::builder() + .endpoint_url("http://localhost:1234") + .http_client(#{NeverClient}::new()) + .build(); + let client = $moduleName::Client::from_conf(config); + + // Test the renamed field and setter + let builder = client.test_operation() + .meta_value("test_meta") + .set_meta_value(Some("test_meta_2".to_string())) + .other("other_value"); + + // Verify getter returns correct value + assert_eq!(*builder.get_meta_value(), Some("test_meta_2".to_string())); + assert_eq!(*builder.get_other(), Some("other_value".to_string())); + + // Build the input and verify field is accessible + let input = builder.as_input(); + assert_eq!(*input.get_meta_value(), Some("test_meta_2".to_string())); + } + """, + "NeverClient" to + CargoDependency.smithyHttpClientTestUtil(codegenContext.runtimeConfig).toType() + .resolve("test_util::NeverClient"), + ) + } + } + } } 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 69aa40405d4..27da2f18360 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 @@ -134,11 +134,15 @@ class OperationBuildError(private val runtimeConfig: RuntimeConfig) { } } -// Setter names will never hit a reserved word and therefore never need escaping. -fun MemberShape.setterName() = "set_${this.memberName.toSnakeCase()}" +fun MemberShape.setterName(symbolProvider: SymbolProvider): String { + val unescaped = symbolProvider.toMemberName(this).removePrefix("r##") + return "set_$unescaped" +} -// Getter names will never hit a reserved word and therefore never need escaping. -fun MemberShape.getterName() = "get_${this.memberName.toSnakeCase()}" +fun MemberShape.getterName(symbolProvider: SymbolProvider): String { + val unescaped = symbolProvider.toMemberName(this).removePrefix("r##") + return "get_$unescaped" +} class BuilderGenerator( private val model: Model, @@ -192,7 +196,7 @@ class BuilderGenerator( val memberName = member.memberName.toSnakeCase() val setter = if (symbolProvider.toSymbol(member).isOptional()) { - member.setterName() + member.setterName(symbolProvider) } else { memberName } @@ -311,7 +315,7 @@ class BuilderGenerator( writer.documentShape(member, model) writer.deprecatedShape(member) - writer.rustBlock("pub fn ${member.setterName()}(mut self, input: ${inputType.render(true)}) -> Self") { + writer.rustBlock("pub fn ${member.setterName(symbolProvider)}(mut self, input: ${inputType.render(true)}) -> Self") { rust("self.$memberName = input; self") } } @@ -333,7 +337,7 @@ class BuilderGenerator( writer.documentShape(member, model) writer.deprecatedShape(member) - writer.rustBlock("pub fn ${member.getterName()}(&self) -> &${inputType.render(true)}") { + writer.rustBlock("pub fn ${member.getterName(symbolProvider)}(&self) -> &${inputType.render(true)}") { rust("&self.$memberName") } } @@ -409,7 +413,13 @@ class BuilderGenerator( ) { docs("Appends an item to `$memberName`.") rust("///") - docs("To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}).") + docs( + "To override the contents of this collection use [`${member.setterName(symbolProvider)}`](Self::${ + member.setterName( + symbolProvider, + ) + }).", + ) rust("///") documentShape(member, model, autoSuppressMissingDocs = false) deprecatedShape(member) @@ -435,7 +445,13 @@ class BuilderGenerator( ) { docs("Adds a key-value pair to `$memberName`.") rust("///") - docs("To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}).") + docs( + "To override the contents of this collection use [`${member.setterName(symbolProvider)}`](Self::${ + member.setterName( + symbolProvider, + ) + }).", + ) rust("///") documentShape(member, model, autoSuppressMissingDocs = false) deprecatedShape(member) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderInstantiator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderInstantiator.kt index f73e8d5a055..1e9264d47ed 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderInstantiator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/BuilderInstantiator.kt @@ -33,12 +33,14 @@ interface BuilderInstantiator { mapErr: Writable? = null, ): Writable + fun setterProvider(field: MemberShape): String + /** Set a field on a builder using the `$setterName` method. $value will be passed directly. */ fun setFieldWithSetter( builder: String, value: Writable, field: MemberShape, ) = writable { - rustTemplate("$builder = $builder.${field.setterName()}(#{value})", "value" to value) + rustTemplate("$builder = $builder.${setterProvider(field)}(#{value})", "value" to value) } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/CborParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/CborParserGenerator.kt index 58dbb9c77fa..63d9dcde4fc 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/CborParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/CborParserGenerator.kt @@ -268,7 +268,7 @@ class CborParserGenerator( rustBlock("${member.memberName.dq()} =>") { val callBuilderSetMemberFieldWritable = writable { - withBlock("builder.${member.setterName()}(", ")") { + withBlock("builder.${member.setterName(symbolProvider)}(", ")") { conditionalBlock("Some(", ")", shouldWrapBuilderMemberSetterInputWithOption(member)) { val symbol = symbolProvider.toSymbol(member) if (symbol.isRustBoxed()) { 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 28737bf353c..23f5cde7f5c 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 @@ -253,7 +253,7 @@ class EventStreamUnmarshallerGenerator( } private fun RustWriter.renderUnmarshallEventHeader(member: MemberShape) { - withBlock("builder = builder.${member.setterName()}(", ");") { + withBlock("builder = builder.${member.setterName(symbolProvider)}(", ");") { conditionalBlock("Some(", ")", member.isOptional) { when (val target = model.expectShape(member.target)) { is BooleanShape -> rustTemplate("#{expect_fns}::expect_bool(header)?", *codegenScope) @@ -287,7 +287,7 @@ class EventStreamUnmarshallerGenerator( *codegenScope, ) } - withBlock("builder = builder.${member.setterName()}(", ");") { + withBlock("builder = builder.${member.setterName(symbolProvider)}(", ");") { conditionalBlock("Some(", ")", member.isOptional) { when (target) { is BlobShape -> { 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 a1d4d360821..bc9caf989a4 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 @@ -262,14 +262,14 @@ class JsonParserGenerator( rustBlock("${jsonName(member).dq()} =>") { when (codegenTarget) { CodegenTarget.CLIENT -> { - withBlock("builder = builder.${member.setterName()}(", ");") { + withBlock("builder = builder.${member.setterName(symbolProvider)}(", ");") { deserializeMember(member) } } CodegenTarget.SERVER -> { if (symbolProvider.toSymbol(member).isOptional()) { - withBlock("builder = builder.${member.setterName()}(", ");") { + withBlock("builder = builder.${member.setterName(symbolProvider)}(", ");") { deserializeMember(member) } } else { @@ -278,7 +278,7 @@ class JsonParserGenerator( rust( """ { - builder = builder.${member.setterName()}(v); + builder = builder.${member.setterName(symbolProvider)}(v); } """, ) 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 64cf8d9d7d2..4cbf6015c6a 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 @@ -294,7 +294,7 @@ class XmlBindingTraitParserGenerator( Ctx(tag = decoder, accum = "$builder.${symbolProvider.toMemberName(member)}.take()"), ) } - rust("$builder = $builder.${member.setterName()}($temp);") + rust("$builder = $builder.${member.setterName(symbolProvider)}($temp);") } rustTemplate( "_ => return Err(#{XmlDecodeError}::custom(\"expected ${member.xmlName()} tag\"))", @@ -333,7 +333,7 @@ class XmlBindingTraitParserGenerator( forceOptional = true, ) } - rust("$builder = $builder.${member.setterName()}($temp);") + rust("$builder = $builder.${member.setterName(symbolProvider)}($temp);") } } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/DefaultBuilderInstantiator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/DefaultBuilderInstantiator.kt index aa11d70edb7..5fb9c607a9c 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/DefaultBuilderInstantiator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/DefaultBuilderInstantiator.kt @@ -13,6 +13,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderGenerator import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderInstantiator +import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName /** * A Default instantiator that uses `builder.build()` in all cases. This exists to support tests in codegen-core @@ -27,6 +28,10 @@ class DefaultBuilderInstantiator(private val checkFallibleBuilder: Boolean, priv return setFieldWithSetter(builder, value, field) } + override fun setterProvider(field: MemberShape): String { + return field.setterName(symbolProvider) + } + override fun finalizeBuilder( builder: String, shape: StructureShape, 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 346eaf103c7..0ee6f1165a7 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 @@ -100,7 +100,7 @@ class InstantiatorTest { override fun hasFallibleBuilder(shape: StructureShape) = BuilderGenerator.hasFallibleBuilder(shape, codegenContext.symbolProvider) - override fun setterName(memberShape: MemberShape) = memberShape.setterName() + override fun setterName(memberShape: MemberShape) = memberShape.setterName(codegenContext.symbolProvider) override fun doesSetterTakeInOption(memberShape: MemberShape) = true } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt index cea95c0265f..49af4a88073 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerBuilderGenerator.kt @@ -32,6 +32,7 @@ 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.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.generators.lifetimeDeclaration +import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.isRustBoxed import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained @@ -45,7 +46,6 @@ 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.redactIfNecessary -import software.amazon.smithy.rust.codegen.core.util.toSnakeCase import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.canReachConstrainedShape import software.amazon.smithy.rust.codegen.server.smithy.generators.protocol.ServerProtocol @@ -151,7 +151,12 @@ class ServerBuilderGenerator( private val builderSymbol = shape.serverBuilderSymbol(codegenContext) private val isBuilderFallible = hasFallibleBuilder(shape, model, symbolProvider, takeInUnconstrainedTypes) private val serverBuilderConstraintViolations = - ServerBuilderConstraintViolations(codegenContext, shape, takeInUnconstrainedTypes, customValidationExceptionWithReasonConversionGenerator) + ServerBuilderConstraintViolations( + codegenContext, + shape, + takeInUnconstrainedTypes, + customValidationExceptionWithReasonConversionGenerator, + ) private val lifetime = shape.lifetimeDeclaration(symbolProvider) private val codegenScope = @@ -236,7 +241,9 @@ class ServerBuilderGenerator( #{Converter:W} """, "Converter" to - customValidationExceptionWithReasonConversionGenerator.renderImplFromConstraintViolationForRequestRejection(protocol), + customValidationExceptionWithReasonConversionGenerator.renderImplFromConstraintViolationForRequestRejection( + protocol, + ), ) } @@ -326,7 +333,8 @@ class ServerBuilderGenerator( val memberName = symbolProvider.toMemberName(member) val hasBox = symbol.mapRustType { it.stripOuter() }.isRustBoxed() - val wrapInMaybeConstrained = takeInUnconstrainedTypes && member.targetCanReachConstrainedShape(model, symbolProvider) + val wrapInMaybeConstrained = + takeInUnconstrainedTypes && member.targetCanReachConstrainedShape(model, symbolProvider) writer.documentShape(member, model) writer.deprecatedShape(member) @@ -351,7 +359,11 @@ class ServerBuilderGenerator( if (!constrainedTypeHoldsFinalType(member)) varExpr = "($varExpr).into()" if (wrapInMaybeConstrained) { - conditionalBlock("input.map(##[allow(clippy::redundant_closure)] |v| ", ")", conditional = symbol.isOptional()) { + conditionalBlock( + "input.map(##[allow(clippy::redundant_closure)] |v| ", + ")", + conditional = symbol.isOptional(), + ) { conditionalBlock("Box::new(", ")", conditional = hasBox) { rust("$maybeConstrainedVariant($varExpr)") } @@ -408,8 +420,7 @@ class ServerBuilderGenerator( val memberName = symbolProvider.toMemberName(member) writer.documentShape(member, model) - // Setter names will never hit a reserved word and therefore never need escaping. - writer.rustBlock("pub(crate) fn set_${member.memberName.toSnakeCase()}(mut self, input: $inputType) -> Self") { + writer.rustBlock("pub(crate) fn ${member.setterName(symbolProvider)}(mut self, input: $inputType) -> Self") { rust( """ self.$memberName = ${ @@ -531,9 +542,10 @@ class ServerBuilderGenerator( // Write the modifier(s). // 1. Enforce constraint traits of data from incoming requests. - serverBuilderConstraintViolations.builderConstraintViolationForMember(member)?.also { constraintViolation -> - enforceConstraints(this, member, constraintViolation) - } + serverBuilderConstraintViolations.builderConstraintViolationForMember(member) + ?.also { constraintViolation -> + enforceConstraints(this, member, constraintViolation) + } if (member.hasNonNullDefault()) { // 2a. If a `@default` value is modeled and the user did not set a value, fall back to using the @@ -610,7 +622,11 @@ class ServerBuilderGenerator( // We've just checked the constraints hold by going through the non-public // constrained type, but the user wants to work with the unconstrained type, so we have to // unwrap it. - if (!publicConstrainedTypes && member.wouldHaveConstrainedWrapperTupleTypeWerePublicConstrainedTypesEnabled(model)) { + if (!publicConstrainedTypes && + member.wouldHaveConstrainedWrapperTupleTypeWerePublicConstrainedTypesEnabled( + model, + ) + ) { writer.rust( ".map(|v: #T| v.into())", constrainedShapeSymbolProvider.toSymbol(model.expectShape(member.target)), diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiator.kt index 5b4860c26db..19fcd638fde 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerInstantiator.kt @@ -18,6 +18,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.generators.BuilderInstant import software.amazon.smithy.rust.codegen.core.smithy.generators.Instantiator import software.amazon.smithy.rust.codegen.core.smithy.generators.InstantiatorCustomization import software.amazon.smithy.rust.codegen.core.smithy.generators.InstantiatorSection +import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName import software.amazon.smithy.rust.codegen.core.smithy.isOptional import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.ReturnSymbolToParse import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext @@ -118,6 +119,10 @@ class ServerBuilderInstantiator( } } + override fun setterProvider(field: MemberShape): String { + return field.setterName(symbolProvider) + } + override fun finalizeBuilder( builder: String, shape: StructureShape, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt index ff2c5278754..3950c1b2595 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt @@ -823,7 +823,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( rustTemplate( """ if let Some(value) = #{ParsedValue:W} { - input = input.${member.setterName()}($valueToSet) + input = input.${member.setterName(symbolProvider)}($valueToSet) } """, "ParsedValue" to parsedValue, @@ -1099,7 +1099,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( val deserializer = generateParseStrFn(binding, true) rustTemplate( """ - input = input.${binding.member.setterName()}( + input = input.${binding.member.setterName(symbolProvider)}( #{deserializer}(m$index)? ); """, @@ -1200,7 +1200,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( rustTemplate( """ if !${memberName}_seen && k == "${it.locationName}" { - input = input.${it.member.setterName()}( + input = input.${it.member.setterName(symbolProvider)}( #{deserializer}(&v)? ); ${memberName}_seen = true; @@ -1314,7 +1314,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( unconstrainedShapeSymbolProvider .toSymbol(queryParamsBinding.member) .isOptional() - withBlock("input = input.${queryParamsBinding.member.setterName()}(", ");") { + withBlock("input = input.${queryParamsBinding.member.setterName(symbolProvider)}(", ");") { conditionalBlock("Some(", ")", conditional = isOptional) { write("query_params") } @@ -1332,7 +1332,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( rustBlock("if !$memberName.is_empty()") { withBlock( "input = input.${ - binding.member.setterName() + binding.member.setterName(symbolProvider) }(", ");", ) {