diff --git a/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/simple-service-aws.cfn.json b/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/simple-service-aws.cfn.json index 2c61b7979ed..e0d8e2ffe83 100644 --- a/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/simple-service-aws.cfn.json +++ b/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/simple-service-aws.cfn.json @@ -19,7 +19,8 @@ }, "properties": { "FooDeprecatedMutableProperty": { - "type": "string" + "type": "string", + "description": "This shape is deprecated: Use the `fooValidFullyMutableProperty` property." }, "FooId": { "type": "string" diff --git a/smithy-jsonschema/src/main/java/software/amazon/smithy/jsonschema/JsonSchemaShapeVisitor.java b/smithy-jsonschema/src/main/java/software/amazon/smithy/jsonschema/JsonSchemaShapeVisitor.java index 46550dfff93..e20a4ae13d7 100644 --- a/smithy-jsonschema/src/main/java/software/amazon/smithy/jsonschema/JsonSchemaShapeVisitor.java +++ b/smithy-jsonschema/src/main/java/software/amazon/smithy/jsonschema/JsonSchemaShapeVisitor.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.regex.Pattern; import software.amazon.smithy.model.Model; @@ -43,6 +44,7 @@ import software.amazon.smithy.model.shapes.TimestampShape; import software.amazon.smithy.model.shapes.UnionShape; import software.amazon.smithy.model.traits.DefaultTrait; +import software.amazon.smithy.model.traits.DeprecatedTrait; import software.amazon.smithy.model.traits.DocumentationTrait; import software.amazon.smithy.model.traits.EnumTrait; import software.amazon.smithy.model.traits.LengthTrait; @@ -274,9 +276,7 @@ private Schema.Builder createBuilder(Shape shape, String defaultType) { * @return Returns the updated schema builder. */ private Schema.Builder updateBuilder(Shape shape, Schema.Builder builder) { - shape.getMemberTrait(model, DocumentationTrait.class) - .map(DocumentationTrait::getValue) - .ifPresent(builder::description); + descriptionMessage(shape).ifPresent(builder::description); shape.getTrait(TitleTrait.class) .map(TitleTrait::getValue) @@ -332,6 +332,24 @@ private Schema.Builder updateBuilder(Shape shape, Schema.Builder builder) { return builder; } + private Optional descriptionMessage(Shape shape) { + StringBuilder builder = new StringBuilder(); + shape + .getTrait(DocumentationTrait.class) + .ifPresent(trait -> + builder.append(trait.getValue()) + ); + shape + .getTrait(DeprecatedTrait.class) + .ifPresent(trait -> + builder + .append("\n") + .append(trait.getDeprecatedDescription(shape.getType())) + ); + String description = builder.toString().trim(); + return description.isEmpty() ? Optional.empty() : Optional.of(description); + } + /** * Builds a schema builder and applied schema mappers. * diff --git a/smithy-model/src/main/java/software/amazon/smithy/model/traits/DeprecatedTrait.java b/smithy-model/src/main/java/software/amazon/smithy/model/traits/DeprecatedTrait.java index d5b0b6ffab3..d960b5d196f 100644 --- a/smithy-model/src/main/java/software/amazon/smithy/model/traits/DeprecatedTrait.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/traits/DeprecatedTrait.java @@ -19,6 +19,7 @@ import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.shapes.ShapeType; import software.amazon.smithy.utils.MapUtils; import software.amazon.smithy.utils.ToSmithyBuilder; @@ -72,6 +73,20 @@ public Optional getMessage() { return Optional.ofNullable(message); } + public String getDeprecatedDescription(ShapeType shapeType) { + StringBuilder builder = new StringBuilder("This "); + builder.append(shapeType == ShapeType.OPERATION ? "operation" : "shape").append(" is deprecated"); + if (since != null) { + builder.append(" since ").append(since); + } + if (message != null) { + builder.append(": ").append(message); + } else { + builder.append("."); + } + return builder.toString(); + } + @Override protected Node createNode() { return new ObjectNode(MapUtils.of(), getSourceLocation()) diff --git a/smithy-model/src/test/java/software/amazon/smithy/model/traits/DeprecatedTraitTest.java b/smithy-model/src/test/java/software/amazon/smithy/model/traits/DeprecatedTraitTest.java index bcb4c8979f4..242d310ceab 100644 --- a/smithy-model/src/test/java/software/amazon/smithy/model/traits/DeprecatedTraitTest.java +++ b/smithy-model/src/test/java/software/amazon/smithy/model/traits/DeprecatedTraitTest.java @@ -26,6 +26,7 @@ import software.amazon.smithy.model.SourceException; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.shapes.ShapeType; public class DeprecatedTraitTest { @Test @@ -48,4 +49,29 @@ public void validatesInput() { provider.createTrait(ShapeId.from("smithy.api#deprecated"), ShapeId.from("ns.qux#foo"), Node.from("abc")); }); } + + @Test + public void returnDefaultDescription() { + DeprecatedTrait deprecatedTrait = DeprecatedTrait.builder().build(); + assertThat(deprecatedTrait.getDeprecatedDescription(ShapeType.OPERATION), equalTo("This operation is deprecated.")); + assertThat(deprecatedTrait.getDeprecatedDescription(ShapeType.STRING), equalTo("This shape is deprecated.")); + } + + @Test + public void returnDescriptionWhenMessageSet() { + DeprecatedTrait deprecatedTrait = DeprecatedTrait.builder().message("Use X shape instead.").build(); + assertThat(deprecatedTrait.getDeprecatedDescription(ShapeType.STRING), equalTo("This shape is deprecated: Use X shape instead.")); + } + + @Test + public void returnDescriptionWhenSinceSet() { + DeprecatedTrait deprecatedTrait = DeprecatedTrait.builder().since("2020-01-01").build(); + assertThat(deprecatedTrait.getDeprecatedDescription(ShapeType.STRING), equalTo("This shape is deprecated since 2020-01-01.")); + } + + @Test + public void returnDescriptionWhenBothSinceAndMessageSet() { + DeprecatedTrait deprecatedTrait = DeprecatedTrait.builder().since("2020-01-01").message("Use X shape instead.").build(); + assertThat(deprecatedTrait.getDeprecatedDescription(ShapeType.STRING), equalTo("This shape is deprecated since 2020-01-01: Use X shape instead.")); + } } diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiJsonSchemaMapperTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiJsonSchemaMapperTest.java index eb87b08b69d..6a1318e4be3 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiJsonSchemaMapperTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiJsonSchemaMapperTest.java @@ -43,6 +43,7 @@ import software.amazon.smithy.model.shapes.StringShape; import software.amazon.smithy.model.shapes.StructureShape; import software.amazon.smithy.model.traits.DeprecatedTrait; +import software.amazon.smithy.model.traits.DocumentationTrait; import software.amazon.smithy.model.traits.DynamicTrait; import software.amazon.smithy.model.traits.ExternalDocumentationTrait; import software.amazon.smithy.model.traits.SensitiveTrait; @@ -131,6 +132,26 @@ public void supportsDeprecatedTrait() { assertThat(document.getRootSchema().getExtension("deprecated").get(), equalTo(Node.from(true))); } + @Test + public void appendsDeprecatedInfoInDescription() { + String message = "Use a.b#D instead."; + String since = "2020-01-01"; + IntegerShape shape = IntegerShape.builder() + .id("a.b#C") + .addTrait(DeprecatedTrait.builder().message(message).since(since).build()) + .addTrait(new DocumentationTrait("This is an integer.")) + .build(); + Model model = Model.builder().addShape(shape).build(); + SchemaDocument document = JsonSchemaConverter.builder() + .addMapper(new OpenApiJsonSchemaMapper()) + .model(model) + .build() + .convertShape(shape); + + String expected = "This is an integer.\nThis shape is deprecated since 2020-01-01: Use a.b#D instead."; + assertThat(document.getRootSchema().getDescription().get(), equalTo(expected)); + } + @Test public void supportsInt32() { IntegerShape shape = IntegerShape.builder().id("a.b#C").build();