From f0d60a2b3ea6d9df2a3684d816105cadff0b1913 Mon Sep 17 00:00:00 2001 From: Hayden Baker Date: Thu, 9 Oct 2025 10:36:22 -0700 Subject: [PATCH 1/7] fix: use symbol-provider for accessors in member-builder --- .../endpoints/OperationInputTestGenerator.kt | 2 +- .../generators/ClientBuilderInstantiator.kt | 5 ++++ .../smithy/generators/ClientInstantiator.kt | 2 +- .../client/FluentBuilderGenerator.kt | 8 +++---- .../client/FluentClientGenerator.kt | 4 ++-- .../protocol/ProtocolParserGenerator.kt | 2 +- .../smithy/generators/BuilderGenerator.kt | 23 +++++++++++-------- .../smithy/generators/BuilderInstantiator.kt | 4 +++- .../protocols/parse/CborParserGenerator.kt | 2 +- .../parse/EventStreamUnmarshallerGenerator.kt | 4 ++-- .../protocols/parse/JsonParserGenerator.kt | 6 ++--- .../parse/XmlBindingTraitParserGenerator.kt | 4 ++-- .../testutil/DefaultBuilderInstantiator.kt | 5 ++++ .../smithy/generators/InstantiatorTest.kt | 2 +- .../smithy/generators/ServerInstantiator.kt | 5 ++++ .../ServerHttpBoundProtocolGenerator.kt | 10 ++++---- 16 files changed, 54 insertions(+), 34 deletions(-) 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..947fc2e5e4e 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(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-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..7574c82c6b1 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,14 @@ 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()}" - -// Getter names will never hit a reserved word and therefore never need escaping. -fun MemberShape.getterName() = "get_${this.memberName.toSnakeCase()}" +fun MemberShape.setterName(symbolProvider: SymbolProvider): String { + val unescaped = symbolProvider.toMemberName(this).removePrefix("r##") + return "set_${unescaped}" +} +fun MemberShape.getterName(symbolProvider: SymbolProvider): String { + val unescaped = symbolProvider.toMemberName(this).removePrefix("r##") + return "get_${unescaped}" +} class BuilderGenerator( private val model: Model, @@ -192,7 +195,7 @@ class BuilderGenerator( val memberName = member.memberName.toSnakeCase() val setter = if (symbolProvider.toSymbol(member).isOptional()) { - member.setterName() + member.setterName(symbolProvider) } else { memberName } @@ -311,7 +314,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 +336,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 +412,7 @@ 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 +438,7 @@ 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..a183d7c4929 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 b2fc9098be6..a8e8e82c5f8 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 @@ -252,7 +252,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) @@ -285,7 +285,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/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 1ef8a44e151..977ba35a594 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 @@ -818,7 +818,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( rustTemplate( """ if let Some(value) = #{ParsedValue:W} { - input = input.${member.setterName()}($valueToSet) + input = input.${member.setterName(symbolProvider)}($valueToSet) } """, "ParsedValue" to parsedValue, @@ -1044,7 +1044,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( val deserializer = generateParseStrFn(binding, true) rustTemplate( """ - input = input.${binding.member.setterName()}( + input = input.${binding.member.setterName(symbolProvider)}( #{deserializer}(m$index)? ); """, @@ -1145,7 +1145,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; @@ -1259,7 +1259,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") } @@ -1277,7 +1277,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( rustBlock("if !$memberName.is_empty()") { withBlock( "input = input.${ - binding.member.setterName() + binding.member.setterName(symbolProvider) }(", ");", ) { From 371fa7cf05fb348bee2ef26ab17f75f3f0b55f4a Mon Sep 17 00:00:00 2001 From: Nate Usher Date: Fri, 10 Oct 2025 09:56:06 -0700 Subject: [PATCH 2/7] fix: pass symbolProvider to setterName() calls The setterName() extension function now requires a symbolProvider parameter. Updated call sites to pass the correct symbolProvider. --- .../software/amazon/smithy/rustsdk/SmokeTestsDecorator.kt | 2 +- .../smithy/rustsdk/endpoints/OperationInputTestGenerator.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 947fc2e5e4e..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(symbolProvider)}(#{value})", + ".${member.setterName(ctx.symbolProvider)}(#{value})", "value" to instantiator.generate(member, value), ) } From 1f171f90a0d286da9c657232b8c94c1d7996160f Mon Sep 17 00:00:00 2001 From: Nate Usher Date: Fri, 10 Oct 2025 10:16:29 -0700 Subject: [PATCH 3/7] test: add test for meta field renaming to meta_value Verifies that structures with a 'meta' field get properly renamed to 'meta_value' with corresponding setter/getter methods to avoid conflicts with error metadata fields. --- .../client/FluentClientGeneratorTest.kt | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) 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"), + ) + } + } + } } From b1670966b7526681b81d6d3a9ca171756f05d7d2 Mon Sep 17 00:00:00 2001 From: Nate Usher Date: Fri, 10 Oct 2025 10:19:29 -0700 Subject: [PATCH 4/7] chore: add changelog entry for builder accessor fix --- .changelog/fix-builder-accessor-naming.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changelog/fix-builder-accessor-naming.md diff --git a/.changelog/fix-builder-accessor-naming.md b/.changelog/fix-builder-accessor-naming.md new file mode 100644 index 00000000000..2804991197a --- /dev/null +++ b/.changelog/fix-builder-accessor-naming.md @@ -0,0 +1,9 @@ +--- +applies_to: ["client"] +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. From 48e8d207ff377713d6479d90f4ad4b2fd18dda20 Mon Sep 17 00:00:00 2001 From: Nate Usher Date: Fri, 10 Oct 2025 11:05:55 -0700 Subject: [PATCH 5/7] Fix server builder setter naming to use symbolProvider Use setterName() extension function instead of manually constructing setter names to handle field renaming (e.g. default -> default_value). --- .../integration-tests/Cargo.lock | 26 +++++++++---------- .../generators/ServerBuilderGenerator.kt | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/codegen-server-test/integration-tests/Cargo.lock b/codegen-server-test/integration-tests/Cargo.lock index 7e5bffb0f46..97ad7c6e578 100644 --- a/codegen-server-test/integration-tests/Cargo.lock +++ b/codegen-server-test/integration-tests/Cargo.lock @@ -50,7 +50,7 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-smithy-async" -version = "1.2.5" +version = "1.2.6" dependencies = [ "futures-util", "pin-project-lite", @@ -59,7 +59,7 @@ dependencies = [ [[package]] name = "aws-smithy-cbor" -version = "0.61.1" +version = "0.61.2" dependencies = [ "aws-smithy-types", "minicbor", @@ -67,7 +67,7 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.11" +version = "0.60.12" dependencies = [ "aws-smithy-types", "bytes", @@ -76,7 +76,7 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.62.4" +version = "0.62.5" dependencies = [ "aws-smithy-eventstream", "aws-smithy-runtime-api", @@ -96,7 +96,7 @@ dependencies = [ [[package]] name = "aws-smithy-http-client" -version = "1.1.2" +version = "1.1.3" dependencies = [ "aws-smithy-async", "aws-smithy-protocol-test", @@ -120,7 +120,7 @@ dependencies = [ [[package]] name = "aws-smithy-http-server" -version = "0.65.6" +version = "0.65.7" dependencies = [ "aws-smithy-cbor", "aws-smithy-http", @@ -148,21 +148,21 @@ dependencies = [ [[package]] name = "aws-smithy-json" -version = "0.61.5" +version = "0.61.6" dependencies = [ "aws-smithy-types", ] [[package]] name = "aws-smithy-observability" -version = "0.1.3" +version = "0.1.4" dependencies = [ "aws-smithy-runtime-api", ] [[package]] name = "aws-smithy-protocol-test" -version = "0.63.4" +version = "0.63.5" dependencies = [ "assert-json-diff", "aws-smithy-runtime-api", @@ -179,7 +179,7 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.9.2" +version = "1.9.3" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -202,7 +202,7 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.9.0" +version = "1.9.1" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -216,7 +216,7 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.3.2" +version = "1.3.3" dependencies = [ "base64-simd", "bytes", @@ -241,7 +241,7 @@ dependencies = [ [[package]] name = "aws-smithy-xml" -version = "0.60.10" +version = "0.60.11" dependencies = [ "xmlparser", ] 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..6f657bb4e54 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 @@ -408,8 +409,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 = ${ From c06302b6e05d23ff3585e7151f0254fffad2b403 Mon Sep 17 00:00:00 2001 From: Nate Usher Date: Fri, 10 Oct 2025 11:09:26 -0700 Subject: [PATCH 6/7] Update changelog to include server tag --- .changelog/fix-builder-accessor-naming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/fix-builder-accessor-naming.md b/.changelog/fix-builder-accessor-naming.md index 2804991197a..9219e9dc6e0 100644 --- a/.changelog/fix-builder-accessor-naming.md +++ b/.changelog/fix-builder-accessor-naming.md @@ -1,5 +1,5 @@ --- -applies_to: ["client"] +applies_to: ["client", "server"] authors: ["haydenbaker", "nated0g"] references: ["smithy-rs#4338"] breaking: false From 4ddf580e2646f93a77212ec640592e9f380b1bc1 Mon Sep 17 00:00:00 2001 From: Landon James Date: Mon, 13 Oct 2025 15:13:49 -0700 Subject: [PATCH 7/7] Fixing ktlint issues --- .../smithy/generators/BuilderGenerator.kt | 21 +++++++++--- .../smithy/generators/BuilderInstantiator.kt | 2 +- .../generators/ServerBuilderGenerator.kt | 34 ++++++++++++++----- 3 files changed, 43 insertions(+), 14 deletions(-) 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 7574c82c6b1..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 @@ -136,11 +136,12 @@ class OperationBuildError(private val runtimeConfig: RuntimeConfig) { fun MemberShape.setterName(symbolProvider: SymbolProvider): String { val unescaped = symbolProvider.toMemberName(this).removePrefix("r##") - return "set_${unescaped}" + return "set_$unescaped" } + fun MemberShape.getterName(symbolProvider: SymbolProvider): String { val unescaped = symbolProvider.toMemberName(this).removePrefix("r##") - return "get_${unescaped}" + return "get_$unescaped" } class BuilderGenerator( @@ -412,7 +413,13 @@ class BuilderGenerator( ) { docs("Appends an item to `$memberName`.") rust("///") - docs("To override the contents of this collection use [`${member.setterName(symbolProvider)}`](Self::${member.setterName(symbolProvider)}).") + docs( + "To override the contents of this collection use [`${member.setterName(symbolProvider)}`](Self::${ + member.setterName( + symbolProvider, + ) + }).", + ) rust("///") documentShape(member, model, autoSuppressMissingDocs = false) deprecatedShape(member) @@ -438,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(symbolProvider)}`](Self::${member.setterName(symbolProvider)}).") + 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 a183d7c4929..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,7 +33,7 @@ interface BuilderInstantiator { mapErr: Writable? = null, ): Writable - fun setterProvider(field: MemberShape): String; + fun setterProvider(field: MemberShape): String /** Set a field on a builder using the `$setterName` method. $value will be passed directly. */ fun setFieldWithSetter( 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 6f657bb4e54..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 @@ -46,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 @@ -152,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 = @@ -237,7 +241,9 @@ class ServerBuilderGenerator( #{Converter:W} """, "Converter" to - customValidationExceptionWithReasonConversionGenerator.renderImplFromConstraintViolationForRequestRejection(protocol), + customValidationExceptionWithReasonConversionGenerator.renderImplFromConstraintViolationForRequestRejection( + protocol, + ), ) } @@ -327,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) @@ -352,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)") } @@ -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)),