@@ -11,12 +11,14 @@ import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
1111import software.amazon.smithy.kotlin.codegen.core.RuntimeTypes
1212import software.amazon.smithy.kotlin.codegen.core.withBlock
1313import software.amazon.smithy.kotlin.codegen.utils.dq
14+ import software.amazon.smithy.model.shapes.ShapeId
15+ import software.amazon.smithy.model.shapes.StructureShape
1416import software.amazon.smithy.waiters.*
1517
1618/* *
1719 * Renders an individual acceptor for a waiter.
1820 */
19- private fun KotlinWriter.renderAcceptor (acceptor : Acceptor ) {
21+ private fun KotlinWriter.renderAcceptor (wi : WaiterInfo , acceptor : Acceptor ) {
2022 addImport(RuntimeTypes .Core .Retries .Policy .RetryDirective )
2123
2224 val directive = when (acceptor.state!! ) {
@@ -39,8 +41,8 @@ private fun KotlinWriter.renderAcceptor(acceptor: Acceptor) {
3941 write(" ErrorTypeAcceptor(RetryDirective.#L, #L)," , directive, matcher.value.dq())
4042 }
4143
42- is Matcher .InputOutputMember -> renderPathAcceptor(directive, true , matcher.value)
43- is Matcher .OutputMember -> renderPathAcceptor(directive, false , matcher.value)
44+ is Matcher .InputOutputMember -> renderPathAcceptor(wi, directive, true , matcher.value)
45+ is Matcher .OutputMember -> renderPathAcceptor(wi, directive, false , matcher.value)
4446 else -> throw CodegenException (""" Unknown matcher type "${matcher::class } """" )
4547 }
4648}
@@ -58,38 +60,49 @@ internal fun KotlinWriter.renderAcceptorList(wi: WaiterInfo, asValName: String)
5860 wi.inputSymbol,
5961 wi.outputSymbol,
6062 ) {
61- wi.waiter.acceptors.forEach(:: renderAcceptor)
63+ wi.waiter.acceptors.forEach { renderAcceptor(wi, it) }
6264 }
6365}
6466
6567/* *
6668 * Render a path-based acceptor (i.e., one that uses an output or inputOutput matcher).
6769 */
68- private fun KotlinWriter.renderPathAcceptor (directive : String , includeInput : Boolean , matcher : PathMatcher ) {
70+ private fun KotlinWriter.renderPathAcceptor (wi : WaiterInfo , directive : String , includeInput : Boolean , matcher : PathMatcher ) {
6971 val acceptorType = if (includeInput) {
70- addImport(RuntimeTypes .Core .Retries .Policy .InputOutputAcceptor )
71- " InputOutputAcceptor"
72+ RuntimeTypes .Core .Retries .Policy .InputOutputAcceptor
7273 } else {
73- addImport(RuntimeTypes .Core .Retries .Policy .OutputAcceptor )
74- " OutputAcceptor"
74+ RuntimeTypes .Core .Retries .Policy .OutputAcceptor
7575 }
7676
77- withBlock(" #L(RetryDirective.#L) {" , " }," , acceptorType, directive) {
78- val visitor = KotlinJmespathExpressionVisitor (this )
77+ val visitedShape = if (includeInput) {
78+ buildSyntheticInputOutputShape(wi.op.id.name, wi.input.id, wi.output.id)
79+ } else {
80+ wi.output
81+ }
82+
83+ withBlock(" #T(RetryDirective.#L) {" , " }," , acceptorType, directive) {
84+ val visitor = KotlinJmespathExpressionVisitor (wi.ctx, this , visitedShape)
7985 val expression = JmespathExpression .parse(matcher.path)
8086 val actual = expression.accept(visitor)
8187
8288 val expected = matcher.expected
8389 val comparison = when (matcher.comparator!! ) {
84- PathComparator .STRING_EQUALS -> " $actual ?.toString() == ${expected.dq()} "
85- PathComparator .BOOLEAN_EQUALS -> " $actual == ${expected.toBoolean()} "
86- PathComparator .ANY_STRING_EQUALS -> " $actual ?.any { it?.toString() == ${expected.dq()} } ?: false"
90+ PathComparator .STRING_EQUALS -> " ${ actual.identifier} == ${expected.dq()} "
91+ PathComparator .BOOLEAN_EQUALS -> " ${ actual.identifier} == ${expected.toBoolean()} "
92+ PathComparator .ANY_STRING_EQUALS -> " ${ actual.identifier} ?.any { it == ${expected.dq()} } ?: false"
8793
88- // NOTE: the size > 0 check is necessary because the waiter spec says that `allStringEquals` requires
94+ // NOTE: the isNotEmpty check is necessary because the waiter spec says that `allStringEquals` requires
8995 // at least one value unlike Kotlin's `all` which returns true if the collection is empty
9096 PathComparator .ALL_STRING_EQUALS ->
91- " $actual != null && $ actual .size > 0 && $actual .all { it?.toString() == ${expected.dq()} }"
97+ " ! ${ actual.identifier} .isNullOrEmpty() && ${ actual.identifier} . all { it == ${expected.dq()} }"
9298 }
9399 write(comparison)
94100 }
95101}
102+
103+ private fun buildSyntheticInputOutputShape (opName : String , input : ShapeId , output : ShapeId ): StructureShape =
104+ StructureShape .Builder ()
105+ .id(" software.amazon.smithy.kotlin.codegen.rendering.waiters.synthetic#${opName} RequestResponse" )
106+ .addMember(" input" , input)
107+ .addMember(" output" , output)
108+ .build()
0 commit comments