Repository: smithy-lang/smithy
Pull request #2042 (2023-11-16 17:31:21)

Fix removal of applied non-prelude meta traits
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.



Patch:
diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/neighbor/UnreferencedTraitDefinitions.java b/smithy-model/src/main/java/software/amazon/smithy/model/neighbor/UnreferencedTraitDefinitions.java
index 1860c5992..be216e006 100644
--- a/smithy-model/src/main/java/software/amazon/smithy/model/neighbor/UnreferencedTraitDefinitions.java
+++ b/smithy-model/src/main/java/software/amazon/smithy/model/neighbor/UnreferencedTraitDefinitions.java
@@ -15,6 +15,10 @@
 
 package software.amazon.smithy.model.neighbor;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -23,9 +27,9 @@ import software.amazon.smithy.model.knowledge.NeighborProviderIndex;
 import software.amazon.smithy.model.loader.Prelude;
 import software.amazon.smithy.model.shapes.ServiceShape;
 import software.amazon.smithy.model.shapes.Shape;
+import software.amazon.smithy.model.shapes.ShapeId;
 import software.amazon.smithy.model.traits.TraitDefinition;
 import software.amazon.smithy.utils.FunctionalUtils;
-import software.amazon.smithy.utils.OptionalUtils;
 
 /**
  * Finds trait definitions that are not connected to a service shape.
@@ -64,10 +68,28 @@ public final class UnreferencedTraitDefinitions {
                 .map(Shape::getAllTraits)
                 .flatMap(traits -> traits.keySet().stream())
                 .distinct()
-                .flatMap(traitId -> OptionalUtils.stream(model.getShape(traitId)))
+                .flatMap(traitId -> getTraitShapes(model, traitId).stream())
                 .filter(keepFilter)
                 .forEach(unused::remove);
 
         return unused;
     }
+
+    private Collection<Shape> getTraitShapes(Model model, ShapeId traitId) {
+        return getTraitShapes(model, traitId, new HashMap<>()).values();
+    }
+
+    private Map<ShapeId, Shape> getTraitShapes(Model model, ShapeId traitId, Map<ShapeId, Shape> traitShapes) {
+        Optional<Shape> initialTraitShapeOp = model.getShape(traitId);
+        if (initialTraitShapeOp.isPresent()) {
+            Shape initialTraitShape = initialTraitShapeOp.get();
+            traitShapes.put(traitId, initialTraitShape);
+            for (ShapeId metaTraitId : initialTraitShape.getAllTraits().keySet()) {
+                if (!metaTraitId.equals(TraitDefinition.ID) && !traitShapes.containsKey(metaTraitId)) {
+                    traitShapes.putAll(getTraitShapes(model, metaTraitId, traitShapes));
+                }
+            }
+        }
+        return traitShapes;
+    }
 }


Test patch:
diff --git a/smithy-model/src/test/resources/software/amazon/smithy/model/neighbor/unreferenced-test.json b/smithy-model/src/test/resources/software/amazon/smithy/model/neighbor/unreferenced-test.json
index eb377d2e6..3226109ec 100644
--- a/smithy-model/src/test/resources/software/amazon/smithy/model/neighbor/unreferenced-test.json
+++ b/smithy-model/src/test/resources/software/amazon/smithy/model/neighbor/unreferenced-test.json
@@ -9,7 +9,9 @@
                 }
             },
             "traits": {
-                "smithy.api#trait": {}
+                "smithy.api#trait": {},
+                "ns.foo#meta": {},
+                "ns.foo#threeMeta": {}
             }
         },
         "ns.foo#quux": {
@@ -23,6 +25,41 @@
                 "smithy.api#trait": {}
             }
         },
+        "ns.foo#meta": {
+            "type": "structure",
+            "members": {
+                "member": {
+                    "target": "smithy.api#String"
+                }
+            },
+            "traits": {
+                "smithy.api#trait": {},
+                "ns.foo#tooMeta": {},
+                "ns.foo#threeMeta": {}
+            }
+        },
+        "ns.foo#tooMeta": {
+            "type": "structure",
+            "members": {
+                "member": {
+                    "target": "smithy.api#String"
+                }
+            },
+            "traits": {
+                "smithy.api#trait": {}
+            }
+        },
+        "ns.foo#threeMeta": {
+            "type": "structure",
+            "members": {
+                "member": {
+                    "target": "smithy.api#String"
+                }
+            },
+            "traits": {
+                "smithy.api#trait": {}
+            }
+        },
         "ns.foo#MyService": {
             "type": "service",
             "version": "2017-01-19",