From 441bdd89afa7e8bde96b8475134ddea996f8da4c Mon Sep 17 00:00:00 2001
From: Jordon Phillips <JordonPhillips@users.noreply.github.com>
Date: Tue, 24 Oct 2023 12:35:55 +0200
Subject: [PATCH] Configure integrations with isolated settings

---
 .../amazon/smithy/codegen/core/SmithyIntegration.java | 11 +++++------
 .../smithy/codegen/core/directed/CodegenDirector.java |  7 +++++--
 .../codegen/core/directed/CapturingIntegration.java   |  5 +++++
 .../codegen/core/directed/CodegenDirectorTest.java    |  4 +++-
 4 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/smithy-codegen-core/src/main/java/software/amazon/smithy/codegen/core/SmithyIntegration.java b/smithy-codegen-core/src/main/java/software/amazon/smithy/codegen/core/SmithyIntegration.java
index 1e60ff918fa..a0a5ff9bf26 100644
--- a/smithy-codegen-core/src/main/java/software/amazon/smithy/codegen/core/SmithyIntegration.java
+++ b/smithy-codegen-core/src/main/java/software/amazon/smithy/codegen/core/SmithyIntegration.java
@@ -75,9 +75,8 @@ default byte priority() {
      * Configures the integration.
      *
      * <p>This provides access to both the parsed settings for the generator and
-     * an unparsed {@link ObjectNode} containing settings for all integrations.
-     * Integrations SHOULD put all of their settings inside a nested object so
-     * that they don't experience conflicts with other integrations.
+     * an unparsed {@link ObjectNode} containing settings for this particular
+     * integration.
      *
      * <p>The following {@code smithy-build.json} file contains an example of how
      * this configuration will be set.
@@ -102,9 +101,9 @@ default byte priority() {
      * }
      * }</pre>
      *
-     * <p>In this example, everything under the key {@code integrations} will be
-     * provided as the {@code rawSettings} value and the {@code my-integration} key
-     * represents the settings for a particular integration.
+     * <p>In this example, an integration whose {@link #name} is {@code my-integration}
+     * Would receive the extra settings from the key of the same name within the
+     * {@code integrations} node.
      *
      * <p>Integrations SHOULD use modeled traits as much as possible to drive
      * configuration. This is intended for configuration that doesn't make sense
diff --git a/smithy-codegen-core/src/main/java/software/amazon/smithy/codegen/core/directed/CodegenDirector.java b/smithy-codegen-core/src/main/java/software/amazon/smithy/codegen/core/directed/CodegenDirector.java
index 474a04fa003..81e024138d5 100644
--- a/smithy-codegen-core/src/main/java/software/amazon/smithy/codegen/core/directed/CodegenDirector.java
+++ b/smithy-codegen-core/src/main/java/software/amazon/smithy/codegen/core/directed/CodegenDirector.java
@@ -145,6 +145,8 @@ public void model(Model model) {
     /**
      * Sets the required settings object used for code generation.
      *
+     * <p>{@link #integrationSettings} MUST also be set.
+     *
      * @param settings Settings object.
      */
     public void settings(S settings) {
@@ -205,7 +207,8 @@ public S settings(Class<S> settingsType, Node settingsNode) {
      * }</pre>
      *
      * <p>In this example, the value of the {@code integrations} key is what must
-     * be passed to this method.
+     * be passed to this method. The value of the {@code my-integration} key will
+     * then be provided to an integration with the name {@code my-integration}.
      *
      * @param integrationSettings Settings used to configure integrations.
      */
@@ -411,7 +414,7 @@ private List<I> findIntegrations() {
         List<I> integrations = SmithyIntegration.sort(integrationFinder.get());
         integrations.forEach(i -> {
             LOGGER.finest(() -> "Found integration " + i.getClass().getCanonicalName());
-            i.configure(settings, integrationSettings);
+            i.configure(settings, integrationSettings.getObjectMember(i.name()).orElse(Node.objectNode()));
         });
         return integrations;
     }
diff --git a/smithy-codegen-core/src/test/java/software/amazon/smithy/codegen/core/directed/CapturingIntegration.java b/smithy-codegen-core/src/test/java/software/amazon/smithy/codegen/core/directed/CapturingIntegration.java
index 6a185a941ac..73fe5997ddf 100644
--- a/smithy-codegen-core/src/test/java/software/amazon/smithy/codegen/core/directed/CapturingIntegration.java
+++ b/smithy-codegen-core/src/test/java/software/amazon/smithy/codegen/core/directed/CapturingIntegration.java
@@ -11,6 +11,11 @@
 public class CapturingIntegration implements TestIntegration {
     public ObjectNode integrationSettings = Node.objectNode();
 
+    @Override
+    public String name() {
+        return "capturing-integration";
+    }
+
     @Override
     public void configure(TestSettings settings, ObjectNode integrationSettings) {
         this.integrationSettings = integrationSettings;
diff --git a/smithy-codegen-core/src/test/java/software/amazon/smithy/codegen/core/directed/CodegenDirectorTest.java b/smithy-codegen-core/src/test/java/software/amazon/smithy/codegen/core/directed/CodegenDirectorTest.java
index 9d6c61f6e5c..df320005b18 100644
--- a/smithy-codegen-core/src/test/java/software/amazon/smithy/codegen/core/directed/CodegenDirectorTest.java
+++ b/smithy-codegen-core/src/test/java/software/amazon/smithy/codegen/core/directed/CodegenDirectorTest.java
@@ -360,9 +360,11 @@ public void testConfiguresIntegrations() {
             .unwrap();
 
         ObjectNode integrationSettings = Node.objectNode().withMember("spam", "eggs");
+        ObjectNode allIntegrationSettings = Node.objectNode()
+                .withMember("capturing-integration", integrationSettings);
         ObjectNode settings = Node.objectNode()
             .withMember("foo", "hi")
-            .withMember("integrations", integrationSettings);
+            .withMember("integrations", allIntegrationSettings);
         runner.settings(TestSettings.class, settings);
         runner.directedCodegen(testDirected);
         runner.fileManifest(manifest);