From df7a01df0263c4b4a32949a510cedcb30462b536 Mon Sep 17 00:00:00 2001 From: Joe Wu Date: Fri, 1 Aug 2025 15:51:16 -0700 Subject: [PATCH 1/3] Fix trait codegen for list or map traits with annotation or javadoc --- .../DeprecatedAnnotationInterceptor.java | 5 ++- .../javadoc/JavaDocInjectorInterceptor.java | 4 ++ .../annotations/AnnotationsTest.java | 34 +++++++++++++++++ .../integrations/javadoc/JavadocTest.java | 38 +++++++++++++++++++ .../annotations/annotations-test.smithy | 11 ++++++ .../integrations/javadoc/javadoc-test.smithy | 18 +++++++++ 6 files changed, 109 insertions(+), 1 deletion(-) diff --git a/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/integrations/annotations/DeprecatedAnnotationInterceptor.java b/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/integrations/annotations/DeprecatedAnnotationInterceptor.java index ec79c2cee15..3dd961cee60 100644 --- a/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/integrations/annotations/DeprecatedAnnotationInterceptor.java +++ b/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/integrations/annotations/DeprecatedAnnotationInterceptor.java @@ -4,7 +4,9 @@ */ package software.amazon.smithy.traitcodegen.integrations.annotations; +import software.amazon.smithy.model.shapes.Shape; import software.amazon.smithy.model.traits.DeprecatedTrait; +import software.amazon.smithy.model.traits.TraitDefinition; import software.amazon.smithy.traitcodegen.sections.ClassSection; import software.amazon.smithy.traitcodegen.sections.EnumVariantSection; import software.amazon.smithy.traitcodegen.sections.GetterSection; @@ -27,7 +29,8 @@ public boolean isIntercepted(CodeSection section) { if (section instanceof ClassSection) { return ((ClassSection) section).shape().hasTrait(DeprecatedTrait.ID); } else if (section instanceof GetterSection) { - return ((GetterSection) section).shape().hasTrait(DeprecatedTrait.ID); + Shape shape = ((GetterSection) section).shape(); + return shape.hasTrait(DeprecatedTrait.ID) && !shape.hasTrait(TraitDefinition.ID); } else if (section instanceof EnumVariantSection) { return ((EnumVariantSection) section).memberShape().hasTrait(DeprecatedTrait.ID); } diff --git a/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavaDocInjectorInterceptor.java b/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavaDocInjectorInterceptor.java index bf8a7b6204a..55259fc8fd3 100644 --- a/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavaDocInjectorInterceptor.java +++ b/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavaDocInjectorInterceptor.java @@ -5,6 +5,7 @@ package software.amazon.smithy.traitcodegen.integrations.javadoc; import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.traits.TraitDefinition; import software.amazon.smithy.traitcodegen.sections.ClassSection; import software.amazon.smithy.traitcodegen.sections.EnumVariantSection; import software.amazon.smithy.traitcodegen.sections.GetterSection; @@ -40,6 +41,9 @@ public void prepend(TraitCodegenWriter writer, CodeSection section) { shape = ((ClassSection) section).shape(); } else if (section instanceof GetterSection) { shape = ((GetterSection) section).shape(); + if (shape.hasTrait(TraitDefinition.ID)) { + return; + } } else if (section instanceof EnumVariantSection) { shape = ((EnumVariantSection) section).memberShape(); } else { diff --git a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java index 70eab9865ff..2ccd479360a 100644 --- a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java +++ b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java @@ -130,6 +130,40 @@ void unstableAnnotationOnEnumVariant() { assertTrue(fileContents.contains(expected)); } + @Test + void deprecatedAnnotationOnList() { + String fileContents = getFileContentsFromShapeName("DeprecatedList", true); + String expected = "@Deprecated\n" + + "@SmithyGenerated\n" + + "public final class DeprecatedListTrait"; + assertTrue(fileContents.contains(expected)); + } + + @Test + void noDeprecatedAnnotationOnListGetValues() { + String fileContents = getFileContentsFromShapeName("DeprecatedList", true); + String expected = " }\n\n" + + " public List getValues() {"; + assertTrue(fileContents.contains(expected)); + } + + @Test + void deprecatedAnnotationOnMap() { + String fileContents = getFileContentsFromShapeName("DeprecatedMap", true); + String expected = "@Deprecated\n" + + "@SmithyGenerated\n" + + "public final class DeprecatedMapTrait"; + assertTrue(fileContents.contains(expected)); + } + + @Test + void noDeprecatedAnnotationOnMapGetValues() { + String fileContents = getFileContentsFromShapeName("DeprecatedMap", true); + String expected = " }\n\n" + + " public Map getValues() {"; + assertTrue(fileContents.contains(expected)); + } + private String getFileContentsFromShapeName(String className, boolean isTrait) { String suffix = isTrait ? "Trait" : ""; String path = String.format("com/example/traits/%s%s.java", className, suffix); diff --git a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavadocTest.java b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavadocTest.java index a69a0e8bad7..d5de08302d0 100644 --- a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavadocTest.java +++ b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavadocTest.java @@ -227,6 +227,44 @@ void allDocumentationIncludedTogetherEnumVariant() { assertTrue(fileContents.contains(expected)); } + @Test + void deprecatedAnnotationAndNoteForListTrait() { + String fileContents = getFileContentsFromShapeName("DeprecatedList", true); + String expectedForClass = "/**\n" + + " * A deprecated list trait\n" + + " *\n" + + " * @see Example\n" + + " * @since 4.5\n" + + " * @deprecated As of yesterday. A message\n" + + " */\n" + + "@Deprecated\n" + + "@SmithyGenerated\n" + + "public final class DeprecatedListTrait"; + String expectedForGetter = " }\n\n" + + " public List getValues() {"; + assertTrue(fileContents.contains(expectedForClass)); + assertTrue(fileContents.contains(expectedForGetter)); + } + + @Test + void deprecatedAnnotationAndNoteForMapTrait() { + String fileContents = getFileContentsFromShapeName("DeprecatedMap", true); + String expectedForClass = "/**\n" + + " * A deprecated map trait\n" + + " *\n" + + " * @see Example\n" + + " * @since 4.5\n" + + " * @deprecated As of yesterday. A message\n" + + " */\n" + + "@Deprecated\n" + + "@SmithyGenerated\n" + + "public final class DeprecatedMapTrait"; + String expectedForGetter = " }\n\n" + + " public Map getValues() {"; + assertTrue(fileContents.contains(expectedForClass)); + assertTrue(fileContents.contains(expectedForGetter)); + } + private String getFileContentsFromShapeName(String className, boolean isTrait) { String suffix = isTrait ? "Trait" : ""; String path = String.format("com/example/traits/%s%s.java", className, suffix); diff --git a/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/annotations/annotations-test.smithy b/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/annotations/annotations-test.smithy index 8ec5896252a..eaad4672da9 100644 --- a/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/annotations/annotations-test.smithy +++ b/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/annotations/annotations-test.smithy @@ -41,4 +41,15 @@ enum EnumWithAnnotations { UNSTABLE } +@trait +@deprecated +list DeprecatedList { + member: Integer +} +@trait +@deprecated +map DeprecatedMap { + key: String + value: Integer +} diff --git a/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/javadoc/javadoc-test.smithy b/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/javadoc/javadoc-test.smithy index d9f154cc0a6..6bb3473f516 100644 --- a/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/javadoc/javadoc-test.smithy +++ b/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/javadoc/javadoc-test.smithy @@ -78,3 +78,21 @@ enum EnumVariantsTest { B } +/// A deprecated list trait +@trait +@deprecated(message: "A message", since: "yesterday") +@externalDocumentation(Example: "https://example.com") +@since("4.5") +list DeprecatedList { + member: Integer +} + +/// A deprecated map trait +@trait +@deprecated(message: "A message", since: "yesterday") +@externalDocumentation(Example: "https://example.com") +@since("4.5") +map DeprecatedMap { + key: String + value: Integer +} From dd57509a806d22430a57a6e1e90be7c1f6661072 Mon Sep 17 00:00:00 2001 From: Joe Wu Date: Fri, 1 Aug 2025 16:03:09 -0700 Subject: [PATCH 2/3] Add test for list / map as structure member --- .../integrations/annotations/AnnotationsTest.java | 13 +++++++++++-- .../integrations/javadoc/JavadocTest.java | 13 +++++++++++++ .../annotations/annotations-test.smithy | 8 ++++++++ .../integrations/javadoc/javadoc-test.smithy | 7 +++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java index 2ccd479360a..a45e8b53379 100644 --- a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java +++ b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java @@ -131,7 +131,7 @@ void unstableAnnotationOnEnumVariant() { } @Test - void deprecatedAnnotationOnList() { + void deprecatedAnnotationOnListTrait() { String fileContents = getFileContentsFromShapeName("DeprecatedList", true); String expected = "@Deprecated\n" + "@SmithyGenerated\n" + @@ -148,7 +148,7 @@ void noDeprecatedAnnotationOnListGetValues() { } @Test - void deprecatedAnnotationOnMap() { + void deprecatedAnnotationOnMapTrait() { String fileContents = getFileContentsFromShapeName("DeprecatedMap", true); String expected = "@Deprecated\n" + "@SmithyGenerated\n" + @@ -164,6 +164,15 @@ void noDeprecatedAnnotationOnMapGetValues() { assertTrue(fileContents.contains(expected)); } + @Test + void deprecatedAnnotationOnListMember() { + String fileContents = getFileContentsFromShapeName("DeprecatedStructure", true); + String expected = " @Deprecated\n" + + " public Optional> getDeprecatedMap() {"; + assertTrue(fileContents.contains(expected)); + } + + private String getFileContentsFromShapeName(String className, boolean isTrait) { String suffix = isTrait ? "Trait" : ""; String path = String.format("com/example/traits/%s%s.java", className, suffix); diff --git a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavadocTest.java b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavadocTest.java index d5de08302d0..c9f75041738 100644 --- a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavadocTest.java +++ b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/javadoc/JavadocTest.java @@ -265,6 +265,19 @@ void deprecatedAnnotationAndNoteForMapTrait() { assertTrue(fileContents.contains(expectedForGetter)); } + @Test + void deprecatedAnnotationAndNoteForListMember() { + String fileContents = getFileContentsFromShapeName("DeprecatedStructure", true); + String expected = " /**\n" + + " * @deprecated As of yesterday. A message\n" + + " */\n" + + " @Deprecated\n" + + " public Optional> getDeprecatedList() {\n" + + " return Optional.ofNullable(deprecatedList);\n" + + " }"; + assertTrue(fileContents.contains(expected)); + } + private String getFileContentsFromShapeName(String className, boolean isTrait) { String suffix = isTrait ? "Trait" : ""; String path = String.format("com/example/traits/%s%s.java", className, suffix); diff --git a/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/annotations/annotations-test.smithy b/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/annotations/annotations-test.smithy index eaad4672da9..5301ab69ab4 100644 --- a/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/annotations/annotations-test.smithy +++ b/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/annotations/annotations-test.smithy @@ -20,6 +20,14 @@ structure DeprecatedStructure { /// Has docs in addition to deprecated @deprecated deprecatedWithDocs: String + + @deprecated + deprecatedMap: MemberMap +} + +map MemberMap { + key: String + value: Integer } @trait diff --git a/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/javadoc/javadoc-test.smithy b/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/javadoc/javadoc-test.smithy index 6bb3473f516..f881b20e951 100644 --- a/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/javadoc/javadoc-test.smithy +++ b/smithy-trait-codegen/src/test/resources/software/amazon/smithy/traitcodegen/integrations/javadoc/javadoc-test.smithy @@ -31,6 +31,13 @@ structure DeprecatedStructure { /// Has docs in addition to deprecated @deprecated(message: "A message", since: "yesterday") deprecatedWithDocs: String + + @deprecated(message: "A message", since: "yesterday") + deprecatedList: MemberList +} + +list MemberList { + member: Integer } @trait From ce3c7e65f0b1d5292b66436009e925f91774c275 Mon Sep 17 00:00:00 2001 From: Joe Wu Date: Fri, 1 Aug 2025 16:27:12 -0700 Subject: [PATCH 3/3] Fix style issue --- .../traitcodegen/integrations/annotations/AnnotationsTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java index a45e8b53379..99051d761f9 100644 --- a/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java +++ b/smithy-trait-codegen/src/test/java/software/amazon/smithy/traitcodegen/integrations/annotations/AnnotationsTest.java @@ -172,7 +172,6 @@ void deprecatedAnnotationOnListMember() { assertTrue(fileContents.contains(expected)); } - private String getFileContentsFromShapeName(String className, boolean isTrait) { String suffix = isTrait ? "Trait" : ""; String path = String.format("com/example/traits/%s%s.java", className, suffix);