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) }(", ");", ) {