Skip to content

Conversation

@kai-ion
Copy link
Contributor

@kai-ion kai-ion commented Jan 13, 2026

Issue #, if available:

Description of changes:
Smithy-based code generator for paginators

Check all that applies:

  • Did a review by yourself.
  • Added proper tests to cover this PR. (If tests are not applicable, explain.)
  • Checked if this PR is a breaking (APIs have been changed) change.
  • Checked if this PR will not introduce cross-platform inconsistent behavior.
  • Checked if this PR would require a ReadMe/Wiki update.

Check which platforms you have built SDK on to verify the correctness of this PR.

  • Linux
  • Windows
  • Android
  • MacOS
  • IOS
  • Other Platforms

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@kai-ion kai-ion force-pushed the paginatorModel branch 6 times, most recently from 0fd0691 to 661e748 Compare January 23, 2026 15:24
implementation("software.amazon.smithy:smithy-aws-traits:1.51.0")
implementation("software.amazon.smithy:smithy-waiters:1.51.0")
implementation("software.amazon.smithy:smithy-rules-engine:1.51.0")
implementation("software.amazon.smithy:smithy-aws-endpoints:1.51.0")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this? It's not like we're going to be using smithy based endpoints rule traits right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this was from copying the pattern used in our codegen-workshop.
I will refactor the build script to use our existing pattern from smoke-test gen

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smithy actually needs all the above dependencies, in the current set up we are not accepting any unknown traits

@kai-ion kai-ion force-pushed the paginatorModel branch 6 times, most recently from 20097ca to 7433789 Compare February 3, 2026 18:26
Fix pagination traits generator for nested tokens
andle explicit nested tokens like "EngineDefaults.Marker" correctly
abbreviation and servicename mismatch
Backward compatibility map for operations that must use "SdkResult" suffix.
S3's ListParts operation has NextPartNumberMarker as integer in C2J but string in Smithy.
…hods for pagination, and smithy generator to make the base client templates. comment out the integration test. move the model traits into the service model dir instead of pagination dir

erated/src/aws-cpp-sdk-bedrock-agentcore-control/include/aws/bedrock-agentcore-control/model/CreateOnlineEvaluationConfigRequest.h
@kai-ion kai-ion force-pushed the paginatorModel branch 3 times, most recently from a426d02 to 03ae46d Compare February 5, 2026 19:49
namespace Aws {
namespace DynamoDB {

using ListContributorInsightsPaginator = Aws::Utils::Pagination::PagePaginator<DynamoDBClient, Model::ListContributorInsightsRequest,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets change PagePaginator to Paginator, unless you feel strongly about the name


namespace Aws {
namespace DynamoDB {
class DynamoDBClient;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of forward declaring DynamoDB why not have ScanPaginationTraits take a template parameter template <typename Client = ClientType> like you have on Invoke then the entire class is tempalted. You already pass DynamoDBClient as a template parameter in DynamoDBClientPagination.h

ListContributorInsightsPaginator(const Model::ListContributorInsightsRequest& request) {
return Aws::Utils::Pagination::PagePaginator<DerivedClient, Model::ListContributorInsightsRequest,
Pagination::ListContributorInsightsPaginationTraits>{
std::shared_ptr<DerivedClient>(static_cast<DerivedClient*>(this), [](DerivedClient*) {}), request};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::shared_ptr(static_cast<DerivedClient*>(this), {})

likely isnt what we want to be doing, you are creating a shared point from this then have a custom deleter [](DerivedClient*) {} that does nothing when delete is called. you are essentially trying to fit this into a shared pointer without using the actual properties of shared.

consider

#include <iostream>
#include <thread>

template<typename crtp_t>
class thing {
public:
  thing(crtp_t& ref) : ptr_(ref) {};
  void do_something() {
    ptr_.work();
  }
private:
  crtp_t& ptr_;
};

template <typename crtp_t>
class mixin {
 public:
  void operation() {
    thing<crtp_t> operation_thing{*static_cast<crtp_t*>(this)};
    operation_thing.do_something();
  }
};

class widget : public mixin<widget> {
public:
  void work() {
    std::cout << "hello from class\n";
  }
};

auto main() -> int {
  widget w{};
  w.operation();
  return 0;
}

which is long way of saying on PagePaginator make client a reference not a pointer


class ScanPaginationTest : public Aws::Testing::AwsCppSdkGTestSuite {
protected:
std::shared_ptr<DynamoDBClient> dynamoClient;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: why shared pointer and not stack varable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other integration test had similar pattern tests/aws-cpp-sdk-dynamodb-integration-tests/TableOperationTest.cpp in using shared pointer,

I will go ahead and use a stack variable here

print(f"Code generation done, (re)generated {len(done)} packages.") # Including defaults and partitions

# Format generated client code
generated_clients = [service for service in self.c2j_models.keys()]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this not needed in this code path anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, we moved the clang formatting to tools/scripts/run_code_generation.py so it can run after all files have been generated instead of just c2j generated codes

"cloudwatch-logs":"logs",
"directory-service":"ds",
"elasticsearch-service ":"es",
"elasticsearch-service":"es",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: whitespace change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original code had an inconsistency that made my custom parsing logic failed. I already fixed my custom parsing logic and went ahead to fix the inconsistency as well

var model = context.getModel();

// Handle legacy services without Smithy models
if (context.getProjectionName().endsWith(".mock")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how is ".mock" generated in the projection name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a small logic in tools/code-generation/smithy/cpp-codegen/build.gradle.kts that generates these projections that do not exist in smithy but does exist in coral so we can maintain backwards compatibility.

// Legacy services without full Smithy models - generate mock projections for base classes
        val legacyServices = mapOf("importexport" to "ImportExport", "sdb" to "SimpleDB", "s3-crt" to "S3Crt")
        legacyServices.forEach { (c2jName, serviceName) ->
            if (filteredServiceList.isEmpty() || c2jName in filteredServiceList) {
                val mockProjectionContents = Node.objectNodeBuilder()
                    .withMember("plugins", Node.objectNode()
                        .withMember("smithy-cpp-codegen", Node.objectNodeBuilder()
                            .withMember("c2jMap", Node.from(c2jMapStr))
                            .build()))
                    .build()
                projectionsBuilder.withMember("$c2jName.mock", mockProjectionContents)
            }

…dessed some nits

change codegen to create templated pagination traits instead of forward declaring
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants