diff --git a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverter.java b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverter.java index 1ecd209160d..2fae2eb2de8 100644 --- a/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverter.java +++ b/smithy-openapi/src/main/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverter.java @@ -432,6 +432,12 @@ private void addPaths( } // Add security requirements to the operation. addOperationSecurity(context, result.getOperation(), shape, plugin); + + // Add the documentation trait to the operation if present. + shape.getTrait(DocumentationTrait.class) + .map(DocumentationTrait::getValue) + .ifPresent(description -> result.getOperation().description(description)); + // Pass the operation through the plugin system and then build it. OperationObject builtOperation = plugin.updateOperation( context, shape, result.getOperation().build(), method, path); diff --git a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverterTest.java b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverterTest.java index ad08da8824e..05fee7e3309 100644 --- a/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverterTest.java +++ b/smithy-openapi/src/test/java/software/amazon/smithy/openapi/fromsmithy/OpenApiConverterTest.java @@ -423,4 +423,20 @@ public void convertsUnions() { Node.assertEquals(result, expectedNode); } + + @Test + public void convertsDocumentation() { + Model model = Model.assembler() + .addImport(getClass().getResource("documentation-test.smithy")) + .discoverModels() + .assemble() + .unwrap(); + OpenApiConfig config = new OpenApiConfig(); + config.setService(ShapeId.from("smithy.example#MyDocs")); + Node result = OpenApiConverter.create().config(config).convertToNode(model); + Node expectedNode = Node.parse(IoUtils.toUtf8String( + getClass().getResourceAsStream("documentation-test.openapi.json"))); + + Node.assertEquals(result, expectedNode); + } } diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/documentation-test.openapi.json b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/documentation-test.openapi.json new file mode 100644 index 00000000000..c897b5541a4 --- /dev/null +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/documentation-test.openapi.json @@ -0,0 +1,54 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "MyDocs", + "version": "2018-01-01", + "description": "Service" + }, + "paths": { + "/": { + "get": { + "description": "Operation", + "operationId": "MyDocsOperation", + "responses": { + "200": { + "description": "MyDocsOperation 200 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MyDocsOperationResponseContent" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "MyDocsOperationResponseContent": { + "type": "object", + "description": "Output", + "properties": { + "foo": { + "type": "string", + "description": "foo member." + }, + "nested": { + "$ref": "#/components/schemas/Nested" + } + } + }, + "Nested": { + "type": "object", + "description": "Nested", + "properties": { + "baz": { + "type": "string" + } + } + } + } + } +} diff --git a/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/documentation-test.smithy b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/documentation-test.smithy new file mode 100644 index 00000000000..3236a6995b2 --- /dev/null +++ b/smithy-openapi/src/test/resources/software/amazon/smithy/openapi/fromsmithy/documentation-test.smithy @@ -0,0 +1,34 @@ +namespace smithy.example + +/// Service +@aws.protocols#restJson1 +service MyDocs { + version: "2018-01-01", + operations: [MyDocsOperation] +} + +/// Operation +@http(method: "GET", uri: "/") +@readonly +operation MyDocsOperation { + output: Output +} + +/// Output +structure Output { + /// foo member. + foo: String, + + /// Note: these member docs are ignored and instead only the documentation + /// on the targeted structure is present in the output. This is because our + /// users have told us that it's more important to reuse structure definitions + /// than it is to have 100% fidelity with the original Smithy model. In a + /// previous implementation, we created a unique named shape for every member, + /// but this results in no shape reuse across the generated OpenAPI model. + nested: Nested, +} + +/// Nested +structure Nested { + baz: String, +}