@@ -263,6 +263,130 @@ class PaginatorGeneratorTest {
263263 actual.shouldContainOnlyOnceWithDiff(expectedImports)
264264 }
265265
266+ @Test
267+ fun testRenderPaginatorWithItemRequiringFullName () {
268+ val testModelWithItems = """
269+ namespace com.test
270+
271+ use aws.protocols#restJson1
272+
273+ service FlowService {
274+ operations: [ListFlows]
275+ }
276+
277+ @paginated(
278+ inputToken: "Marker",
279+ outputToken: "NextMarker",
280+ pageSize: "MaxItems",
281+ items: "Flows"
282+ )
283+ @readonly
284+ @http(method: "GET", uri: "/flows", code: 200)
285+ operation ListFlows {
286+ input: ListFlowsRequest,
287+ output: ListFlowsResponse
288+ }
289+
290+ structure ListFlowsRequest {
291+ @httpQuery("FlowVersion")
292+ FlowVersion: String,
293+ @httpQuery("Marker")
294+ Marker: String,
295+ @httpQuery("MasterRegion")
296+ MasterRegion: String,
297+ @httpQuery("MaxItems")
298+ MaxItems: Integer
299+ }
300+
301+ structure ListFlowsResponse {
302+ Flows: FlowList,
303+ NextMarker: String
304+ }
305+
306+ list FlowList {
307+ member: Flow
308+ }
309+
310+ structure Flow {
311+ Name: String
312+ }
313+ """ .toSmithyModel()
314+ val testContextWithItems = testModelWithItems.newTestContext(" FlowService" , " com.test" )
315+
316+ val codegenContextWithItems = object : CodegenContext {
317+ override val model: Model = testContextWithItems.generationCtx.model
318+ override val symbolProvider: SymbolProvider = testContextWithItems.generationCtx.symbolProvider
319+ override val settings: KotlinSettings = testContextWithItems.generationCtx.settings
320+ override val protocolGenerator: ProtocolGenerator = testContextWithItems.generator
321+ override val integrations: List <KotlinIntegration > = testContextWithItems.generationCtx.integrations
322+ }
323+
324+ val unit = PaginatorGenerator ()
325+ unit.writeAdditionalFiles(codegenContextWithItems, testContextWithItems.generationCtx.delegator)
326+
327+ testContextWithItems.generationCtx.delegator.flushWriters()
328+ val testManifest = testContextWithItems.generationCtx.delegator.fileManifest as MockManifest
329+ val actual = testManifest.expectFileString(" src/main/kotlin/com/test/paginators/Paginators.kt" )
330+
331+ val expectedCode = """
332+ /**
333+ * Paginate over [ListFlowsResponse] results.
334+ *
335+ * When this operation is called, a [kotlinx.coroutines.Flow] is created. Flows are lazy (cold) so no service
336+ * calls are made until the flow is collected. This also means there is no guarantee that the request is valid
337+ * until then. Once you start collecting the flow, the SDK will lazily load response pages by making service
338+ * calls until there are no pages left or the flow is cancelled. If there are errors in your request, you will
339+ * see the failures only after you start collection.
340+ * @param initialRequest A [ListFlowsRequest] to start pagination
341+ * @return A [kotlinx.coroutines.flow.Flow] that can collect [ListFlowsResponse]
342+ */
343+ public fun TestClient.listFlowsPaginated(initialRequest: ListFlowsRequest = ListFlowsRequest { }): kotlinx.coroutines.flow.Flow<ListFlowsResponse> =
344+ flow {
345+ var cursor: kotlin.String? = initialRequest.marker
346+ var hasNextPage: Boolean = true
347+
348+ while (hasNextPage) {
349+ val req = initialRequest.copy {
350+ this.marker = cursor
351+ }
352+ val result = [email protected] (req) 353+ cursor = result.nextMarker
354+ hasNextPage = cursor?.isNotEmpty() == true
355+ emit(result)
356+ }
357+ }
358+
359+ /**
360+ * Paginate over [ListFlowsResponse] results.
361+ *
362+ * When this operation is called, a [kotlinx.coroutines.Flow] is created. Flows are lazy (cold) so no service
363+ * calls are made until the flow is collected. This also means there is no guarantee that the request is valid
364+ * until then. Once you start collecting the flow, the SDK will lazily load response pages by making service
365+ * calls until there are no pages left or the flow is cancelled. If there are errors in your request, you will
366+ * see the failures only after you start collection.
367+ * @param block A builder block used for DSL-style invocation of the operation
368+ * @return A [kotlinx.coroutines.flow.Flow] that can collect [ListFlowsResponse]
369+ */
370+ public fun TestClient.listFlowsPaginated(block: ListFlowsRequest.Builder.() -> Unit): kotlinx.coroutines.flow.Flow<ListFlowsResponse> =
371+ listFlowsPaginated(ListFlowsRequest.Builder().apply(block).build())
372+
373+ /**
374+ * This paginator transforms the flow returned by [listFlowsPaginated]
375+ * to access the nested member [Flow]
376+ * @return A [kotlinx.coroutines.flow.Flow] that can collect [Flow]
377+ */
378+ @JvmName("listFlowsResponseFlow")
379+ public fun kotlinx.coroutines.flow.Flow<ListFlowsResponse>.flows(): kotlinx.coroutines.flow.Flow<Flow> =
380+ transform() { response ->
381+ response.flows?.forEach {
382+ emit(it)
383+ }
384+ }
385+ """ .trimIndent()
386+
387+ actual.shouldContainOnlyOnceWithDiff(expectedCode)
388+ }
389+
266390 @Test
267391 fun testRenderPaginatorWithSparseItem () {
268392 val testModelWithItems = """
0 commit comments