diff --git a/codegen-server-test/build.gradle.kts b/codegen-server-test/build.gradle.kts index a22d7df0364d58cfbb0d880ec6169e70eb1f665a..e61c0a9e3eeda7e2a97de5d8dab080ad0db1b4e6 100644 --- a/codegen-server-test/build.gradle.kts +++ b/codegen-server-test/build.gradle.kts @@ -27,6 +27,11 @@ val CodegenTests = listOf( CodegenTest("com.amazonaws.ebs#Ebs", "ebs") ) +/** + * The fluent client is generated to prevent warnings in RustDoc since the client is + * referenced by multiple documentations. + * TODO: review client generation in the future. + */ fun generateSmithyBuild(tests: List): String { val projections = tests.joinToString(",\n") { @@ -35,7 +40,7 @@ fun generateSmithyBuild(tests: List): String { "plugins": { "rust-server-codegen": { "codegen": { - "includeFluentClient": false + "includeFluentClient": true }, "runtimeConfig": { "relativePath": "${rootProject.projectDir.absolutePath}/rust-runtime" diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/RestJson1.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/RestJson1.kt index 6e80fd9e3dccebe91880b84a547b5b02e48affb9..ab32d0490e87122f8b290022dca20f0ec18ddad6 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/RestJson1.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/RestJson1.kt @@ -102,9 +102,6 @@ class RestJson1HttpSerializerGenerator( return } val serializerSymbol = jsonSerializerGenerator.serverOutputSerializer(operationShape) - if (serializerSymbol == null) { - return - } val outputSymbol = symbolProvider.toSymbol(outputShape) writer.write("") writer.rustBlockTemplate( @@ -169,44 +166,38 @@ class RestJson1HttpSerializerGenerator( val variantSymbol = symbolProvider.toSymbol(variantShape) val data = safeName("var") val serializerSymbol = jsonSerializerGenerator.serverErrorSerializer(it) - if (serializerSymbol != null) { - rustBlock("#TKind::${variantSymbol.name}($data) =>", errorSymbol) { + rustBlock("#TKind::${variantSymbol.name}($data) =>", errorSymbol) { + rust( + """ + #T(&$data)?; + object.key(${"code".dq()}).string(${httpBindingResolver.errorCode(variantShape).dq()}); + """.trimIndent(), + serializerSymbol + ) + if (variantShape.errorMessageMember() != null) { rust( """ - #T(&$data)?; - object.key(${"code".dq()}).string(${httpBindingResolver.errorCode(variantShape).dq()}); - """.trimIndent(), - serializerSymbol - ) - if (variantShape.errorMessageMember() != null) { - rust( - """ - if let Some(message) = $data.message() { - object.key(${"message".dq()}).string(message); - } - """.trimIndent() - ) - } - val bindings = httpBindingResolver.errorResponseBindings(it) - bindings.forEach { binding -> - when (val location = binding.location) { - HttpLocation.RESPONSE_CODE, HttpLocation.DOCUMENT -> {} - else -> { - logger.warning( - "$operationShape: response serialization does not currently support $location bindings" - ) + if let Some(message) = $data.message() { + object.key(${"message".dq()}).string(message); } + """.trimIndent() + ) + } + val bindings = httpBindingResolver.errorResponseBindings(it) + bindings.forEach { binding -> + when (val location = binding.location) { + HttpLocation.RESPONSE_CODE, HttpLocation.DOCUMENT -> {} + else -> { + logger.warning( + "$operationShape: response serialization does not currently support $location bindings" + ) } } - val status = - variantShape.getTrait()?.let { trait -> trait.code } - ?: errorTrait.defaultHttpStatusCode - rust("response = response.status($status);") } - } else { - logger.warning( - "[rust-server-codegen] $variantShape: response error serialization does not contain any member" - ) + val status = + variantShape.getTrait()?.let { trait -> trait.code } + ?: errorTrait.defaultHttpStatusCode + rust("response = response.status($status);") } } rust( @@ -369,9 +360,6 @@ class RestJson1HttpDeserializerGenerator( return } val deserializerSymbol = jsonParserGenerator.serverInputParser(operationShape) - if (deserializerSymbol == null) { - return - } val inputSymbol = symbolProvider.toSymbol(inputShape) writer.write("") writer.rustBlockTemplate( diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/JsonParserGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/JsonParserGenerator.kt index 2fbec31348f3c1d2311d1000f268346d04788bed..0dbb0f6d7a2a404a299691a1872012c5a32cb4d5 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/JsonParserGenerator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/JsonParserGenerator.kt @@ -83,14 +83,14 @@ class JsonParserGenerator( /** * Reusable structure parser implementation that can be used to generate parsing code for * operation, error and structure shapes. + * We still generate the parser symbol even if there are no included members because the server + * generation requires parsers for all input structures. */ - private fun structureParser(fnName: String, structureShape: StructureShape, includedMembers: List): RuntimeType? { - if (includedMembers.isEmpty()) { - return null - } + private fun structureParser(fnName: String, structureShape: StructureShape, includedMembers: List): RuntimeType { + val unusedMut = if (includedMembers.isEmpty()) "##[allow(unused_mut)] " else "" return RuntimeType.forInlineFun(fnName, jsonDeserModule) { it.rustBlockTemplate( - "pub fn $fnName(value: &[u8], mut builder: #{Builder}) -> Result<#{Builder}, #{Error}>", + "pub fn $fnName(value: &[u8], ${unusedMut}mut builder: #{Builder}) -> Result<#{Builder}, #{Error}>", "Builder" to structureShape.builderSymbol(symbolProvider), *codegenScope ) { @@ -138,12 +138,18 @@ class JsonParserGenerator( override fun operationParser(operationShape: OperationShape): RuntimeType? { // Don't generate an operation JSON deserializer if there is no JSON body val httpDocumentMembers = httpBindingResolver.responseMembers(operationShape, HttpLocation.DOCUMENT) + if (httpDocumentMembers.isEmpty()) { + return null + } val outputShape = operationShape.outputShape(model) val fnName = symbolProvider.deserializeFunctionName(operationShape) return structureParser(fnName, outputShape, httpDocumentMembers) } override fun errorParser(errorShape: StructureShape): RuntimeType? { + if (errorShape.members().isEmpty()) { + return null + } val fnName = symbolProvider.deserializeFunctionName(errorShape) + "_json_err" return structureParser(fnName, errorShape, errorShape.members().toList()) } @@ -184,7 +190,7 @@ class JsonParserGenerator( ) } - override fun serverInputParser(operationShape: OperationShape): RuntimeType? { + override fun serverInputParser(operationShape: OperationShape): RuntimeType { val inputShape = operationShape.inputShape(model) val includedMembers = httpBindingResolver.requestMembers(operationShape, HttpLocation.DOCUMENT) val fnName = symbolProvider.deserializeFunctionName(inputShape) diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/StructuredDataParserGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/StructuredDataParserGenerator.kt index dd9b6f8c97c696c129522b13dbe6cf61b3889bc6..fbd36f7a8d87289b5083f4e9257bb3536913d29d 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/StructuredDataParserGenerator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/StructuredDataParserGenerator.kt @@ -66,5 +66,5 @@ interface StructuredDataParserGenerator { * } * ``` */ - fun serverInputParser(operationShape: OperationShape): RuntimeType? + fun serverInputParser(operationShape: OperationShape): RuntimeType } diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt index ee53e03c44063297ca5642cdaf790c94ebfdb72e..7648bbed45f5983901394184c852a832ac272929 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt @@ -241,7 +241,7 @@ class XmlBindingTraitParserGenerator( TODO("Document shapes are not supported by rest XML") } - override fun serverInputParser(operationShape: OperationShape): RuntimeType? { + override fun serverInputParser(operationShape: OperationShape): RuntimeType { TODO("Not yet implemented") } diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/AwsQuerySerializerGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/AwsQuerySerializerGenerator.kt index 9bd3b342d1597c407aec73f18fe8cb644b3e25d1..6f8cf6fccb86215a0fb72e7736fb23187fc9d9e3 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/AwsQuerySerializerGenerator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/AwsQuerySerializerGenerator.kt @@ -22,11 +22,11 @@ class AwsQuerySerializerGenerator(codegenContext: CodegenContext) : QuerySeriali override fun MemberShape.isFlattened(): Boolean = getTrait() != null - override fun serverOutputSerializer(operationShape: OperationShape): RuntimeType? { + override fun serverOutputSerializer(operationShape: OperationShape): RuntimeType { TODO("Not yet implemented") } - override fun serverErrorSerializer(shape: ShapeId): RuntimeType? { + override fun serverErrorSerializer(shape: ShapeId): RuntimeType { TODO("Not yet implemented") } } diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/Ec2QuerySerializerGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/Ec2QuerySerializerGenerator.kt index e36d92e09e337dbe70a54e5c8ae405a86fccd39b..cfcd4fde4f19bb28ea4514f8c393bc864c93a1ba 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/Ec2QuerySerializerGenerator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/Ec2QuerySerializerGenerator.kt @@ -25,11 +25,11 @@ class Ec2QuerySerializerGenerator(codegenContext: CodegenContext) : QuerySeriali override fun MemberShape.isFlattened(): Boolean = true - override fun serverOutputSerializer(operationShape: OperationShape): RuntimeType? { + override fun serverOutputSerializer(operationShape: OperationShape): RuntimeType { TODO("Not yet implemented") } - override fun serverErrorSerializer(shape: ShapeId): RuntimeType? { + override fun serverErrorSerializer(shape: ShapeId): RuntimeType { TODO("Not yet implemented") } } diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/JsonSerializerGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/JsonSerializerGenerator.kt index 7d403d4c1712e8ce4fe1f9d681d8856f710cf959..5dd82db964adb0660557c22a5b178cefe1482d16 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/JsonSerializerGenerator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/JsonSerializerGenerator.kt @@ -141,10 +141,13 @@ class JsonSerializerGenerator( private val operationSerModule = RustModule.private("operation_ser") private val jsonSerModule = RustModule.private("json_ser") - private fun structureSerializer(fnName: String, structureShape: StructureShape, includedMembers: List): RuntimeType? { - if (includedMembers.isEmpty()) { - return null - } + /** + * Reusable structure serializer implementation that can be used to generate serializing code for + * operation, error and structure shapes. + * We still generate the serializer symbol even if there are no included members because the server + * generation requires serializers for all output/error structures. + */ + private fun structureSerializer(fnName: String, structureShape: StructureShape, includedMembers: List): RuntimeType { return RuntimeType.forInlineFun(fnName, operationSerModule) { it.rustBlockTemplate( "pub fn $fnName(value: &#{target}) -> Result", @@ -220,14 +223,14 @@ class JsonSerializerGenerator( } } - override fun serverOutputSerializer(operationShape: OperationShape): RuntimeType? { + override fun serverOutputSerializer(operationShape: OperationShape): RuntimeType { val outputShape = operationShape.outputShape(model) val includedMembers = httpBindingResolver.responseMembers(operationShape, HttpLocation.DOCUMENT) val fnName = symbolProvider.serializeFunctionName(outputShape) return structureSerializer(fnName, outputShape, includedMembers) } - override fun serverErrorSerializer(shape: ShapeId): RuntimeType? { + override fun serverErrorSerializer(shape: ShapeId): RuntimeType { val errorShape = model.expectShape(shape, StructureShape::class.java) val includedMembers = httpBindingResolver.errorResponseBindings(shape).filter { it.location == HttpLocation.DOCUMENT }.map { it.member } val fnName = symbolProvider.serializeFunctionName(errorShape) diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/StructuredDataSerializerGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/StructuredDataSerializerGenerator.kt index 5c97f905852e87fed3b8e1e557ce498750472912..881e94ea5669009485da2522c8c4adb38fdd711d 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/StructuredDataSerializerGenerator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/StructuredDataSerializerGenerator.kt @@ -49,7 +49,7 @@ interface StructuredDataSerializerGenerator { * } * ``` */ - fun serverOutputSerializer(operationShape: OperationShape): RuntimeType? + fun serverOutputSerializer(operationShape: OperationShape): RuntimeType /** * Generate a serializer for a server operation error structure @@ -59,5 +59,5 @@ interface StructuredDataSerializerGenerator { * } * ``` */ - fun serverErrorSerializer(shape: ShapeId): RuntimeType? + fun serverErrorSerializer(shape: ShapeId): RuntimeType } diff --git a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/XmlBindingTraitSerializerGenerator.kt b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/XmlBindingTraitSerializerGenerator.kt index 014e1f78b82df5fd9beb7d801b1a7ef34e311c94..c1dd549648e09d50b195b07fb01e942569f25aa5 100644 --- a/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/XmlBindingTraitSerializerGenerator.kt +++ b/codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/smithy/protocols/serialize/XmlBindingTraitSerializerGenerator.kt @@ -177,11 +177,11 @@ class XmlBindingTraitSerializerGenerator( } } - override fun serverOutputSerializer(operationShape: OperationShape): RuntimeType? { + override fun serverOutputSerializer(operationShape: OperationShape): RuntimeType { TODO("Not yet implemented") } - override fun serverErrorSerializer(shape: ShapeId): RuntimeType? { + override fun serverErrorSerializer(shape: ShapeId): RuntimeType { TODO("Not yet implemented") }