private static String createTraitDiffMessage(Shape oldShape, Shape newShape) {
        StringJoiner joiner = new StringJoiner(". ");
        ChangedShape<Shape> targetChange = new ChangedShape<>(oldShape, newShape);

        Set<ShapeId> removedTraits = targetChange.removedTraits()
                .map(Trait::toShapeId)
                .collect(Collectors.toCollection(TreeSet::new));

        if (!removedTraits.isEmpty()) {
            joiner.add("The targeted shape no longer has the following traits: " + removedTraits);
        }

        Set<ShapeId> addedTraits = targetChange.addedTraits()
                .map(Trait::toShapeId)
                .collect(Collectors.toCollection(TreeSet::new));

        if (!addedTraits.isEmpty()) {
            joiner.add("The newly targeted shape now has the following additional traits: " + addedTraits);
        }

        // Only select the traits that exist in both placed but changed.
        Set<ShapeId> changedTraits = new TreeSet<>(targetChange.getTraitDifferences().keySet());
        changedTraits.removeAll(addedTraits);
        changedTraits.removeAll(removedTraits);

        if (!changedTraits.isEmpty()) {
            joiner.add("The newly targeted shape has traits that differ from the previous shape: " + changedTraits);
        }

        return joiner.toString();
    }
These traits are traits that are known to significantly influence
code generation. Right now it just contains the enum trait, but
other traits could be added in the future as needed.
smithy-diff/src/main/java/software/amazon/smithy/diff/evaluators/ChangedMemberTarget.java