From 673e385c732933030769d6c5980c8460235e5241 Mon Sep 17 00:00:00 2001
From: 82marbag <69267416+82marbag@users.noreply.github.com>
Date: Wed, 27 Sep 2023 14:17:55 +0100
Subject: [PATCH] Add injection hook for structures in no service (#3001)

## Motivation and Context
This change will allow to render structures in no service closures with
a decorator.

## Checklist
<!--- If a checkbox below is not applicable, then please DELETE it
rather than leaving it unchecked -->
- [ ] I have updated `CHANGELOG.next.toml` if I made changes to the
smithy-rs codegen or runtime crates
- [ ] I have updated `CHANGELOG.next.toml` if I made changes to the AWS
SDK, generated SDK code, or SDK runtime crates

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._

Signed-off-by: Daniele Ahmed <ahmeddan@amazon.de>
---
 .../server/smithy/ServerCodegenVisitor.kt       |  4 ++++
 .../smithy/customize/ServerCodegenDecorator.kt  | 17 ++++++++++++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt
index 156cc455e..c8dc16caf 100644
--- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt
+++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt
@@ -621,6 +621,7 @@ open class ServerCodegenVisitor(
      *  - Operations ser/de
      *  - Errors via `ServerOperationErrorGenerator`
      *  - OperationShapes via `ServerOperationGenerator`
+     *  - Additional structure shapes via `postprocessGenerateAdditionalStructures`
      */
     override fun operationShape(shape: OperationShape) {
         // Generate errors.
@@ -637,6 +638,9 @@ open class ServerCodegenVisitor(
         rustCrate.withModule(ServerRustModule.Operation) {
             protocolGenerator.renderOperation(this, shape)
         }
+
+        codegenDecorator.postprocessGenerateAdditionalStructures(shape)
+            .forEach { structureShape -> this.structureShape(structureShape) }
     }
 
     override fun blobShape(shape: BlobShape) {
diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customize/ServerCodegenDecorator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customize/ServerCodegenDecorator.kt
index 2522024ef..06f9c3c09 100644
--- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customize/ServerCodegenDecorator.kt
+++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customize/ServerCodegenDecorator.kt
@@ -6,7 +6,9 @@
 package software.amazon.smithy.rust.codegen.server.smithy.customize
 
 import software.amazon.smithy.build.PluginContext
+import software.amazon.smithy.model.shapes.OperationShape
 import software.amazon.smithy.model.shapes.ShapeId
+import software.amazon.smithy.model.shapes.StructureShape
 import software.amazon.smithy.rust.codegen.core.smithy.customize.CombinedCoreCodegenDecorator
 import software.amazon.smithy.rust.codegen.core.smithy.customize.CoreCodegenDecorator
 import software.amazon.smithy.rust.codegen.core.smithy.protocols.ProtocolMap
@@ -31,6 +33,14 @@ interface ServerCodegenDecorator : CoreCodegenDecorator<ServerCodegenContext, Se
      * constrained but the `ValidationException` shape is not attached to the operation's errors.
      */
     fun postprocessValidationExceptionNotAttachedErrorMessage(validationResult: ValidationResult) = validationResult
+
+    /**
+     * For each operation in the service's closure, this hook allows decorators to return a collection of structure shapes that will additionally be generated.
+     * If a structure shape is in the service's closure, note that returning it here will cause for it to be generated more than once,
+     * making the resulting crate not compile (since it will contain more than one struct with the same name).
+     * Therefore, ensure that all the structure shapes returned by this method are not in the service's closure.
+     */
+    fun postprocessGenerateAdditionalStructures(operationShape: OperationShape): List<StructureShape> = emptyList()
 }
 
 /**
@@ -38,7 +48,7 @@ interface ServerCodegenDecorator : CoreCodegenDecorator<ServerCodegenContext, Se
  *
  * This makes the actual concrete codegen simpler by not needing to deal with multiple separate decorators.
  */
-class CombinedServerCodegenDecorator(private val decorators: List<ServerCodegenDecorator>) :
+class CombinedServerCodegenDecorator(decorators: List<ServerCodegenDecorator>) :
     CombinedCoreCodegenDecorator<ServerCodegenContext, ServerRustSettings, ServerCodegenDecorator>(decorators),
     ServerCodegenDecorator {
 
@@ -64,6 +74,11 @@ class CombinedServerCodegenDecorator(private val decorators: List<ServerCodegenD
             decorator.postprocessValidationExceptionNotAttachedErrorMessage(accumulated)
         }
 
+    override fun postprocessGenerateAdditionalStructures(operationShape: OperationShape): List<StructureShape> {
+        return orderedDecorators.map { decorator -> decorator.postprocessGenerateAdditionalStructures(operationShape) }
+            .flatten()
+    }
+
     companion object {
         fun fromClasspath(
             context: PluginContext,
-- 
GitLab