Skip to content

Commit 36dea0e

Browse files
author
luigi
committed
fix
1 parent 4fd9c2f commit 36dea0e

File tree

3 files changed

+84
-38
lines changed

3 files changed

+84
-38
lines changed

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/protocol/HttpBindingProtocolGenerator.kt

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -120,19 +120,27 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
120120
httpOperations.forEach { operation ->
121121
generateOperationSerializer(ctx, operation)
122122
}
123+
124+
if (ctx.settings.build.generateServiceProject){
125+
val modeledErrors = httpOperations.flatMap { it.errors }.map { ctx.model.expectShape(it) as StructureShape }.toSet()
126+
modeledErrors.forEach { generateExceptionSerializer(ctx, it) }
127+
}
123128
}
124129

125130
private fun generateDeserializers(ctx: ProtocolGenerator.GenerationContext) {
126131
val resolver = getProtocolHttpBindingResolver(ctx.model, ctx.service)
127132
// render HttpDeserialize for all operation outputs
128133
val httpOperations = resolver.bindingOperations()
129134
httpOperations.forEach { operation ->
135+
130136
generateOperationDeserializer(ctx, operation)
131137
}
132138

133139
// generate HttpDeserialize for exception types
134-
val modeledErrors = httpOperations.flatMap { it.errors }.map { ctx.model.expectShape(it) as StructureShape }.toSet()
135-
modeledErrors.forEach { generateExceptionDeserializer(ctx, it) }
140+
if (!ctx.settings.build.generateServiceProject){
141+
val modeledErrors = httpOperations.flatMap { it.errors }.map { ctx.model.expectShape(it) as StructureShape }.toSet()
142+
modeledErrors.forEach { generateExceptionDeserializer(ctx, it) }
143+
}
136144
}
137145

138146
override fun generateProtocolClient(ctx: ProtocolGenerator.GenerationContext) {
@@ -297,6 +305,44 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
297305
}
298306
}
299307

308+
/**
309+
* Generate HttpSerialize for a modeled error (exception)
310+
*/
311+
private fun generateExceptionSerializer(ctx: ProtocolGenerator.GenerationContext, shape: StructureShape) {
312+
val serializationSymbol = ctx.symbolProvider.toSymbol(shape)
313+
val exceptionSerializerSymbols = setOf(
314+
RuntimeTypes.Core.ExecutionContext,
315+
RuntimeTypes.Serde.SdkObjectDescriptor,
316+
RuntimeTypes.Serde.SdkFieldDescriptor,
317+
RuntimeTypes.Serde.SerialKind,
318+
RuntimeTypes.Serde.serializeStruct,
319+
RuntimeTypes.Http.Response.HttpResponse,
320+
)
321+
322+
val serializerSymbol = buildSymbol {
323+
val deserializerName = "${serializationSymbol.name}Serializer"
324+
definitionFile = "$deserializerName.kt"
325+
name = deserializerName
326+
namespace = ctx.settings.pkg.serde
327+
reference(serializationSymbol, SymbolReference.ContextOption.DECLARE)
328+
}
329+
330+
// exception serializers are never streaming
331+
val serdeMeta = HttpSerdeMeta(false)
332+
333+
// ctx.delegator.useSymbolWriter(serializerSymbol) { writer ->
334+
// val resolver = getProtocolHttpBindingResolver(ctx.model, ctx.service)
335+
// val bindings = resolver.responseBindings(shape)
336+
// writer
337+
// .addImport(exceptionSerializerSymbols)
338+
// .write("")
339+
// .openBlock("internal class #T {", serializerSymbol)
340+
// .write("")
341+
// .call { renderServiceHttpSerialize(ctx, serializationSymbol, bindings, serdeMeta, null, writer) }
342+
// .closeBlock("}")
343+
// }
344+
}
345+
300346
/**
301347
* Calls the operation body serializer function and binds the results to `builder.body`.
302348
* By default if no members are bound to the body this function renders nothing.
@@ -723,25 +769,13 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
723769
} else {
724770
resolver.responseBindings(shape)
725771
}
726-
727-
when (ctx.settings.build.generateServiceProject) {
728-
true ->
729-
writer
730-
.addImport(exceptionDeserializerSymbols)
731-
.write("")
732-
.openBlock("internal class #T {", deserializerSymbol)
733-
.write("")
734-
.call { renderServiceHttpDeserialize(ctx, deserializationSymbol, bindings, serdeMeta, null, writer) }
735-
.closeBlock("}")
736-
false ->
737-
writer
738-
.addImport(exceptionDeserializerSymbols)
739-
.write("")
740-
.openBlock("internal class #T: #T.NonStreaming<#T> {", deserializerSymbol, RuntimeTypes.HttpClient.Operation.HttpDeserializer, deserializationSymbol)
741-
.write("")
742-
.call { renderHttpDeserialize(ctx, deserializationSymbol, bindings, serdeMeta, null, writer) }
743-
.closeBlock("}")
744-
}
772+
writer
773+
.addImport(exceptionDeserializerSymbols)
774+
.write("")
775+
.openBlock("internal class #T: #T.NonStreaming<#T> {", deserializerSymbol, RuntimeTypes.HttpClient.Operation.HttpDeserializer, deserializationSymbol)
776+
.write("")
777+
.call { renderHttpDeserialize(ctx, deserializationSymbol, bindings, serdeMeta, null, writer) }
778+
.closeBlock("}")
745779
}
746780
}
747781

@@ -830,13 +864,15 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
830864
) {
831865
writer
832866
.openBlock(
833-
"public fun deserialize(context: #T, payload: #T?): #T {",
867+
"public fun deserialize(context: #T, call: #T, payload: #T?): #T {",
834868
RuntimeTypes.Core.ExecutionContext,
869+
RuntimeTypes.KtorServerCore.ApplicationCallClass,
835870
KotlinTypes.ByteArray,
836871
deserializationSymbol,
837872
)
838873

839-
writer.write("val builder = #T.Builder()", deserializationSymbol)
874+
writer.write("val request = call.request")
875+
.write("val builder = #T.Builder()", deserializationSymbol)
840876
.write("")
841877
.call {
842878
// headers
@@ -959,13 +995,11 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
959995
} else {
960996
""
961997
}
962-
// FIXME: Service supports only CBOR now. Modify this part to support service for other data format.
963-
// val message = if (ctx.settings.build.generateServiceProject) {
964-
// "request"
965-
// } else {
966-
// "response"
967-
// }
968-
val message = "response"
998+
val message = if (ctx.settings.build.generateServiceProject) {
999+
"request"
1000+
} else {
1001+
"response"
1002+
}
9691003
when (memberTarget) {
9701004
is NumberShape -> {
9711005
if (memberTarget is IntEnumShape) {

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/KtorStubGenerator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ internal class KtorStubGenerator(
287287
)
288288
write("val deserializer = ${shape.id.name}OperationDeserializer()")
289289
withBlock(
290-
"var requestObj = try { deserializer.deserialize(#T(), request) } catch (ex: Exception) {",
290+
"var requestObj = try { deserializer.deserialize(#T(), call, request) } catch (ex: Exception) {",
291291
"}",
292292
RuntimeTypes.Core.ExecutionContext,
293293
) {

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/service/contraints/ConstraintGenerator.kt

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,31 @@ internal class ConstraintGenerator(
3333
for (memberTrait in memberAndTargetTraits.values) {
3434
val traitGenerator = getTraitGeneratorFromTrait(prefix, memberName, memberTrait, pkgName, writer)
3535
if (memberTrait !is RequiredTrait) {
36-
writer.write("if ($prefix$memberName == null) { return }")
36+
writer.withBlock("if ($prefix$memberName != null) {", "}") {
37+
traitGenerator?.render()
38+
}
39+
} else {
40+
traitGenerator?.render()
3741
}
38-
traitGenerator?.render()
3942
}
4043

41-
for (member in targetShape.allMembers) {
42-
val newMemberPrefix = "${targetShape.id.name}".replaceFirstChar { it.lowercase() }
43-
writer.withBlock("if ($prefix$memberName != null) {", "}") {
44-
withBlock("for ($newMemberPrefix${member.key} in $prefix$memberName) {", "}") {
45-
call { generateConstraintValidations(newMemberPrefix, member.value, writer) }
44+
if (targetShape.isListShape){
45+
for (member in targetShape.allMembers) {
46+
val newMemberPrefix = "${targetShape.id.name}".replaceFirstChar { it.lowercase() }
47+
writer.withBlock("if ($prefix$memberName != null) {", "}") {
48+
withBlock("for ($newMemberPrefix${member.key} in $prefix$memberName ?: listOf()) {", "}") {
49+
call { generateConstraintValidations(newMemberPrefix, member.value, writer) }
50+
}
4651
}
4752
}
4853
}
54+
55+
if (targetShape.isStructureShape){
56+
for (member in targetShape.allMembers) {
57+
val newMemberPrefix = "$prefix$memberName?."
58+
generateConstraintValidations(newMemberPrefix, member.value, writer)
59+
}
60+
}
4961
}
5062

5163
private fun renderRequestConstraintsValidation() {

0 commit comments

Comments
 (0)