Skip to content

Commit 0cc2193

Browse files
sichanyooSichan Yoo
andauthored
fix: Add documentation generation for operations. (#578)
* Add error info generation for operations. --------- Co-authored-by: Sichan Yoo <[email protected]>
1 parent bbc7e35 commit 0cc2193

File tree

8 files changed

+61
-4
lines changed

8 files changed

+61
-4
lines changed

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/ServiceGenerator.kt

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import software.amazon.smithy.model.Model
1212
import software.amazon.smithy.model.knowledge.OperationIndex
1313
import software.amazon.smithy.model.knowledge.TopDownIndex
1414
import software.amazon.smithy.model.shapes.OperationShape
15+
import software.amazon.smithy.model.shapes.ServiceShape
16+
import software.amazon.smithy.model.shapes.ShapeId
1517
import software.amazon.smithy.model.shapes.StructureShape
18+
import software.amazon.smithy.model.traits.DocumentationTrait
1619
import software.amazon.smithy.model.traits.StreamingTrait
1720
import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator
1821
import software.amazon.smithy.swift.codegen.model.toLowerCamelCase
@@ -40,6 +43,7 @@ class ServiceGenerator(
4043
*/
4144
fun renderOperationDefinition(
4245
model: Model,
46+
service: ServiceShape,
4347
symbolProvider: SymbolProvider,
4448
writer: SwiftWriter,
4549
opIndex: OperationIndex,
@@ -56,8 +60,7 @@ class ServiceGenerator(
5660
val outputShape = opIndex.getOutput(op).get()
5761
val outputShapeName = symbolProvider.toSymbol(outputShape).name
5862

59-
writer.writeShapeDocs(op)
60-
writer.writeAvailableAttribute(model, op)
63+
renderOperationDoc(model, service, op, writer)
6164

6265
val accessSpecifier = if (insideProtocol) "" else "public "
6366

@@ -68,6 +71,42 @@ class ServiceGenerator(
6871
outputShapeName
6972
)
7073
}
74+
75+
/**
76+
* Helper method for generating in-line documentation for operation
77+
*/
78+
private fun renderOperationDoc(model: Model, service: ServiceShape, op: OperationShape, writer: SwiftWriter) {
79+
writer.writeShapeDocs(op)
80+
writer.writeAvailableAttribute(model, op)
81+
82+
fun writeEmptyLine() {
83+
writer.writeSingleLineDocs { write("") }
84+
}
85+
86+
writeEmptyLine()
87+
writer.writeDocs("\\- Parameter ${op.inputShape.name} : ${retrieveMemberShapeDoc(op.inputShape, model)}")
88+
89+
writeEmptyLine()
90+
writer.writeDocs("\\- Returns: \\`${op.outputShape.name}\\` : ${retrieveMemberShapeDoc(op.outputShape, model)}")
91+
92+
if (op.getErrors(service).isNotEmpty()) {
93+
writeEmptyLine()
94+
writer.writeSingleLineDocs { write("- Throws: One of the exceptions listed below __Possible Exceptions__.") }
95+
writeEmptyLine()
96+
writer.writeSingleLineDocs { write("__Possible Exceptions:__") }
97+
op.getErrors(service).forEach { error ->
98+
writer.writeDocs("\\- \\`${error.name}\\` : ${retrieveMemberShapeDoc(error.toShapeId(), model)}")
99+
}
100+
}
101+
}
102+
103+
/**
104+
* Helper method to grab documentation for operation's member shapes (input, output, error(s)
105+
*/
106+
private fun retrieveMemberShapeDoc(shapeId: ShapeId, model: Model): String {
107+
val docTrait = model.getShape(shapeId).get().getTrait(DocumentationTrait::class.java).getOrNull()
108+
return docTrait?.value ?: "[no documentation found]"
109+
}
71110
}
72111

73112
fun render() {
@@ -118,7 +157,7 @@ class ServiceGenerator(
118157
writer.openBlock("public protocol ${serviceSymbol.name}Protocol {")
119158
.call {
120159
operations.forEach { op ->
121-
renderOperationDefinition(model, symbolProvider, writer, operationsIndex, op, true)
160+
renderOperationDefinition(model, service, symbolProvider, writer, operationsIndex, op, true)
122161
}
123162
}
124163
.closeBlock("}")

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/HttpProtocolClientGenerator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ open class HttpProtocolClientGenerator(
5050

5151
writer.openBlock("extension ${serviceSymbol.name}: ${serviceSymbol.name}Protocol {", "}") {
5252
operations.forEach {
53-
ServiceGenerator.renderOperationDefinition(model, symbolProvider, writer, operationsIndex, it)
53+
ServiceGenerator.renderOperationDefinition(model, serviceShape, symbolProvider, writer, operationsIndex, it)
5454
writer.openBlock("{", "}") {
5555
val operationStackName = "operation"
5656
val generator = MiddlewareExecutionGenerator(ctx, writer, httpBindingResolver, httpProtocolCustomizable, operationMiddleware, operationStackName)

smithy-swift-codegen/src/test/kotlin/ContentMd5MiddlewareTests.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ class ContentMd5MiddlewareTests {
99
val expectedContents =
1010
"""
1111
extension RestXmlProtocolClient: RestXmlProtocolClientProtocol {
12+
/// This is a very cool operation.
13+
///
14+
/// - Parameter IdempotencyTokenWithStructureInput : [no documentation found]
15+
///
16+
/// - Returns: `IdempotencyTokenWithStructureOutputResponse` : [no documentation found]
1217
public func idempotencyTokenWithStructure(input: IdempotencyTokenWithStructureInput) async throws -> IdempotencyTokenWithStructureOutputResponse
1318
{
1419
let context = ClientRuntime.HttpContextBuilder()

smithy-swift-codegen/src/test/kotlin/HttpProtocolClientGeneratorTests.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ class HttpProtocolClientGeneratorTests {
107107
contents.shouldSyntacticSanityCheck()
108108
val expected = """
109109
extension RestJsonProtocolClient: RestJsonProtocolClientProtocol {
110+
/// This is a very cool operation.
111+
///
112+
/// - Parameter AllocateWidgetInput : [no documentation found]
113+
///
114+
/// - Returns: `AllocateWidgetOutputResponse` : [no documentation found]
110115
public func allocateWidget(input: AllocateWidgetInput) async throws -> AllocateWidgetOutputResponse
111116
{
112117
let context = ClientRuntime.HttpContextBuilder()

smithy-swift-codegen/src/test/kotlin/IdempotencyTokenTraitTests.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ class IdempotencyTokenTraitTests {
99
val expectedContents =
1010
"""
1111
extension RestXmlProtocolClient: RestXmlProtocolClientProtocol {
12+
/// This is a very cool operation.
13+
///
14+
/// - Parameter IdempotencyTokenWithStructureInput : [no documentation found]
15+
///
16+
/// - Returns: `IdempotencyTokenWithStructureOutputResponse` : [no documentation found]
1217
public func idempotencyTokenWithStructure(input: IdempotencyTokenWithStructureInput) async throws -> IdempotencyTokenWithStructureOutputResponse
1318
{
1419
let context = ClientRuntime.HttpContextBuilder()

smithy-swift-codegen/src/test/resources/Isolated/contentmd5checksum.smithy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ service RestXml {
1515
]
1616
}
1717

18+
@documentation("This is a very cool operation.")
1819
@httpChecksumRequired
1920
@http(uri: "/IdempotencyTokenWithStructure", method: "PUT")
2021
operation IdempotencyTokenWithStructure {

smithy-swift-codegen/src/test/resources/Isolated/idempotencyToken.smithy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ service RestXml {
1616
}
1717

1818
@http(uri: "/IdempotencyTokenWithStructure", method: "PUT")
19+
@documentation("This is a very cool operation.")
1920
operation IdempotencyTokenWithStructure {
2021
input: IdempotencyToken,
2122
}

smithy-swift-codegen/src/test/resources/service-generator-test-operations.smithy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ operation GetFooStreamingInputNoOutput {
8080
}
8181

8282
// https://awslabs.github.io/smithy/1.0/spec/core/behavior-traits.html#idempotencytoken-trait
83+
@documentation("This is a very cool operation.")
8384
@http(method: "POST", uri: "/input/AllocateWidget")
8485
operation AllocateWidget {
8586
input: AllocateWidgetInput

0 commit comments

Comments
 (0)