From 24af34c29d4448d38af38d66d37eb034221995a9 Mon Sep 17 00:00:00 2001 From: Joe Wu Date: Tue, 5 Aug 2025 11:11:13 -0700 Subject: [PATCH 1/2] Add sourceLocation setting in fromNode() in trait codegen --- .../traitcodegen/test/CreatesTraitTest.java | 41 +++++++++++++++++++ .../generators/FromNodeGenerator.java | 10 +++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/smithy-trait-codegen/src/it/java/software/amazon/smithy/traitcodegen/test/CreatesTraitTest.java b/smithy-trait-codegen/src/it/java/software/amazon/smithy/traitcodegen/test/CreatesTraitTest.java index 63584c77f8d..42e01f89266 100644 --- a/smithy-trait-codegen/src/it/java/software/amazon/smithy/traitcodegen/test/CreatesTraitTest.java +++ b/smithy-trait-codegen/src/it/java/software/amazon/smithy/traitcodegen/test/CreatesTraitTest.java @@ -71,6 +71,7 @@ public class CreatesTraitTest { private static final ShapeId DUMMY_ID = ShapeId.from("ns.foo#foo"); private final TraitFactory provider = TraitFactory.createServiceFactory(); + private static final SourceLocation testLocation = new SourceLocation("test.smithy", 1, 2); static Stream createTraitTests() { return Stream.of( @@ -236,4 +237,44 @@ void createsTraitFromNode(ShapeId traitId, Node fromNode) { assertEquals(SourceLocation.NONE, trait.getSourceLocation()); assertEquals(trait, provider.createTrait(traitId, DUMMY_ID, trait.toNode()).orElseThrow(RuntimeException::new)); } + + static Stream createSourceLocationTests() { + return Stream.of( + Arguments.of(NumberListTrait.ID, + ArrayNode.builder() + .withValue(Node.from(1)) + .withValue(Node.from(2)) + .withValue(Node.from(3)) + .sourceLocation(testLocation) + .build() + .toNode()), + Arguments.of(NumberSetTrait.ID, + ArrayNode.builder() + .withValue(Node.from(1)) + .withValue(Node.from(2)) + .withValue(Node.from(3)) + .sourceLocation(testLocation) + .build() + .toNode()), + Arguments.of(NestedMapTrait.ID, + NestedMapTrait.builder() + .putValues("1", MapUtils.of("1", MapUtils.of("2", "3"))) + .sourceLocation(testLocation) + .build() + .toNode()), + Arguments.of(StructWithListOfMapTrait.ID, + StructWithListOfMapTrait.builder() + .addItems(MapUtils.of("1", "2")) + .addItems(MapUtils.of("3", "4")) + .sourceLocation(testLocation) + .build() + .toNode())); + } + + @ParameterizedTest + @MethodSource("createSourceLocationTests") + void sourceLocationTest(ShapeId traitId, Node fromNode) { + Trait trait = provider.createTrait(traitId, DUMMY_ID, fromNode).orElseThrow(RuntimeException::new); + assertEquals(testLocation, trait.getSourceLocation()); + } } diff --git a/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/generators/FromNodeGenerator.java b/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/generators/FromNodeGenerator.java index 07cea31125c..a032b3a1df8 100644 --- a/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/generators/FromNodeGenerator.java +++ b/smithy-trait-codegen/src/main/java/software/amazon/smithy/traitcodegen/generators/FromNodeGenerator.java @@ -37,6 +37,7 @@ import software.amazon.smithy.model.shapes.UnionShape; import software.amazon.smithy.model.traits.IdRefTrait; import software.amazon.smithy.model.traits.TimestampFormatTrait; +import software.amazon.smithy.model.traits.TraitDefinition; import software.amazon.smithy.model.traits.UniqueItemsTrait; import software.amazon.smithy.traitcodegen.SymbolProperties; import software.amazon.smithy.traitcodegen.TraitCodegenUtils; @@ -83,7 +84,8 @@ public Void listShape(ListShape shape) { symbol, Node.class, () -> { - writer.writeWithNoFormatting("Builder builder = builder();"); + writer.writeWithNoFormatting("Builder builder = builder()" + + (shape.hasTrait(TraitDefinition.ID) ? ".sourceLocation(node);" : ";")); shape.accept(new FromNodeMapperVisitor(writer, model, "node", symbolProvider)); writer.write("builder.values(value0);"); writer.writeWithNoFormatting("return builder.build();"); @@ -101,7 +103,8 @@ public Void mapShape(MapShape shape) { symbol, Node.class, () -> { - writer.writeWithNoFormatting("Builder builder = builder();"); + writer.writeWithNoFormatting("Builder builder = builder()" + + (shape.hasTrait(TraitDefinition.ID) ? ".sourceLocation(node);" : ";")); shape.accept(new FromNodeMapperVisitor(writer, model, "node", symbolProvider)); writer.writeWithNoFormatting("return builder.build();"); }); @@ -159,7 +162,8 @@ public Void structureShape(StructureShape shape) { writeFromNodeJavaDoc(); writer.write("public static $T fromNode($T node) {", symbol, Node.class); writer.indent(); - writer.write("Builder builder = builder();"); + writer.write("Builder builder = builder()" + + (shape.hasTrait(TraitDefinition.ID) ? ".sourceLocation(node);" : ";")); // If the shape has no members (i.e. is an annotation trait) then there will be no member setters, and we // need to terminate the line. writer.putContext("isEmpty", shape.members().isEmpty()); From ef3354f0d3bf1dcaf4d9ee5932e8183d0838a07a Mon Sep 17 00:00:00 2001 From: Joe Wu Date: Tue, 5 Aug 2025 11:29:41 -0700 Subject: [PATCH 2/2] Add more test for other trait types --- .../smithy/traitcodegen/test/CreatesTraitTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/smithy-trait-codegen/src/it/java/software/amazon/smithy/traitcodegen/test/CreatesTraitTest.java b/smithy-trait-codegen/src/it/java/software/amazon/smithy/traitcodegen/test/CreatesTraitTest.java index 42e01f89266..10b9a140f21 100644 --- a/smithy-trait-codegen/src/it/java/software/amazon/smithy/traitcodegen/test/CreatesTraitTest.java +++ b/smithy-trait-codegen/src/it/java/software/amazon/smithy/traitcodegen/test/CreatesTraitTest.java @@ -60,7 +60,9 @@ import software.amazon.smithy.model.SourceLocation; import software.amazon.smithy.model.node.ArrayNode; import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.NumberNode; import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.node.StringNode; import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.traits.Trait; import software.amazon.smithy.model.traits.TraitFactory; @@ -240,6 +242,16 @@ void createsTraitFromNode(ShapeId traitId, Node fromNode) { static Stream createSourceLocationTests() { return Stream.of( + Arguments.of(BigDecimalTrait.ID, new NumberNode(1, testLocation)), + Arguments.of(BigIntegerTrait.ID, new NumberNode(1, testLocation)), + Arguments.of(ByteTrait.ID, new NumberNode(1, testLocation)), + Arguments.of(DoubleTrait.ID, new NumberNode(1.2, testLocation)), + Arguments.of(FloatTrait.ID, new NumberNode(1.2, testLocation)), + Arguments.of(IntegerTrait.ID, new NumberNode(1, testLocation)), + Arguments.of(LongTrait.ID, new NumberNode(1L, testLocation)), + Arguments.of(ShortTrait.ID, new NumberNode(1, testLocation)), + Arguments.of(StringTrait.ID, new StringNode("a", testLocation)), + Arguments.of(TimestampTrait.ID, new StringNode("1985-04-12T23:20:50.52Z", testLocation)), Arguments.of(NumberListTrait.ID, ArrayNode.builder() .withValue(Node.from(1))