From bd04a63e076debd3de3e551361a64ea864ddce08 Mon Sep 17 00:00:00 2001 From: kai lin Date: Tue, 13 Jan 2026 14:44:20 -0500 Subject: [PATCH 01/19] Smithy code gen for pagination --- .../include/aws/s3/S3ClientPagination.h | 25 +++++ .../pagination/ListBucketsPaginationTraits.h | 44 +++++++++ .../ListDirectoryBucketsPaginationTraits.h | 44 +++++++++ .../ListObjectsV2PaginationTraits.h | 44 +++++++++ .../pagination/ListPartsPaginationTraits.h | 44 +++++++++ .../cpp-pagination-codegen/build.gradle.kts | 17 ++++ .../awsclientsmithygenerator/CppWriter.java | 38 ++++++++ .../CppWriterDelegator.java | 37 +++++++ .../generators/PaginationCodegenPlugin.java | 22 +++++ .../generators/PaginationData.java | 32 ++++++ .../generators/PaginationHeaderWriter.java | 97 +++++++++++++++++++ .../generators/PaginationParser.java | 60 ++++++++++++ .../generators/PaginationShapeDiscovery.java | 37 +++++++ .../templates/PaginationClientTemplate.java | 71 ++++++++++++++ ...ware.amazon.smithy.build.SmithyBuildPlugin | 1 + .../codegen/cpp-pagination/build.gradle.kts | 77 +++++++++++++++ .../codegen/cpp-pagination/smithy-build.json | 16 +++ .../smithy/codegen/settings.gradle.kts | 2 + tools/scripts/codegen/pagination_gen.py | 95 ++++++++++++++++++ tools/scripts/run_code_generation.py | 8 ++ 20 files changed, 811 insertions(+) create mode 100644 generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h create mode 100644 generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h create mode 100644 generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h create mode 100644 generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h create mode 100644 generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/build.gradle.kts create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriter.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriterDelegator.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationShapeDiscovery.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/resources/META-INF/services/software.amazon.smithy.build.SmithyBuildPlugin create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination/build.gradle.kts create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination/smithy-build.json create mode 100644 tools/scripts/codegen/pagination_gen.py diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h new file mode 100644 index 00000000000..ff25ee95d87 --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h @@ -0,0 +1,25 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include +#include +#include + +namespace Aws +{ +namespace S3 +{ + +using ListBucketsPaginator = Aws::Utils::Pagination::PagePaginator; +using ListDirectoryBucketsPaginator = Aws::Utils::Pagination::PagePaginator; +using ListObjectsV2Paginator = Aws::Utils::Pagination::PagePaginator; +using ListPartsPaginator = Aws::Utils::Pagination::PagePaginator; + +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h new file mode 100644 index 00000000000..5e180a9499c --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h @@ -0,0 +1,44 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws +{ +namespace S3 +{ +namespace Pagination +{ + +struct ListBucketsPaginationTraits +{ + using RequestType = Model::ListBucketsRequest; + using ResultType = Model::ListBucketsResult; + using OutcomeType = Model::ListBucketsOutcome; + using ClientType = S3Client; + + static OutcomeType Invoke(ClientType& client, const RequestType& request) + { + return client.ListBuckets(request); + } + + static bool HasMoreResults(const ResultType& result) + { + return result.GetIsTruncated(); + } + + static void SetNextRequest(const ResultType& result, RequestType& request) + { + request.SetContinuationToken(result.GetContinuationToken()); + } +}; + +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h new file mode 100644 index 00000000000..70e0a73c0ff --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h @@ -0,0 +1,44 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws +{ +namespace S3 +{ +namespace Pagination +{ + +struct ListDirectoryBucketsPaginationTraits +{ + using RequestType = Model::ListDirectoryBucketsRequest; + using ResultType = Model::ListDirectoryBucketsResult; + using OutcomeType = Model::ListDirectoryBucketsOutcome; + using ClientType = S3Client; + + static OutcomeType Invoke(ClientType& client, const RequestType& request) + { + return client.ListDirectoryBuckets(request); + } + + static bool HasMoreResults(const ResultType& result) + { + return result.GetIsTruncated(); + } + + static void SetNextRequest(const ResultType& result, RequestType& request) + { + request.SetContinuationToken(result.GetContinuationToken()); + } +}; + +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h new file mode 100644 index 00000000000..14f2129b449 --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h @@ -0,0 +1,44 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws +{ +namespace S3 +{ +namespace Pagination +{ + +struct ListObjectsV2PaginationTraits +{ + using RequestType = Model::ListObjectsV2Request; + using ResultType = Model::ListObjectsV2Result; + using OutcomeType = Model::ListObjectsV2Outcome; + using ClientType = S3Client; + + static OutcomeType Invoke(ClientType& client, const RequestType& request) + { + return client.ListObjectsV2(request); + } + + static bool HasMoreResults(const ResultType& result) + { + return result.GetIsTruncated(); + } + + static void SetNextRequest(const ResultType& result, RequestType& request) + { + request.SetContinuationToken(result.GetNextContinuationToken()); + } +}; + +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h new file mode 100644 index 00000000000..d1d78792e6d --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h @@ -0,0 +1,44 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws +{ +namespace S3 +{ +namespace Pagination +{ + +struct ListPartsPaginationTraits +{ + using RequestType = Model::ListPartsRequest; + using ResultType = Model::ListPartsResult; + using OutcomeType = Model::ListPartsOutcome; + using ClientType = S3Client; + + static OutcomeType Invoke(ClientType& client, const RequestType& request) + { + return client.ListParts(request); + } + + static bool HasMoreResults(const ResultType& result) + { + return result.GetIsTruncated(); + } + + static void SetNextRequest(const ResultType& result, RequestType& request) + { + request.SetPartNumberMarker(result.GetNextPartNumberMarker()); + } +}; + +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/build.gradle.kts b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/build.gradle.kts new file mode 100644 index 00000000000..70081533b3e --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + `java-library` +} + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation("software.amazon.smithy:smithy-model:1.51.0") + implementation("software.amazon.smithy:smithy-codegen-core:1.51.0") + 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") +} diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriter.java new file mode 100644 index 00000000000..9317bc0655a --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriter.java @@ -0,0 +1,38 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator; + +import java.util.function.Consumer; + +public class CppWriter { + private final StringBuilder content = new StringBuilder(); + + public void write(String text, Object... args) { + content.append(String.format(text, args)).append("\n"); + } + + public void openBlock(String opener, String closer, Consumer block) { + write(opener); + block.accept(null); + write(closer); + } + + public void writeInclude(String header) { + write("#include <%s>", header); + } + + public void writeNamespaceOpen(String namespace) { + write("namespace %s\n{", namespace); + } + + public void writeNamespaceClose(String namespace) { + write("} // namespace %s", namespace); + } + + @Override + public String toString() { + return content.toString(); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriterDelegator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriterDelegator.java new file mode 100644 index 00000000000..d2adb93fdc2 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriterDelegator.java @@ -0,0 +1,37 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator; + +import software.amazon.smithy.build.FileManifest; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +public class CppWriterDelegator { + private final FileManifest fileManifest; + private final Map writers = new HashMap<>(); + + public CppWriterDelegator(FileManifest fileManifest) { + this.fileManifest = fileManifest; + } + + public void useFileWriter(String filename, Consumer writerConsumer) { + CppWriter writer = writers.computeIfAbsent(filename, k -> new CppWriter()); + writerConsumer.accept(writer); + } + + public void flushWriters() { + writers.forEach((filename, writer) -> { + try { + Path outputPath = fileManifest.getBaseDir().resolve(filename); + java.nio.file.Files.createDirectories(outputPath.getParent()); + java.nio.file.Files.writeString(outputPath, writer.toString()); + } catch (Exception e) { + throw new RuntimeException("Failed to write file: " + filename, e); + } + }); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java new file mode 100644 index 00000000000..d28917359c1 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java @@ -0,0 +1,22 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.build.SmithyBuildPlugin; + +public class PaginationCodegenPlugin implements SmithyBuildPlugin { + + @Override + public String getName() { + return "cpp-codegen-pagination-plugin"; + } + + @Override + public void execute(PluginContext context) { + PaginationParser parser = new PaginationParser(context); + parser.run(); + } +} diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java new file mode 100644 index 00000000000..d17d7718d86 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java @@ -0,0 +1,32 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.model.traits.PaginatedTrait; + +public class PaginationData { + private final OperationShape operation; + private final PaginatedTrait trait; + private final ServiceShape service; + + public PaginationData(OperationShape operation, PaginatedTrait trait, ServiceShape service) { + this.operation = operation; + this.trait = trait; + this.service = service; + } + + public OperationShape getOperation() { + return operation; + } + + public PaginatedTrait getTrait() { + return trait; + } + + public ServiceShape getService() { + return service; + } +} diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java new file mode 100644 index 00000000000..a72b357a328 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java @@ -0,0 +1,97 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.codegen.core.SymbolProvider; +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.model.traits.PaginatedTrait; +import software.amazon.smithy.aws.traits.ServiceTrait; +import java.nio.file.*; +import java.util.*; + +public class PaginationHeaderWriter { + private final PluginContext context; + private final ServiceShape service; + private final List paginatedOps; + + public PaginationHeaderWriter(PluginContext context, ServiceShape service, List paginatedOps) { + this.context = context; + this.service = service; + this.paginatedOps = paginatedOps; + } + + public void write() { + String serviceName = service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .replace(" ", "") + .replace("-", ""); + Path outputPath = context.getFileManifest().getBaseDir() + .resolve("include/aws/" + serviceName.toLowerCase() + "/model/pagination"); + + for (PaginationData data : paginatedOps) { + String content = generateTraitsHeader(data, serviceName); + String fileName = data.getOperation().getId().getName() + "PaginationTraits.h"; + + try { + Files.createDirectories(outputPath); + Files.writeString(outputPath.resolve(fileName), content); + } catch (Exception e) { + throw new RuntimeException("Failed to write pagination traits header", e); + } + } + } + + private String generateTraitsHeader(PaginationData data, String serviceName) { + OperationShape op = data.getOperation(); + PaginatedTrait trait = data.getTrait(); + String opName = op.getId().getName(); + + StringBuilder sb = new StringBuilder(); + sb.append("/**\n"); + sb.append(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n"); + sb.append(" * SPDX-License-Identifier: Apache-2.0.\n"); + sb.append(" */\n\n"); + sb.append("#pragma once\n"); + sb.append("#include \n"); + sb.append("#include \n"); + sb.append("#include \n"); + sb.append("#include \n\n"); + sb.append("namespace Aws\n{\nnamespace ").append(serviceName).append("\n{\nnamespace Pagination\n{\n\n"); + sb.append("struct ").append(opName).append("PaginationTraits\n{\n"); + sb.append(" using RequestType = Model::").append(opName).append("Request;\n"); + sb.append(" using ResultType = Model::").append(opName).append("Result;\n"); + sb.append(" using OutcomeType = Model::").append(opName).append("Outcome;\n"); + sb.append(" using ClientType = ").append(serviceName).append("Client;\n\n"); + + sb.append(" static OutcomeType Invoke(ClientType& client, const RequestType& request)\n {\n"); + sb.append(" return client.").append(opName).append("(request);\n }\n\n"); + + sb.append(" static bool HasMoreResults(const ResultType& result)\n {\n"); + // Check if there's a truncated field first, otherwise fall back to token check + sb.append(" return result.GetIsTruncated();\n"); + sb.append(" }\n\n"); + + sb.append(" static void SetNextRequest(const ResultType& result, RequestType& request)\n {\n"); + if (trait.getInputToken().isPresent() && trait.getOutputToken().isPresent()) { + String inToken = trait.getInputToken().get(); + String outToken = trait.getOutputToken().get(); + sb.append(" request.Set").append(capitalize(inToken)).append("(result.Get").append(capitalize(outToken)).append("());\n"); + } + sb.append(" }\n"); + + sb.append("};\n\n"); + sb.append("} // namespace Pagination\n"); + sb.append("} // namespace ").append(serviceName).append("\n"); + sb.append("} // namespace Aws\n"); + + return sb.toString(); + } + + private String capitalize(String str) { + return str.substring(0, 1).toUpperCase() + str.substring(1); + } +} diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java new file mode 100644 index 00000000000..f88dcfc1cdf --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java @@ -0,0 +1,60 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.aws.traits.ServiceTrait; +import com.amazonaws.util.awsclientsmithygenerator.CppWriterDelegator; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationClientTemplate; +import java.util.*; + +public class PaginationParser { + private final PluginContext context; + private final Model model; + private final PaginationShapeDiscovery shapeDiscovery; + private final CppWriterDelegator writerDelegator; + + public PaginationParser(PluginContext context) { + this.context = context; + this.model = context.getModel(); + this.shapeDiscovery = new PaginationShapeDiscovery(model); + this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); + } + + public void run() { + for (ServiceShape service : model.getServiceShapes()) { + List paginatedOps = shapeDiscovery.findPaginatedOperations(service); + + if (!paginatedOps.isEmpty()) { + generatePaginationFiles(service, paginatedOps); + } + } + writerDelegator.flushWriters(); + } + + private void generatePaginationFiles(ServiceShape service, List paginatedOps) { + String serviceName = getServiceName(service); + + // Generate client pagination header + writerDelegator.useFileWriter( + "include/aws/" + serviceName.toLowerCase() + "/" + serviceName + "ClientPagination.h", + writer -> new PaginationClientTemplate(service, paginatedOps).render(writer) + ); + + // Generate pagination traits headers + PaginationHeaderWriter headerWriter = new PaginationHeaderWriter(context, service, paginatedOps); + headerWriter.write(); + } + + private String getServiceName(ServiceShape service) { + return service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .replace(" ", "") + .replace("-", ""); + } +} diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationShapeDiscovery.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationShapeDiscovery.java new file mode 100644 index 00000000000..14f5b67c143 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationShapeDiscovery.java @@ -0,0 +1,37 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.model.traits.PaginatedTrait; +import java.util.*; +import java.util.stream.Collectors; + +public class PaginationShapeDiscovery { + private final Model model; + + public PaginationShapeDiscovery(Model model) { + this.model = model; + } + + public List findPaginatedOperations(ServiceShape service) { + return service.getOperations().stream() + .map(id -> model.expectShape(id, OperationShape.class)) + .filter(op -> op.hasTrait(PaginatedTrait.class)) + .map(op -> new PaginationData(op, op.expectTrait(PaginatedTrait.class), service)) + .collect(Collectors.toList()); + } + + public Set getReferencedStructures(List paginatedOps) { + Set structures = new HashSet<>(); + for (PaginationData data : paginatedOps) { + OperationShape op = data.getOperation(); + structures.add(model.expectShape(op.getInputShape(), StructureShape.class)); + structures.add(model.expectShape(op.getOutputShape(), StructureShape.class)); + } + return structures; + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java new file mode 100644 index 00000000000..23ad0d4157c --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java @@ -0,0 +1,71 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.templates; + +import com.amazonaws.util.awsclientsmithygenerator.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.PaginationData; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.aws.traits.ServiceTrait; +import java.util.List; + +public class PaginationClientTemplate { + private final ServiceShape service; + private final List paginatedOps; + + public PaginationClientTemplate(ServiceShape service, List paginatedOps) { + this.service = service; + this.paginatedOps = paginatedOps; + } + + public void render(CppWriter writer) { + String serviceName = getServiceName(); + + // Header and includes + writer.write("/**"); + writer.write(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved."); + writer.write(" * SPDX-License-Identifier: Apache-2.0."); + writer.write(" */"); + writer.write(""); + writer.write("#pragma once"); + + renderIncludes(writer, serviceName); + renderNamespaces(writer, serviceName); + } + + private void renderIncludes(CppWriter writer, String serviceName) { + writer.writeInclude("aws/" + serviceName.toLowerCase() + "/" + serviceName + "Client.h"); + writer.writeInclude("aws/core/utils/pagination/Paginator.h"); + + for (PaginationData data : paginatedOps) { + String opName = data.getOperation().getId().getName(); + writer.writeInclude("aws/" + serviceName.toLowerCase() + "/model/pagination/" + opName + "PaginationTraits.h"); + } + writer.write(""); + } + + private void renderNamespaces(CppWriter writer, String serviceName) { + writer.writeNamespaceOpen("Aws"); + writer.writeNamespaceOpen(serviceName); + writer.write(""); + + for (PaginationData data : paginatedOps) { + String opName = data.getOperation().getId().getName(); + writer.write("using %sPaginator = Aws::Utils::Pagination::PagePaginator<%sClient, Model::%sRequest, Pagination::%sPaginationTraits>;", + opName, serviceName, opName, opName); + } + + writer.write(""); + writer.writeNamespaceClose(serviceName); + writer.writeNamespaceClose("Aws"); + } + + private String getServiceName() { + return service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .replace(" ", "") + .replace("-", ""); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/resources/META-INF/services/software.amazon.smithy.build.SmithyBuildPlugin b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/resources/META-INF/services/software.amazon.smithy.build.SmithyBuildPlugin new file mode 100644 index 00000000000..f4e06486044 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/resources/META-INF/services/software.amazon.smithy.build.SmithyBuildPlugin @@ -0,0 +1 @@ +com.amazonaws.util.awsclientsmithygenerator.generators.PaginationCodegenPlugin diff --git a/tools/code-generation/smithy/codegen/cpp-pagination/build.gradle.kts b/tools/code-generation/smithy/codegen/cpp-pagination/build.gradle.kts new file mode 100644 index 00000000000..d4a4310418f --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination/build.gradle.kts @@ -0,0 +1,77 @@ +import software.amazon.smithy.model.Model +import software.amazon.smithy.model.node.Node +import software.amazon.smithy.model.shapes.ServiceShape +import software.amazon.smithy.aws.traits.ServiceTrait +import org.gradle.api.logging.Logging +import kotlin.streams.toList + +val logger = Logging.getLogger("MyLogger") + +plugins { + id("java-library") + id("software.amazon.smithy.gradle.smithy-base").version("1.3.0") +} + +repositories { + mavenLocal() + mavenCentral() +} + +buildscript { + dependencies { + classpath(codegen.model) + classpath(codegen.aws.traits) + classpath(codegen.rules.engine) + } +} + +dependencies { + implementation(project(":cpp-pagination-codegen")) + implementation(codegen.aws.traits) + implementation(codegen.waiters) +} + +tasks.jar { + enabled = false +} + +tasks.register("generate-smithy-build") { + doLast { + val projectionsBuilder = Node.objectNodeBuilder() + val models = project.file("../../api-descriptions") + val filteredServices: String = project.findProperty("servicesFilter")?.toString() ?: "" + val filteredServiceList = filteredServices.split(",").map { it.trim() }.filter { it.isNotEmpty() } + val c2jMapStr: String = project.findProperty("c2jMap")?.toString() ?: "" + + fileTree(models).filter { it.isFile }.files.forEach eachFile@{ file -> + val model = Model.assembler().addImport(file.absolutePath).assemble().result.get() + val services = model.shapes(ServiceShape::class.java).sorted().toList() + if (services.size != 1) return@eachFile + + val service = services[0] + val serviceTrait = service.getTrait(ServiceTrait::class.java).get() + val sdkId = serviceTrait.sdkId.replace(" ", "-").replace("_", "-").lowercase() + + if (filteredServiceList.isNotEmpty() && sdkId !in filteredServiceList) return@eachFile + + val projectionContents = Node.objectNodeBuilder() + .withMember("imports", Node.fromStrings("${models.absolutePath}${File.separator}${file.name}")) + .withMember("plugins", Node.objectNode() + .withMember("cpp-codegen-pagination-plugin", Node.objectNodeBuilder() + .withMember("c2jMap", Node.from(c2jMapStr)) + .build())) + .build() + + projectionsBuilder.withMember("$sdkId.${service.version.lowercase()}", projectionContents) + } + + val outputDirectoryArg = project.findProperty("outputDirectory")?.toString() ?: "output" + file("smithy-build.json").writeText(Node.prettyPrintJson(Node.objectNodeBuilder() + .withMember("version", "1.0") + .withMember("projections", projectionsBuilder.build()) + .withMember("outputDirectory", outputDirectoryArg) + .build())) + } +} + +tasks["build"].dependsOn(tasks["generate-smithy-build"]) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination/smithy-build.json b/tools/code-generation/smithy/codegen/cpp-pagination/smithy-build.json new file mode 100644 index 00000000000..a3adf6fee9d --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination/smithy-build.json @@ -0,0 +1,16 @@ +{ + "version": "1.0", + "projections": { + "s3.2006-03-01": { + "imports": [ + "/Users/cailinn/Desktop/workspace/aws-sdk-cpp/tools/code-generation/smithy/api-descriptions/s3.json" + ], + "plugins": { + "cpp-codegen-pagination-plugin": { + "c2jMap": "{\"api-gateway\": \"apigateway\", \"application-auto-scaling\": \"application-autoscaling\", \"app-mesh\": \"appmesh\", \"auto-scaling\": \"autoscaling\", \"auto-scaling-plans\": \"autoscaling-plans\", \"cloudhsm-v2\": \"cloudhsmv2\", \"cloudsearch-domain\": \"cloudsearchdomain\", \"config-service\": \"config\", \"cost-and-usage-report-service\": \"cur\", \"data-pipeline\": \"datapipeline\", \"device-farm\": \"devicefarm\", \"direct-connect\": \"directconnect\", \"dynamodb-streams\": \"dynamodbstreams\", \"elastic-beanstalk\": \"elasticbeanstalk\", \"elastic-load-balancing\": \"elasticloadbalancing\", \"elastic-load-balancing-v2\": \"elasticloadbalancingv2\", \"global-accelerator\": \"globalaccelerator\", \"iot-1click-devices-service\": \"iot1click-devices\", \"iot-1click-projects\": \"iot1click-projects\", \"iot-data-plane\": \"iot-data\", \"iot-events-data\": \"iotevents-data\", \"iot-events\": \"iotevents\", \"iot-jobs-data-plane\": \"iot-jobs-data\", \"iot-wireless\": \"iotwireless\", \"kinesis-analytics\": \"kinesisanalytics\", \"kinesis-analytics-v2\": \"kinesisanalyticsv2\", \"kinesis-video\": \"kinesisvideo\", \"lex-models-v2\": \"lexv2-models\", \"lex-runtime-service\": \"lex\", \"lex-runtime-v2\": \"lexv2-runtime\", \"machine-learning\": \"machinelearning\", \"marketplace-commerce-analytics\": \"marketplacecommerceanalytics\", \"marketplace-entitlement-service\": \"marketplace-entitlement\", \"marketplace-metering\": \"meteringmarketplace\", \"migration-hub\": \"AWSMigrationHub\", \"mturk\": \"mturk-requester\", \"pinpoint-sms-voice\": \"sms-voice\", \"resource-groups-tagging-api\": \"resourcegroupstaggingapi\", \"route-53-domains\": \"route53domains\", \"route-53\": \"route53\", \"s3-control\": \"s3control\", \"sagemaker-runtime\": \"sagemaker-runtime\", \"secrets-manager\": \"secretsmanager\", \"serverlessapplicationrepository\": \"serverlessrepo\", \"service-catalog-appregistry\": \"servicecatalog-appregistry\", \"service-catalog\": \"servicecatalog\", \"transfer\": \"awstransfer\", \"cloudwatch\": \"monitoring\", \"cloudwatch-events\": \"events\", \"storage-gateway\": \"storagegateway\", \"efs\": \"elasticfilesystem\", \"emr\": \"elasticmapreduce\", \"ses\": \"email\", \"cognito-identity-provider\": \"cognito-idp\", \"cost-explorer\": \"ce\", \"application-discovery-service\": \"discovery\", \"database-migration-service\": \"dms\", \"sfn\": \"states\", \"lex-model-building-service\": \"lex-models\", \"cloudwatch-logs\": \"logs\", \"directory-service\": \"ds\", \"elasticsearch-service \": \"es\", \"importexport\": \"importexport\", \"sdb\": \"sdb\", \"transcribe-streaming\": \"transcribestreaming\"}" + } + } + } + }, + "outputDirectory": "output" +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/settings.gradle.kts b/tools/code-generation/smithy/codegen/settings.gradle.kts index bc2b770a273..e14d59a763f 100644 --- a/tools/code-generation/smithy/codegen/settings.gradle.kts +++ b/tools/code-generation/smithy/codegen/settings.gradle.kts @@ -2,6 +2,8 @@ rootProject.name = "smithy_code_generation" include("cpp-smoke-tests") include("cpp-smoke-tests-codegen") +include("cpp-pagination-codegen") +include("cpp-pagination") pluginManagement { repositories { diff --git a/tools/scripts/codegen/pagination_gen.py b/tools/scripts/codegen/pagination_gen.py new file mode 100644 index 00000000000..34a828d2f43 --- /dev/null +++ b/tools/scripts/codegen/pagination_gen.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 + +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0. + +""" +Wrapper for Smithy pagination generator +""" +import json +import os +import shutil +import subprocess +from typing import List + +SMITHY_GENERATOR_LOCATION = "tools/code-generation/smithy/codegen" +SMITHY_TO_C2J_MAP_FILE = "tools/code-generation/smithy/codegen/smithy2c2j_service_map.json" + + +class PaginationGen(object): + """Wrapper for Smithy pagination generator for C++ SDK""" + + def __init__(self, debug: bool, **kwargs): + self.debug = debug + with open(os.path.abspath(SMITHY_TO_C2J_MAP_FILE), 'r') as file: + self.smithy_c2j_data = json.load(file) + self.c2j_smithy_data = {value: key for key, value in self.smithy_c2j_data.items()} + + def generate(self, clients_to_build: set): + """Generate pagination APIs for SDK clients""" + smithy_services = [self.c2j_smithy_data.get(service, service) for service in clients_to_build] + print(f"Generating pagination for: {','.join(smithy_services)}") + + if self._generate_pagination(smithy_services, json.dumps(self.smithy_c2j_data)): + self._copy_cpp_codegen_contents( + os.path.abspath("tools/code-generation/smithy/codegen"), + "cpp-codegen-pagination-plugin", + os.path.abspath("generated/src") + ) + return 0 + return -1 + + def _generate_pagination(self, smithy_services: List[str], smithy_c2j_data: str): + smithy_codegen_command = [ + "./gradlew", + ":cpp-pagination:build", + "-PservicesFilter=" + ",".join(smithy_services), + "-Pc2jMap=" + smithy_c2j_data + ] + + try: + if self.debug: + print(f"RUNNING: {' '.join(smithy_codegen_command)}\nFROM: {SMITHY_GENERATOR_LOCATION}") + + process = subprocess.run( + smithy_codegen_command, + timeout=6*60, + check=True, + capture_output=True, + text=True, + cwd=SMITHY_GENERATOR_LOCATION + ) + print("Pagination codegen successful!\n", process.stdout) + return True + + except subprocess.CalledProcessError as e: + print(f"Command failed: {e.returncode}\nError: {e.stderr}") + return False + + def _copy_cpp_codegen_contents(self, top_level_dir: str, plugin_name: str, target_dir: str): + for root, dirs, files in os.walk(top_level_dir): + if plugin_name in dirs: + source_dir = os.path.join(root, plugin_name) + + # Extract service name from the projection directory + projection_dir = os.path.basename(os.path.dirname(source_dir)) + service_name = projection_dir.split('.')[0] # e.g., "s3.2006-03-01" -> "s3" + + service_target_dir = os.path.join(target_dir, f"aws-cpp-sdk-{service_name}") + os.makedirs(service_target_dir, exist_ok=True) + + for item in os.listdir(source_dir): + source_item = os.path.join(source_dir, item) + target_item = os.path.join(service_target_dir, item) + if os.path.isdir(source_item): + shutil.copytree(source_item, target_item, dirs_exist_ok=True) + else: + shutil.copy2(source_item, target_item) + print(f"Copied from '{source_dir}' to '{service_target_dir}'") + + # Cleanup output directory + output_dir = os.path.join(top_level_dir, "cpp-pagination/output") + if os.path.exists(output_dir): + shutil.rmtree(output_dir) + print(f"Cleaned up '{output_dir}'") + diff --git a/tools/scripts/run_code_generation.py b/tools/scripts/run_code_generation.py index 014ee39ce3d..69e431675b3 100644 --- a/tools/scripts/run_code_generation.py +++ b/tools/scripts/run_code_generation.py @@ -13,6 +13,7 @@ from codegen.model_utils import ModelUtils from codegen.protocol_tests_gen import ProtocolTestsGen from codegen.smoke_tests_gen import SmokeTestsGen +from codegen.pagination_gen import PaginationGen def parse_arguments() -> dict: @@ -154,6 +155,13 @@ def main(): # generate code using smithy for all discoverable clients # clients_to_build check is present because user can generate only defaults or partitions or protocol-tests clients_to_build = model_utils.get_clients_to_build() + + if clients_to_build: + pagination_gen = PaginationGen(args["debug"]) + if pagination_gen.generate(clients_to_build) != 0: + print("ERROR: Failed to generate pagination!") + return -1 + if args["generate_smoke_tests"] and clients_to_build: smoke_tests_gen = SmokeTestsGen(args["debug"]) if smoke_tests_gen.generate(clients_to_build) != 0: From 153df501974194d2a39b76b42ea4239ca95e14b9 Mon Sep 17 00:00:00 2001 From: kai lin Date: Tue, 13 Jan 2026 14:44:20 -0500 Subject: [PATCH 02/19] Smithy code gen for pagination --- .../include/aws/s3/S3ClientPagination.h | 21 ++++----- .../pagination/ListBucketsPaginationTraits.h | 45 +++++++------------ .../ListDirectoryBucketsPaginationTraits.h | 45 +++++++------------ .../ListObjectsV2PaginationTraits.h | 45 +++++++------------ .../pagination/ListPartsPaginationTraits.h | 45 +++++++------------ .../cpp-pagination-codegen/build.gradle.kts | 1 + .../codegen/cpp-pagination/build.gradle.kts | 16 +++++-- tools/scripts/codegen/legacy_c2j_cpp_gen.py | 7 --- tools/scripts/codegen/pagination_gen.py | 16 ++++--- tools/scripts/run_code_generation.py | 8 ++++ 10 files changed, 112 insertions(+), 137 deletions(-) diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h index ff25ee95d87..9afd5a3e990 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h @@ -4,22 +4,23 @@ */ #pragma once -#include #include +#include #include #include #include #include -namespace Aws -{ -namespace S3 -{ +namespace Aws { +namespace S3 { -using ListBucketsPaginator = Aws::Utils::Pagination::PagePaginator; -using ListDirectoryBucketsPaginator = Aws::Utils::Pagination::PagePaginator; -using ListObjectsV2Paginator = Aws::Utils::Pagination::PagePaginator; +using ListBucketsPaginator = + Aws::Utils::Pagination::PagePaginator; +using ListDirectoryBucketsPaginator = + Aws::Utils::Pagination::PagePaginator; +using ListObjectsV2Paginator = + Aws::Utils::Pagination::PagePaginator; using ListPartsPaginator = Aws::Utils::Pagination::PagePaginator; -} // namespace S3 -} // namespace Aws +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h index 5e180a9499c..b59c4d30577 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h @@ -4,41 +4,30 @@ */ #pragma once +#include #include #include #include -#include -namespace Aws -{ -namespace S3 -{ -namespace Pagination -{ +namespace Aws { +namespace S3 { +namespace Pagination { -struct ListBucketsPaginationTraits -{ - using RequestType = Model::ListBucketsRequest; - using ResultType = Model::ListBucketsResult; - using OutcomeType = Model::ListBucketsOutcome; - using ClientType = S3Client; +struct ListBucketsPaginationTraits { + using RequestType = Model::ListBucketsRequest; + using ResultType = Model::ListBucketsResult; + using OutcomeType = Model::ListBucketsOutcome; + using ClientType = S3Client; - static OutcomeType Invoke(ClientType& client, const RequestType& request) - { - return client.ListBuckets(request); - } + static OutcomeType Invoke(ClientType& client, const RequestType& request) { return client.ListBuckets(request); } - static bool HasMoreResults(const ResultType& result) - { - return result.GetIsTruncated(); - } + static bool HasMoreResults(const ResultType& result) { return result.GetIsTruncated(); } - static void SetNextRequest(const ResultType& result, RequestType& request) - { - request.SetContinuationToken(result.GetContinuationToken()); - } + static void SetNextRequest(const ResultType& result, RequestType& request) { + request.SetContinuationToken(result.GetContinuationToken()); + } }; -} // namespace Pagination -} // namespace S3 -} // namespace Aws +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h index 70e0a73c0ff..42696009e48 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h @@ -4,41 +4,30 @@ */ #pragma once +#include #include #include #include -#include -namespace Aws -{ -namespace S3 -{ -namespace Pagination -{ +namespace Aws { +namespace S3 { +namespace Pagination { -struct ListDirectoryBucketsPaginationTraits -{ - using RequestType = Model::ListDirectoryBucketsRequest; - using ResultType = Model::ListDirectoryBucketsResult; - using OutcomeType = Model::ListDirectoryBucketsOutcome; - using ClientType = S3Client; +struct ListDirectoryBucketsPaginationTraits { + using RequestType = Model::ListDirectoryBucketsRequest; + using ResultType = Model::ListDirectoryBucketsResult; + using OutcomeType = Model::ListDirectoryBucketsOutcome; + using ClientType = S3Client; - static OutcomeType Invoke(ClientType& client, const RequestType& request) - { - return client.ListDirectoryBuckets(request); - } + static OutcomeType Invoke(ClientType& client, const RequestType& request) { return client.ListDirectoryBuckets(request); } - static bool HasMoreResults(const ResultType& result) - { - return result.GetIsTruncated(); - } + static bool HasMoreResults(const ResultType& result) { return result.GetIsTruncated(); } - static void SetNextRequest(const ResultType& result, RequestType& request) - { - request.SetContinuationToken(result.GetContinuationToken()); - } + static void SetNextRequest(const ResultType& result, RequestType& request) { + request.SetContinuationToken(result.GetContinuationToken()); + } }; -} // namespace Pagination -} // namespace S3 -} // namespace Aws +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h index 14f2129b449..2874bd1d609 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h @@ -4,41 +4,30 @@ */ #pragma once +#include #include #include #include -#include -namespace Aws -{ -namespace S3 -{ -namespace Pagination -{ +namespace Aws { +namespace S3 { +namespace Pagination { -struct ListObjectsV2PaginationTraits -{ - using RequestType = Model::ListObjectsV2Request; - using ResultType = Model::ListObjectsV2Result; - using OutcomeType = Model::ListObjectsV2Outcome; - using ClientType = S3Client; +struct ListObjectsV2PaginationTraits { + using RequestType = Model::ListObjectsV2Request; + using ResultType = Model::ListObjectsV2Result; + using OutcomeType = Model::ListObjectsV2Outcome; + using ClientType = S3Client; - static OutcomeType Invoke(ClientType& client, const RequestType& request) - { - return client.ListObjectsV2(request); - } + static OutcomeType Invoke(ClientType& client, const RequestType& request) { return client.ListObjectsV2(request); } - static bool HasMoreResults(const ResultType& result) - { - return result.GetIsTruncated(); - } + static bool HasMoreResults(const ResultType& result) { return result.GetIsTruncated(); } - static void SetNextRequest(const ResultType& result, RequestType& request) - { - request.SetContinuationToken(result.GetNextContinuationToken()); - } + static void SetNextRequest(const ResultType& result, RequestType& request) { + request.SetContinuationToken(result.GetNextContinuationToken()); + } }; -} // namespace Pagination -} // namespace S3 -} // namespace Aws +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h index d1d78792e6d..59c47154ef9 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h @@ -4,41 +4,30 @@ */ #pragma once +#include #include #include #include -#include -namespace Aws -{ -namespace S3 -{ -namespace Pagination -{ +namespace Aws { +namespace S3 { +namespace Pagination { -struct ListPartsPaginationTraits -{ - using RequestType = Model::ListPartsRequest; - using ResultType = Model::ListPartsResult; - using OutcomeType = Model::ListPartsOutcome; - using ClientType = S3Client; +struct ListPartsPaginationTraits { + using RequestType = Model::ListPartsRequest; + using ResultType = Model::ListPartsResult; + using OutcomeType = Model::ListPartsOutcome; + using ClientType = S3Client; - static OutcomeType Invoke(ClientType& client, const RequestType& request) - { - return client.ListParts(request); - } + static OutcomeType Invoke(ClientType& client, const RequestType& request) { return client.ListParts(request); } - static bool HasMoreResults(const ResultType& result) - { - return result.GetIsTruncated(); - } + static bool HasMoreResults(const ResultType& result) { return result.GetIsTruncated(); } - static void SetNextRequest(const ResultType& result, RequestType& request) - { - request.SetPartNumberMarker(result.GetNextPartNumberMarker()); - } + static void SetNextRequest(const ResultType& result, RequestType& request) { + request.SetPartNumberMarker(result.GetNextPartNumberMarker()); + } }; -} // namespace Pagination -} // namespace S3 -} // namespace Aws +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/build.gradle.kts b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/build.gradle.kts index 70081533b3e..d929cca7cbb 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/build.gradle.kts +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/build.gradle.kts @@ -14,4 +14,5 @@ dependencies { 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") + implementation("software.amazon.smithy:smithy-aws-iam-traits:1.51.0") } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination/build.gradle.kts b/tools/code-generation/smithy/codegen/cpp-pagination/build.gradle.kts index d4a4310418f..e6fc1e2a689 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination/build.gradle.kts +++ b/tools/code-generation/smithy/codegen/cpp-pagination/build.gradle.kts @@ -28,6 +28,11 @@ buildscript { dependencies { implementation(project(":cpp-pagination-codegen")) implementation(codegen.aws.traits) + implementation(codegen.aws.cloudformation.traits) + implementation(codegen.aws.iam.traits) + implementation(codegen.aws.endpoints) + implementation(codegen.smoke.test.traits) + implementation(codegen.aws.smoke.test.model) implementation(codegen.waiters) } @@ -44,9 +49,14 @@ tasks.register("generate-smithy-build") { val c2jMapStr: String = project.findProperty("c2jMap")?.toString() ?: "" fileTree(models).filter { it.isFile }.files.forEach eachFile@{ file -> - val model = Model.assembler().addImport(file.absolutePath).assemble().result.get() - val services = model.shapes(ServiceShape::class.java).sorted().toList() - if (services.size != 1) return@eachFile + val model = Model.assembler() + .addImport(file.absolutePath) + // Grab the result directly rather than worrying about checking for errors via unwrap. + // All we care about here is the service shape, any unchecked errors will be exposed + // as part of the actual build task done by the smithy gradle plugin. + .assemble().result.get() + val services = model.shapes(ServiceShape::class.java).sorted().toList() + if (services.size != 1) return@eachFile val service = services[0] val serviceTrait = service.getTrait(ServiceTrait::class.java).get() diff --git a/tools/scripts/codegen/legacy_c2j_cpp_gen.py b/tools/scripts/codegen/legacy_c2j_cpp_gen.py index 7e1df6be35f..ee77eaa90c4 100644 --- a/tools/scripts/codegen/legacy_c2j_cpp_gen.py +++ b/tools/scripts/codegen/legacy_c2j_cpp_gen.py @@ -16,7 +16,6 @@ from concurrent.futures import ProcessPoolExecutor, wait, FIRST_COMPLETED, ALL_COMPLETED from pathlib import Path -from codegen.format_util import format_directories from codegen.include_tests_util import IncludeTestsUtil from codegen.model_utils import ServiceModel @@ -149,12 +148,6 @@ def generate(self, executor: ProcessPoolExecutor, max_workers: int, args: dict) 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()] - if generated_clients: - client_dirs = [f"{self.output_location}/src/aws-cpp-sdk-{client}" for client in generated_clients] - format_directories(client_dirs) - return 0 def _init_common_java_cli(self, diff --git a/tools/scripts/codegen/pagination_gen.py b/tools/scripts/codegen/pagination_gen.py index 34a828d2f43..503faaa6a38 100644 --- a/tools/scripts/codegen/pagination_gen.py +++ b/tools/scripts/codegen/pagination_gen.py @@ -28,13 +28,15 @@ def __init__(self, debug: bool, **kwargs): def generate(self, clients_to_build: set): """Generate pagination APIs for SDK clients""" smithy_services = [self.c2j_smithy_data.get(service, service) for service in clients_to_build] - print(f"Generating pagination for: {','.join(smithy_services)}") + if self.debug: + print(f"Generating pagination for: {','.join(smithy_services)}") if self._generate_pagination(smithy_services, json.dumps(self.smithy_c2j_data)): + target_dir = os.path.abspath("generated/src") self._copy_cpp_codegen_contents( os.path.abspath("tools/code-generation/smithy/codegen"), "cpp-codegen-pagination-plugin", - os.path.abspath("generated/src") + target_dir ) return 0 return -1 @@ -59,7 +61,9 @@ def _generate_pagination(self, smithy_services: List[str], smithy_c2j_data: str) text=True, cwd=SMITHY_GENERATOR_LOCATION ) - print("Pagination codegen successful!\n", process.stdout) + print("Pagination codegen successful!") + if self.debug: + print(process.stdout) return True except subprocess.CalledProcessError as e: @@ -85,11 +89,13 @@ def _copy_cpp_codegen_contents(self, top_level_dir: str, plugin_name: str, targe shutil.copytree(source_item, target_item, dirs_exist_ok=True) else: shutil.copy2(source_item, target_item) - print(f"Copied from '{source_dir}' to '{service_target_dir}'") + if self.debug: + print(f"Copied from '{source_dir}' to '{service_target_dir}'") # Cleanup output directory output_dir = os.path.join(top_level_dir, "cpp-pagination/output") if os.path.exists(output_dir): shutil.rmtree(output_dir) - print(f"Cleaned up '{output_dir}'") + if self.debug: + print(f"Cleaned up '{output_dir}'") diff --git a/tools/scripts/run_code_generation.py b/tools/scripts/run_code_generation.py index 69e431675b3..b88ee081179 100644 --- a/tools/scripts/run_code_generation.py +++ b/tools/scripts/run_code_generation.py @@ -14,6 +14,7 @@ from codegen.protocol_tests_gen import ProtocolTestsGen from codegen.smoke_tests_gen import SmokeTestsGen from codegen.pagination_gen import PaginationGen +from codegen.format_util import format_directories def parse_arguments() -> dict: @@ -168,6 +169,13 @@ def main(): print("ERROR: Failed to generate smoke test(s)!") return -1 + # Format all generated C++ code at the end + if clients_to_build: + client_dirs = [f"{args['output_location']}/src/aws-cpp-sdk-{client}" for client in clients_to_build] + existing_dirs = [d for d in client_dirs if os.path.exists(d)] + if existing_dirs: + format_directories(existing_dirs) + return 0 From 1461605321e8515e6ec3c4cc79d244b4a6434208 Mon Sep 17 00:00:00 2001 From: kai lin Date: Wed, 14 Jan 2026 14:57:37 -0500 Subject: [PATCH 03/19] updated parser to use c2j mapping names --- .../generators/PaginationParser.java | 31 ++++++++++++++++++- tools/scripts/codegen/pagination_gen.py | 8 +++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java index f88dcfc1cdf..05116306ce2 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java @@ -6,6 +6,8 @@ import software.amazon.smithy.build.PluginContext; import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.aws.traits.ServiceTrait; import com.amazonaws.util.awsclientsmithygenerator.CppWriterDelegator; @@ -17,12 +19,27 @@ public class PaginationParser { private final Model model; private final PaginationShapeDiscovery shapeDiscovery; private final CppWriterDelegator writerDelegator; + private Map c2jMap; public PaginationParser(PluginContext context) { this.context = context; this.model = context.getModel(); this.shapeDiscovery = new PaginationShapeDiscovery(model); this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); + + // Initialize c2j map + this.c2jMap = new HashMap<>(); + ObjectNode settings = context.getSettings(); + if (settings.containsMember("c2jMap")) { + Node c2jMapNode = settings.expectMember("c2jMap"); + if (c2jMapNode.isStringNode()) { + String jsonStr = c2jMapNode.expectStringNode().getValue(); + ObjectNode mapNode = Node.parseJsonWithComments(jsonStr).expectObjectNode(); + mapNode.getMembers().forEach((key, value) -> { + this.c2jMap.put(key.getValue(), value.expectStringNode().getValue()); + }); + } + } } public void run() { @@ -38,10 +55,11 @@ public void run() { private void generatePaginationFiles(ServiceShape service, List paginatedOps) { String serviceName = getServiceName(service); + String c2jServiceName = getC2jServiceName(service); // Generate client pagination header writerDelegator.useFileWriter( - "include/aws/" + serviceName.toLowerCase() + "/" + serviceName + "ClientPagination.h", + "include/aws/" + c2jServiceName + "/" + serviceName + "ClientPagination.h", writer -> new PaginationClientTemplate(service, paginatedOps).render(writer) ); @@ -57,4 +75,15 @@ private String getServiceName(ServiceShape service) { .replace(" ", "") .replace("-", ""); } + + private String getC2jServiceName(ServiceShape service) { + String sdkId = service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .trim() + .toLowerCase() + .replace(" ", "-"); + + return c2jMap.getOrDefault(sdkId, sdkId); + } } diff --git a/tools/scripts/codegen/pagination_gen.py b/tools/scripts/codegen/pagination_gen.py index 503faaa6a38..1a5b7704ee2 100644 --- a/tools/scripts/codegen/pagination_gen.py +++ b/tools/scripts/codegen/pagination_gen.py @@ -64,6 +64,7 @@ def _generate_pagination(self, smithy_services: List[str], smithy_c2j_data: str) print("Pagination codegen successful!") if self.debug: print(process.stdout) + print(f"Pagination generation done, (re)generated {len(smithy_services)} package(s).") return True except subprocess.CalledProcessError as e: @@ -77,9 +78,12 @@ def _copy_cpp_codegen_contents(self, top_level_dir: str, plugin_name: str, targe # Extract service name from the projection directory projection_dir = os.path.basename(os.path.dirname(source_dir)) - service_name = projection_dir.split('.')[0] # e.g., "s3.2006-03-01" -> "s3" + smithy_service_name = projection_dir.split('.')[0] # e.g., "api-gateway.2017-11-27" -> "api-gateway" - service_target_dir = os.path.join(target_dir, f"aws-cpp-sdk-{service_name}") + # Map to c2j service name + c2j_service_name = self.smithy_c2j_data.get(smithy_service_name, smithy_service_name) + + service_target_dir = os.path.join(target_dir, f"aws-cpp-sdk-{c2j_service_name}") os.makedirs(service_target_dir, exist_ok=True) for item in os.listdir(source_dir): From 262eae8d0493dd3cc29fbce5e22c25b8190f1c0f Mon Sep 17 00:00:00 2001 From: kai lin Date: Wed, 14 Jan 2026 15:53:54 -0500 Subject: [PATCH 04/19] updated writer to use c2j mapping names and deleted space in map.json --- .../generators/PaginationHeaderWriter.java | 14 ++++++++------ .../generators/PaginationParser.java | 2 +- .../smithy/codegen/smithy2c2j_service_map.json | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java index a72b357a328..09d91faa596 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java @@ -16,11 +16,13 @@ public class PaginationHeaderWriter { private final PluginContext context; private final ServiceShape service; private final List paginatedOps; + private final String c2jServiceName; - public PaginationHeaderWriter(PluginContext context, ServiceShape service, List paginatedOps) { + public PaginationHeaderWriter(PluginContext context, ServiceShape service, List paginatedOps, String c2jServiceName) { this.context = context; this.service = service; this.paginatedOps = paginatedOps; + this.c2jServiceName = c2jServiceName; } public void write() { @@ -30,7 +32,7 @@ public void write() { .replace(" ", "") .replace("-", ""); Path outputPath = context.getFileManifest().getBaseDir() - .resolve("include/aws/" + serviceName.toLowerCase() + "/model/pagination"); + .resolve("include/aws/" + c2jServiceName + "/model/pagination"); for (PaginationData data : paginatedOps) { String content = generateTraitsHeader(data, serviceName); @@ -56,10 +58,10 @@ private String generateTraitsHeader(PaginationData data, String serviceName) { sb.append(" * SPDX-License-Identifier: Apache-2.0.\n"); sb.append(" */\n\n"); sb.append("#pragma once\n"); - sb.append("#include \n"); - sb.append("#include \n"); - sb.append("#include \n"); - sb.append("#include \n\n"); + sb.append("#include \n"); + sb.append("#include \n"); + sb.append("#include \n"); + sb.append("#include \n\n"); sb.append("namespace Aws\n{\nnamespace ").append(serviceName).append("\n{\nnamespace Pagination\n{\n\n"); sb.append("struct ").append(opName).append("PaginationTraits\n{\n"); sb.append(" using RequestType = Model::").append(opName).append("Request;\n"); diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java index 05116306ce2..45e9f7b58dc 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java @@ -64,7 +64,7 @@ private void generatePaginationFiles(ServiceShape service, List ); // Generate pagination traits headers - PaginationHeaderWriter headerWriter = new PaginationHeaderWriter(context, service, paginatedOps); + PaginationHeaderWriter headerWriter = new PaginationHeaderWriter(context, service, paginatedOps, c2jServiceName); headerWriter.write(); } diff --git a/tools/code-generation/smithy/codegen/smithy2c2j_service_map.json b/tools/code-generation/smithy/codegen/smithy2c2j_service_map.json index d4865618ff4..1ff0190e0ac 100644 --- a/tools/code-generation/smithy/codegen/smithy2c2j_service_map.json +++ b/tools/code-generation/smithy/codegen/smithy2c2j_service_map.json @@ -60,7 +60,7 @@ "lex-model-building-service":"lex-models", "cloudwatch-logs":"logs", "directory-service":"ds", - "elasticsearch-service ":"es", + "elasticsearch-service":"es", "importexport":"importexport", "sdb":"sdb", "transcribe-streaming":"transcribestreaming" From b647665a4b084564187be4f2b47de27ebc44cd85 Mon Sep 17 00:00:00 2001 From: kai lin Date: Thu, 15 Jan 2026 12:05:53 -0500 Subject: [PATCH 05/19] fix file location --- .../util/awsclientsmithygenerator/{ => generators}/CppWriter.java | 0 .../{ => generators}/CppWriterDelegator.java | 0 .../generators/{ => templates}/PaginationCodegenPlugin.java | 0 .../generators/{ => templates}/PaginationData.java | 0 .../generators/{ => templates}/PaginationHeaderWriter.java | 0 .../generators/{ => templates}/PaginationParser.java | 0 .../generators/{ => templates}/PaginationShapeDiscovery.java | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/{ => generators}/CppWriter.java (100%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/{ => generators}/CppWriterDelegator.java (100%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{ => templates}/PaginationCodegenPlugin.java (100%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{ => templates}/PaginationData.java (100%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{ => templates}/PaginationHeaderWriter.java (100%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{ => templates}/PaginationParser.java (100%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{ => templates}/PaginationShapeDiscovery.java (100%) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java similarity index 100% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriter.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriterDelegator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriterDelegator.java similarity index 100% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/CppWriterDelegator.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriterDelegator.java diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCodegenPlugin.java similarity index 100% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCodegenPlugin.java diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationData.java similarity index 100% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationData.java diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationHeaderWriter.java similarity index 100% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationHeaderWriter.java diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationParser.java similarity index 100% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationParser.java diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationShapeDiscovery.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationShapeDiscovery.java similarity index 100% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationShapeDiscovery.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationShapeDiscovery.java From 03c06ef7b8975163a6575924677d985275bef067 Mon Sep 17 00:00:00 2001 From: kai lin Date: Thu, 15 Jan 2026 14:40:22 -0500 Subject: [PATCH 06/19] added a compilation test --- .../pagination/ListBucketsPaginationTraits.h | 2 +- .../ListDirectoryBucketsPaginationTraits.h | 2 +- .../ListObjectsV2PaginationTraits.h | 2 +- .../pagination/ListPartsPaginationTraits.h | 2 +- .../AllPaginationHeadersCompilationTest.cpp | 28 ++++++++ .../generators/ClientCodegenSettings.java | 20 ++++++ .../generators/CppWriter.java | 5 +- .../generators/CppWriterDelegator.java | 2 +- .../generators/HeaderCompilationParser.java | 65 +++++++++++++++++ .../generators/PaginationCodegenPlugin.java | 45 ++++++++++++ .../{templates => }/PaginationData.java | 2 +- .../PaginationHeaderWriter.java | 18 ++++- .../{templates => }/PaginationParser.java | 20 +++--- .../generators/ShapeUtil.java | 25 +++++++ .../HeaderCompilationCMakeTemplate.java | 42 +++++++++++ .../templates/HeaderCompilationTemplate.java | 70 +++++++++++++++++++ .../templates/PaginationClientTemplate.java | 4 +- .../templates/PaginationCodegenPlugin.java | 22 ------ .../templates/PaginationShapeDiscovery.java | 37 ---------- tools/scripts/codegen/pagination_gen.py | 13 ++++ 20 files changed, 344 insertions(+), 82 deletions(-) create mode 100644 generated/tests/s3-gen-tests/AllPaginationHeadersCompilationTest.cpp create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ClientCodegenSettings.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/HeaderCompilationParser.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{templates => }/PaginationData.java (91%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{templates => }/PaginationHeaderWriter.java (82%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{templates => }/PaginationParser.java (83%) create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ShapeUtil.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationCMakeTemplate.java create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationTemplate.java delete mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCodegenPlugin.java delete mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationShapeDiscovery.java diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h index b59c4d30577..a3ab75a45a2 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListBucketsPaginationTraits.h @@ -21,7 +21,7 @@ struct ListBucketsPaginationTraits { static OutcomeType Invoke(ClientType& client, const RequestType& request) { return client.ListBuckets(request); } - static bool HasMoreResults(const ResultType& result) { return result.GetIsTruncated(); } + static bool HasMoreResults(const ResultType& result) { return !result.GetContinuationToken().empty(); } static void SetNextRequest(const ResultType& result, RequestType& request) { request.SetContinuationToken(result.GetContinuationToken()); diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h index 42696009e48..f7f6de8b6fc 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListDirectoryBucketsPaginationTraits.h @@ -21,7 +21,7 @@ struct ListDirectoryBucketsPaginationTraits { static OutcomeType Invoke(ClientType& client, const RequestType& request) { return client.ListDirectoryBuckets(request); } - static bool HasMoreResults(const ResultType& result) { return result.GetIsTruncated(); } + static bool HasMoreResults(const ResultType& result) { return !result.GetContinuationToken().empty(); } static void SetNextRequest(const ResultType& result, RequestType& request) { request.SetContinuationToken(result.GetContinuationToken()); diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h index 2874bd1d609..718d6333778 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListObjectsV2PaginationTraits.h @@ -21,7 +21,7 @@ struct ListObjectsV2PaginationTraits { static OutcomeType Invoke(ClientType& client, const RequestType& request) { return client.ListObjectsV2(request); } - static bool HasMoreResults(const ResultType& result) { return result.GetIsTruncated(); } + static bool HasMoreResults(const ResultType& result) { return !result.GetNextContinuationToken().empty(); } static void SetNextRequest(const ResultType& result, RequestType& request) { request.SetContinuationToken(result.GetNextContinuationToken()); diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h index 59c47154ef9..dc6a20a510d 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/pagination/ListPartsPaginationTraits.h @@ -21,7 +21,7 @@ struct ListPartsPaginationTraits { static OutcomeType Invoke(ClientType& client, const RequestType& request) { return client.ListParts(request); } - static bool HasMoreResults(const ResultType& result) { return result.GetIsTruncated(); } + static bool HasMoreResults(const ResultType& result) { return result.GetNextPartNumberMarker() != 0; } static void SetNextRequest(const ResultType& result, RequestType& request) { request.SetPartNumberMarker(result.GetNextPartNumberMarker()); diff --git a/generated/tests/s3-gen-tests/AllPaginationHeadersCompilationTest.cpp b/generated/tests/s3-gen-tests/AllPaginationHeadersCompilationTest.cpp new file mode 100644 index 00000000000..418f96be4ce --- /dev/null +++ b/generated/tests/s3-gen-tests/AllPaginationHeadersCompilationTest.cpp @@ -0,0 +1,28 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +// Header compilation test for ALL pagination headers +// This test ensures all generated pagination headers compile successfully + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class AllPaginationHeadersCompilationTest : public Aws::Testing::AwsCppSdkGTestSuite +{ +}; + +TEST_F(AllPaginationHeadersCompilationTest, AllPaginationHeadersCompile) +{ + // Test passes if compilation succeeds + SUCCEED(); +} diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ClientCodegenSettings.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ClientCodegenSettings.java new file mode 100644 index 00000000000..f992d3b76df --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ClientCodegenSettings.java @@ -0,0 +1,20 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.shapes.ShapeId; + +public class ClientCodegenSettings { + private final ShapeId service; + + public ClientCodegenSettings(ObjectNode settings) { + this.service = ShapeId.from(settings.expectStringMember("service").getValue()); + } + + public ShapeId getService() { + return service; + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java index 9317bc0655a..da9add080f1 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java @@ -2,15 +2,16 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -package com.amazonaws.util.awsclientsmithygenerator; +package com.amazonaws.util.awsclientsmithygenerator.generators; import java.util.function.Consumer; public class CppWriter { private final StringBuilder content = new StringBuilder(); - public void write(String text, Object... args) { + public CppWriter write(String text, Object... args) { content.append(String.format(text, args)).append("\n"); + return this; } public void openBlock(String opener, String closer, Consumer block) { diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriterDelegator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriterDelegator.java index d2adb93fdc2..9d42e8b7090 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriterDelegator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriterDelegator.java @@ -2,7 +2,7 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -package com.amazonaws.util.awsclientsmithygenerator; +package com.amazonaws.util.awsclientsmithygenerator.generators; import software.amazon.smithy.build.FileManifest; import java.nio.file.Path; diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/HeaderCompilationParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/HeaderCompilationParser.java new file mode 100644 index 00000000000..6ca4a65f926 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/HeaderCompilationParser.java @@ -0,0 +1,65 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.aws.traits.ServiceTrait; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.HeaderCompilationTemplate; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.HeaderCompilationCMakeTemplate; +import com.amazonaws.util.awsclientsmithygenerator.generators.ShapeUtil; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import java.util.*; + +public class HeaderCompilationParser { + private final PluginContext context; + private final ServiceShape service; + private final List paginatedOps; + private final CppWriterDelegator writerDelegator; + + public HeaderCompilationParser(PluginContext context, ServiceShape service, List paginatedOps) { + this.context = context; + this.service = service; + this.paginatedOps = paginatedOps; + this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); + } + + public void run() { + List services = List.of(service); + generateSingleHeaderCompilationTest(services, paginatedOps); + writerDelegator.flushWriters(); + } + + private void generateSingleHeaderCompilationTest(List services, List allPaginatedOps) { + String serviceName = getServiceName(service); + String c2jServiceName = getC2jServiceName(service); + + // Generate single compilation test for all pagination headers in service's client-gen-tests + writerDelegator.useFileWriter( + "generated/tests/" + c2jServiceName + "-gen-tests/AllPaginationHeadersCompilationTest.cpp", + writer -> new HeaderCompilationTemplate(services, allPaginatedOps).render(writer) + ); + } + + + private String getServiceName(ServiceShape service) { + return service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .replace(" ", "") + .replace("-", ""); + } + + private String getC2jServiceName(ServiceShape service) { + return service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .trim() + .toLowerCase() + .replace(" ", "-"); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java new file mode 100644 index 00000000000..9d4dd0e6504 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java @@ -0,0 +1,45 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.build.SmithyBuildPlugin; +import software.amazon.smithy.model.knowledge.TopDownIndex; +import software.amazon.smithy.model.traits.PaginatedTrait; +import software.amazon.smithy.model.shapes.*; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import java.util.List; +import java.util.stream.Collectors; + +public class PaginationCodegenPlugin implements SmithyBuildPlugin { + + @Override + public String getName() { + return "cpp-codegen-pagination-plugin"; + } + + @Override + public void execute(PluginContext context) { + var model = context.getModel(); + + for (ServiceShape service : model.getServiceShapes()) { + // Find paginated operations using TopDownIndex + List paginatedOps = TopDownIndex.of(model).getContainedOperations(service).stream() + .filter(op -> op.hasTrait(PaginatedTrait.class)) + .map(op -> new PaginationData(op, op.expectTrait(PaginatedTrait.class), service)) + .collect(Collectors.toList()); + + if (!paginatedOps.isEmpty()) { + // Generate pagination files + PaginationParser parser = new PaginationParser(context, service, paginatedOps); + parser.run(); + + // Generate header compilation test + HeaderCompilationParser headerParser = new HeaderCompilationParser(context, service, paginatedOps); + headerParser.run(); + } + } + } +} diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationData.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java similarity index 91% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationData.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java index d17d7718d86..62a13819dd1 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationData.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java @@ -2,7 +2,7 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -package com.amazonaws.util.awsclientsmithygenerator.generators; +package com.amazonaws.util.awsclientsmithygenerator.generators.templates; import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.model.traits.PaginatedTrait; diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationHeaderWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java similarity index 82% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationHeaderWriter.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java index 09d91faa596..08eb41cdc21 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationHeaderWriter.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java @@ -9,6 +9,7 @@ import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.model.traits.PaginatedTrait; import software.amazon.smithy.aws.traits.ServiceTrait; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; import java.nio.file.*; import java.util.*; @@ -73,8 +74,21 @@ private String generateTraitsHeader(PaginationData data, String serviceName) { sb.append(" return client.").append(opName).append("(request);\n }\n\n"); sb.append(" static bool HasMoreResults(const ResultType& result)\n {\n"); - // Check if there's a truncated field first, otherwise fall back to token check - sb.append(" return result.GetIsTruncated();\n"); + // Use the output token to determine if there are more results + if (trait.getOutputToken().isPresent()) { + String outToken = trait.getOutputToken().get(); + // Handle different token types - strings use .empty(), numbers check for non-zero + if (outToken.toLowerCase().contains("marker") || outToken.toLowerCase().contains("number")) { + // Numeric tokens - check if they exist/are set + sb.append(" return result.Get").append(capitalize(outToken)).append("() != 0;\n"); + } else { + // String tokens - check if not empty + sb.append(" return !result.Get").append(capitalize(outToken)).append("().empty();\n"); + } + } else { + // Fallback to checking for IsTruncated if no output token + sb.append(" return result.GetIsTruncated();\n"); + } sb.append(" }\n\n"); sb.append(" static void SetNextRequest(const ResultType& result, RequestType& request)\n {\n"); diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java similarity index 83% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationParser.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java index 45e9f7b58dc..98c829628b7 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationParser.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java @@ -10,21 +10,25 @@ import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.aws.traits.ServiceTrait; -import com.amazonaws.util.awsclientsmithygenerator.CppWriterDelegator; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.PaginationHeaderWriter; import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationClientTemplate; import java.util.*; public class PaginationParser { private final PluginContext context; private final Model model; - private final PaginationShapeDiscovery shapeDiscovery; + private final ServiceShape service; + private final List paginatedOps; private final CppWriterDelegator writerDelegator; private Map c2jMap; - public PaginationParser(PluginContext context) { + public PaginationParser(PluginContext context, ServiceShape service, List paginatedOps) { this.context = context; this.model = context.getModel(); - this.shapeDiscovery = new PaginationShapeDiscovery(model); + this.service = service; + this.paginatedOps = paginatedOps; this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); // Initialize c2j map @@ -43,13 +47,7 @@ public PaginationParser(PluginContext context) { } public void run() { - for (ServiceShape service : model.getServiceShapes()) { - List paginatedOps = shapeDiscovery.findPaginatedOperations(service); - - if (!paginatedOps.isEmpty()) { - generatePaginationFiles(service, paginatedOps); - } - } + generatePaginationFiles(service, paginatedOps); writerDelegator.flushWriters(); } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ShapeUtil.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ShapeUtil.java new file mode 100644 index 00000000000..0745a619a92 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ShapeUtil.java @@ -0,0 +1,25 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.*; +import java.util.HashSet; +import java.util.Set; + +public class ShapeUtil { + + /** + * Returns all shapes referenced by a root shape, recursively. + */ + public static Set getReferences(Model model, Shape root) { + Set refs = new HashSet<>(); + refs.add(root); + for (var member : root.members()) { + refs.addAll(getReferences(model, model.expectShape(member.getTarget()))); + } + return refs; + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationCMakeTemplate.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationCMakeTemplate.java new file mode 100644 index 00000000000..598abe29a20 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationCMakeTemplate.java @@ -0,0 +1,42 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.templates; + +import software.amazon.smithy.model.shapes.ServiceShape; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; + +public class HeaderCompilationCMakeTemplate { + + public HeaderCompilationCMakeTemplate() { + } + + public void render(CppWriter writer) { + String testName = "all-pagination-headers-compilation-test"; + + writer.write("# Header compilation test for all pagination headers") + .write("cmake_minimum_required(VERSION 3.13)") + .write("") + .write("project($L)", testName) + .write("") + .write("find_package(aws-cpp-sdk-core REQUIRED)") + .write("find_package(GTest REQUIRED)") + .write("") + .write("add_executable($L", testName) + .write(" AllPaginationHeadersCompilationTest.cpp") + .write(")") + .write("") + .write("target_link_libraries($L", testName) + .write(" aws-cpp-sdk-core") + .write(" GTest::gtest") + .write(" GTest::gtest_main") + .write(")") + .write("") + .write("target_include_directories($L PRIVATE", testName) + .write(" ${CMAKE_CURRENT_SOURCE_DIR}") + .write(")") + .write("") + .write("add_test(NAME $L COMMAND $L)", testName, testName); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationTemplate.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationTemplate.java new file mode 100644 index 00000000000..20e53fb6ff3 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationTemplate.java @@ -0,0 +1,70 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.templates; + +import software.amazon.smithy.model.shapes.*; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import java.util.*; + +public class HeaderCompilationTemplate { + private final List services; + private final List allPaginatedOps; + + public HeaderCompilationTemplate(List services, List allPaginatedOps) { + this.services = services; + this.allPaginatedOps = allPaginatedOps; + } + + public void render(CppWriter writer) { + writer.write("/**") + .write(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.") + .write(" * SPDX-License-Identifier: Apache-2.0.") + .write(" */") + .write("") + .write("// Header compilation test for ALL pagination headers") + .write("// This test ensures all generated pagination headers compile successfully") + .write(""); + + // Include all service headers + writeIncludes(writer); + + writer.write("") + .write("#include ") + .write("") + .write("class AllPaginationHeadersCompilationTest : public Aws::Testing::AwsCppSdkGTestSuite") + .write("{") + .write("};") + .write("") + .write("TEST_F(AllPaginationHeadersCompilationTest, AllPaginationHeadersCompile)") + .write("{") + .write(" // Test passes if compilation succeeds") + .write(" SUCCEED();") + .write("}"); + } + + private void writeIncludes(CppWriter writer) { + for (PaginationData paginationData : allPaginatedOps) { + ServiceShape service = paginationData.getService(); + String serviceName = getServiceName(service); + + // Include pagination client header + writer.writeInclude("aws/" + serviceName.toLowerCase() + "/" + serviceName + "ClientPagination.h"); + + // Include pagination traits headers + String operationName = paginationData.getOperation().getId().getName(); + writer.writeInclude("aws/" + serviceName.toLowerCase() + "/model/pagination/" + operationName + "PaginationTraits.h"); + } + } + + private String getServiceName(ServiceShape service) { + return service.getTrait(software.amazon.smithy.aws.traits.ServiceTrait.class) + .map(software.amazon.smithy.aws.traits.ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .replace(" ", "") + .replace("-", ""); + } + +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java index 23ad0d4157c..2338ec5aeec 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java @@ -4,8 +4,8 @@ */ package com.amazonaws.util.awsclientsmithygenerator.generators.templates; -import com.amazonaws.util.awsclientsmithygenerator.CppWriter; -import com.amazonaws.util.awsclientsmithygenerator.generators.PaginationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.aws.traits.ServiceTrait; import java.util.List; diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCodegenPlugin.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCodegenPlugin.java deleted file mode 100644 index d28917359c1..00000000000 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCodegenPlugin.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -package com.amazonaws.util.awsclientsmithygenerator.generators; - -import software.amazon.smithy.build.PluginContext; -import software.amazon.smithy.build.SmithyBuildPlugin; - -public class PaginationCodegenPlugin implements SmithyBuildPlugin { - - @Override - public String getName() { - return "cpp-codegen-pagination-plugin"; - } - - @Override - public void execute(PluginContext context) { - PaginationParser parser = new PaginationParser(context); - parser.run(); - } -} diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationShapeDiscovery.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationShapeDiscovery.java deleted file mode 100644 index 14f5b67c143..00000000000 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationShapeDiscovery.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -package com.amazonaws.util.awsclientsmithygenerator.generators; - -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.*; -import software.amazon.smithy.model.traits.PaginatedTrait; -import java.util.*; -import java.util.stream.Collectors; - -public class PaginationShapeDiscovery { - private final Model model; - - public PaginationShapeDiscovery(Model model) { - this.model = model; - } - - public List findPaginatedOperations(ServiceShape service) { - return service.getOperations().stream() - .map(id -> model.expectShape(id, OperationShape.class)) - .filter(op -> op.hasTrait(PaginatedTrait.class)) - .map(op -> new PaginationData(op, op.expectTrait(PaginatedTrait.class), service)) - .collect(Collectors.toList()); - } - - public Set getReferencedStructures(List paginatedOps) { - Set structures = new HashSet<>(); - for (PaginationData data : paginatedOps) { - OperationShape op = data.getOperation(); - structures.add(model.expectShape(op.getInputShape(), StructureShape.class)); - structures.add(model.expectShape(op.getOutputShape(), StructureShape.class)); - } - return structures; - } -} \ No newline at end of file diff --git a/tools/scripts/codegen/pagination_gen.py b/tools/scripts/codegen/pagination_gen.py index 1a5b7704ee2..5a70e731971 100644 --- a/tools/scripts/codegen/pagination_gen.py +++ b/tools/scripts/codegen/pagination_gen.py @@ -88,11 +88,24 @@ def _copy_cpp_codegen_contents(self, top_level_dir: str, plugin_name: str, targe for item in os.listdir(source_dir): source_item = os.path.join(source_dir, item) + + # Handle test directories separately - move to generated/tests + if item == "generated" and os.path.isdir(source_item): + generated_source = os.path.join(source_item, "tests") + if os.path.exists(generated_source): + test_target_dir = os.path.abspath("generated/tests") + os.makedirs(test_target_dir, exist_ok=True) + shutil.copytree(generated_source, test_target_dir, dirs_exist_ok=True) + if self.debug: + print(f"Copied tests from '{generated_source}' to '{test_target_dir}'") + continue + target_item = os.path.join(service_target_dir, item) if os.path.isdir(source_item): shutil.copytree(source_item, target_item, dirs_exist_ok=True) else: shutil.copy2(source_item, target_item) + if self.debug: print(f"Copied from '{source_dir}' to '{service_target_dir}'") From d58423ec3617749ea6d6b51bf283f2c56b40f7ef Mon Sep 17 00:00:00 2001 From: kai lin Date: Thu, 15 Jan 2026 15:32:38 -0500 Subject: [PATCH 07/19] updated cppwriter to use smithy library --- ...t.cpp => S3PaginationCompilationTests.cpp} | 10 ++--- .../generators/CppImportContainer.java | 36 ++++++++++++++++ .../generators/CppWriter.java | 43 ++++++++++--------- ...PaginationData.java => OperationData.java} | 12 +++--- .../generators/PaginationCodegenPlugin.java | 10 +++-- ...a => PaginationCompilationTestParser.java} | 20 ++++----- .../generators/PaginationHeaderWriter.java | 11 ++--- .../generators/PaginationParser.java | 9 ++-- .../HeaderCompilationCMakeTemplate.java | 42 ------------------ .../templates/PaginationClientTemplate.java | 13 +++--- ...> PaginationCompilationTestGenerator.java} | 37 +++++++++------- .../codegen/cpp-pagination/smithy-build.json | 12 +++++- 12 files changed, 135 insertions(+), 120 deletions(-) rename generated/tests/s3-gen-tests/{AllPaginationHeadersCompilationTest.cpp => S3PaginationCompilationTests.cpp} (71%) create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppImportContainer.java rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{PaginationData.java => OperationData.java} (60%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{HeaderCompilationParser.java => PaginationCompilationTestParser.java} (70%) delete mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationCMakeTemplate.java rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/{HeaderCompilationTemplate.java => PaginationCompilationTestGenerator.java} (63%) diff --git a/generated/tests/s3-gen-tests/AllPaginationHeadersCompilationTest.cpp b/generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp similarity index 71% rename from generated/tests/s3-gen-tests/AllPaginationHeadersCompilationTest.cpp rename to generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp index 418f96be4ce..0fa4ac48c38 100644 --- a/generated/tests/s3-gen-tests/AllPaginationHeadersCompilationTest.cpp +++ b/generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0. */ -// Header compilation test for ALL pagination headers +// Header compilation test for S3 pagination headers // This test ensures all generated pagination headers compile successfully #include @@ -17,12 +17,12 @@ #include -class AllPaginationHeadersCompilationTest : public Aws::Testing::AwsCppSdkGTestSuite +class S3PaginationCompilationTest : public Aws::Testing::AwsCppSdkGTestSuite { }; -TEST_F(AllPaginationHeadersCompilationTest, AllPaginationHeadersCompile) +TEST_F(S3PaginationCompilationTest, S3PaginationHeadersCompile) { - // Test passes if compilation succeeds - SUCCEED(); + // Test passes if compilation succeeds + SUCCEED(); } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppImportContainer.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppImportContainer.java new file mode 100644 index 00000000000..8c26688ae5f --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppImportContainer.java @@ -0,0 +1,36 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.codegen.core.ImportContainer; +import software.amazon.smithy.codegen.core.Symbol; +import java.util.HashSet; +import java.util.Set; + +/** + * CppImportContainer tracks symbols used in code generation. + * For C++, we handle includes manually via writeInclude method. + */ +public class CppImportContainer implements ImportContainer { + private final Set imports = new HashSet<>(); + + @Override + public void importSymbol(Symbol symbol, String alias) { + // Track the symbol's namespace for potential future use + if (symbol.getNamespace() != null && !symbol.getNamespace().isEmpty()) { + imports.add(symbol.getNamespace()); + } + } + + public Set getImports() { + return imports; + } + + @Override + public String toString() { + // Return empty string since we handle includes manually + return ""; + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java index da9add080f1..950e772d793 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java @@ -4,36 +4,39 @@ */ package com.amazonaws.util.awsclientsmithygenerator.generators; -import java.util.function.Consumer; +import software.amazon.smithy.codegen.core.SymbolWriter; -public class CppWriter { - private final StringBuilder content = new StringBuilder(); +public class CppWriter extends SymbolWriter { - public CppWriter write(String text, Object... args) { - content.append(String.format(text, args)).append("\n"); - return this; - } - - public void openBlock(String opener, String closer, Consumer block) { - write(opener); - block.accept(null); - write(closer); + public CppWriter() { + super(new CppImportContainer()); + + // Add custom formatter for symbols + putFormatter('T', (arg, indent) -> { + if (!(arg instanceof software.amazon.smithy.codegen.core.Symbol symbol)) { + throw new software.amazon.smithy.codegen.core.CodegenException("Expected a symbol but got " + arg); + } + + // Record our symbol so we can generate appropriate includes later if needed + getImportContainer().importSymbol(symbol, null); + + // For C++, use namespace::name syntax (e.g. Aws::S3::Model::ListBucketsRequest) + if (symbol.getNamespace() != null && !symbol.getNamespace().isEmpty()) { + return symbol.getNamespace() + "::" + symbol.getName(); + } + return symbol.getName(); + }); } public void writeInclude(String header) { - write("#include <%s>", header); + write("#include <$L>", header); } public void writeNamespaceOpen(String namespace) { - write("namespace %s\n{", namespace); + write("namespace $L\n{", namespace); } public void writeNamespaceClose(String namespace) { - write("} // namespace %s", namespace); - } - - @Override - public String toString() { - return content.toString(); + write("} // namespace $L", namespace); } } \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/OperationData.java similarity index 60% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/OperationData.java index 62a13819dd1..7d4c3bec889 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationData.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/OperationData.java @@ -2,17 +2,17 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -package com.amazonaws.util.awsclientsmithygenerator.generators.templates; +package com.amazonaws.util.awsclientsmithygenerator.generators; import software.amazon.smithy.model.shapes.*; -import software.amazon.smithy.model.traits.PaginatedTrait; +import software.amazon.smithy.model.traits.Trait; -public class PaginationData { +public class OperationData { private final OperationShape operation; - private final PaginatedTrait trait; + private final T trait; private final ServiceShape service; - public PaginationData(OperationShape operation, PaginatedTrait trait, ServiceShape service) { + public OperationData(OperationShape operation, T trait, ServiceShape service) { this.operation = operation; this.trait = trait; this.service = service; @@ -22,7 +22,7 @@ public OperationShape getOperation() { return operation; } - public PaginatedTrait getTrait() { + public T getTrait() { return trait; } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java index 9d4dd0e6504..9a8cb71c83e 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java @@ -9,7 +9,9 @@ import software.amazon.smithy.model.knowledge.TopDownIndex; import software.amazon.smithy.model.traits.PaginatedTrait; import software.amazon.smithy.model.shapes.*; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import software.amazon.smithy.model.traits.PaginatedTrait; +import com.amazonaws.util.awsclientsmithygenerator.generators.PaginationCompilationTestParser; import java.util.List; import java.util.stream.Collectors; @@ -26,9 +28,9 @@ public void execute(PluginContext context) { for (ServiceShape service : model.getServiceShapes()) { // Find paginated operations using TopDownIndex - List paginatedOps = TopDownIndex.of(model).getContainedOperations(service).stream() + List> paginatedOps = TopDownIndex.of(model).getContainedOperations(service).stream() .filter(op -> op.hasTrait(PaginatedTrait.class)) - .map(op -> new PaginationData(op, op.expectTrait(PaginatedTrait.class), service)) + .map(op -> new OperationData<>(op, op.expectTrait(PaginatedTrait.class), service)) .collect(Collectors.toList()); if (!paginatedOps.isEmpty()) { @@ -37,7 +39,7 @@ public void execute(PluginContext context) { parser.run(); // Generate header compilation test - HeaderCompilationParser headerParser = new HeaderCompilationParser(context, service, paginatedOps); + PaginationCompilationTestParser headerParser = new PaginationCompilationTestParser(context, service, paginatedOps); headerParser.run(); } } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/HeaderCompilationParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCompilationTestParser.java similarity index 70% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/HeaderCompilationParser.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCompilationTestParser.java index 6ca4a65f926..146964ac3a3 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/HeaderCompilationParser.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCompilationTestParser.java @@ -5,23 +5,21 @@ package com.amazonaws.util.awsclientsmithygenerator.generators; import software.amazon.smithy.build.PluginContext; -import software.amazon.smithy.model.Model; import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.aws.traits.ServiceTrait; import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.HeaderCompilationTemplate; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.HeaderCompilationCMakeTemplate; -import com.amazonaws.util.awsclientsmithygenerator.generators.ShapeUtil; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationCompilationTestGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import software.amazon.smithy.model.traits.PaginatedTrait; import java.util.*; -public class HeaderCompilationParser { +public class PaginationCompilationTestParser { private final PluginContext context; private final ServiceShape service; - private final List paginatedOps; + private final List> paginatedOps; private final CppWriterDelegator writerDelegator; - public HeaderCompilationParser(PluginContext context, ServiceShape service, List paginatedOps) { + public PaginationCompilationTestParser(PluginContext context, ServiceShape service, List> paginatedOps) { this.context = context; this.service = service; this.paginatedOps = paginatedOps; @@ -34,14 +32,14 @@ public void run() { writerDelegator.flushWriters(); } - private void generateSingleHeaderCompilationTest(List services, List allPaginatedOps) { + private void generateSingleHeaderCompilationTest(List services, List> allPaginatedOps) { String serviceName = getServiceName(service); String c2jServiceName = getC2jServiceName(service); // Generate single compilation test for all pagination headers in service's client-gen-tests writerDelegator.useFileWriter( - "generated/tests/" + c2jServiceName + "-gen-tests/AllPaginationHeadersCompilationTest.cpp", - writer -> new HeaderCompilationTemplate(services, allPaginatedOps).render(writer) + "generated/tests/" + c2jServiceName + "-gen-tests/" + serviceName + "PaginationCompilationTests.cpp", + writer -> new PaginationCompilationTestGenerator(services, allPaginatedOps).render(writer) ); } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java index 08eb41cdc21..c1c67d9ee06 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java @@ -9,17 +9,18 @@ import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.model.traits.PaginatedTrait; import software.amazon.smithy.aws.traits.ServiceTrait; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import software.amazon.smithy.model.traits.PaginatedTrait; import java.nio.file.*; import java.util.*; public class PaginationHeaderWriter { private final PluginContext context; private final ServiceShape service; - private final List paginatedOps; + private final List> paginatedOps; private final String c2jServiceName; - public PaginationHeaderWriter(PluginContext context, ServiceShape service, List paginatedOps, String c2jServiceName) { + public PaginationHeaderWriter(PluginContext context, ServiceShape service, List> paginatedOps, String c2jServiceName) { this.context = context; this.service = service; this.paginatedOps = paginatedOps; @@ -35,7 +36,7 @@ public void write() { Path outputPath = context.getFileManifest().getBaseDir() .resolve("include/aws/" + c2jServiceName + "/model/pagination"); - for (PaginationData data : paginatedOps) { + for (OperationData data : paginatedOps) { String content = generateTraitsHeader(data, serviceName); String fileName = data.getOperation().getId().getName() + "PaginationTraits.h"; @@ -48,7 +49,7 @@ public void write() { } } - private String generateTraitsHeader(PaginationData data, String serviceName) { + private String generateTraitsHeader(OperationData data, String serviceName) { OperationShape op = data.getOperation(); PaginatedTrait trait = data.getTrait(); String opName = op.getId().getName(); diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java index 98c829628b7..389e2a6669e 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java @@ -11,7 +11,8 @@ import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.aws.traits.ServiceTrait; import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import software.amazon.smithy.model.traits.PaginatedTrait; import com.amazonaws.util.awsclientsmithygenerator.generators.PaginationHeaderWriter; import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationClientTemplate; import java.util.*; @@ -20,11 +21,11 @@ public class PaginationParser { private final PluginContext context; private final Model model; private final ServiceShape service; - private final List paginatedOps; + private final List> paginatedOps; private final CppWriterDelegator writerDelegator; private Map c2jMap; - public PaginationParser(PluginContext context, ServiceShape service, List paginatedOps) { + public PaginationParser(PluginContext context, ServiceShape service, List> paginatedOps) { this.context = context; this.model = context.getModel(); this.service = service; @@ -51,7 +52,7 @@ public void run() { writerDelegator.flushWriters(); } - private void generatePaginationFiles(ServiceShape service, List paginatedOps) { + private void generatePaginationFiles(ServiceShape service, List> paginatedOps) { String serviceName = getServiceName(service); String c2jServiceName = getC2jServiceName(service); diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationCMakeTemplate.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationCMakeTemplate.java deleted file mode 100644 index 598abe29a20..00000000000 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationCMakeTemplate.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -package com.amazonaws.util.awsclientsmithygenerator.generators.templates; - -import software.amazon.smithy.model.shapes.ServiceShape; -import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; - -public class HeaderCompilationCMakeTemplate { - - public HeaderCompilationCMakeTemplate() { - } - - public void render(CppWriter writer) { - String testName = "all-pagination-headers-compilation-test"; - - writer.write("# Header compilation test for all pagination headers") - .write("cmake_minimum_required(VERSION 3.13)") - .write("") - .write("project($L)", testName) - .write("") - .write("find_package(aws-cpp-sdk-core REQUIRED)") - .write("find_package(GTest REQUIRED)") - .write("") - .write("add_executable($L", testName) - .write(" AllPaginationHeadersCompilationTest.cpp") - .write(")") - .write("") - .write("target_link_libraries($L", testName) - .write(" aws-cpp-sdk-core") - .write(" GTest::gtest") - .write(" GTest::gtest_main") - .write(")") - .write("") - .write("target_include_directories($L PRIVATE", testName) - .write(" ${CMAKE_CURRENT_SOURCE_DIR}") - .write(")") - .write("") - .write("add_test(NAME $L COMMAND $L)", testName, testName); - } -} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java index 2338ec5aeec..4b4d41e85b6 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java @@ -5,16 +5,17 @@ package com.amazonaws.util.awsclientsmithygenerator.generators.templates; import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.aws.traits.ServiceTrait; +import software.amazon.smithy.model.traits.PaginatedTrait; import java.util.List; public class PaginationClientTemplate { private final ServiceShape service; - private final List paginatedOps; + private final List> paginatedOps; - public PaginationClientTemplate(ServiceShape service, List paginatedOps) { + public PaginationClientTemplate(ServiceShape service, List> paginatedOps) { this.service = service; this.paginatedOps = paginatedOps; } @@ -38,7 +39,7 @@ private void renderIncludes(CppWriter writer, String serviceName) { writer.writeInclude("aws/" + serviceName.toLowerCase() + "/" + serviceName + "Client.h"); writer.writeInclude("aws/core/utils/pagination/Paginator.h"); - for (PaginationData data : paginatedOps) { + for (OperationData data : paginatedOps) { String opName = data.getOperation().getId().getName(); writer.writeInclude("aws/" + serviceName.toLowerCase() + "/model/pagination/" + opName + "PaginationTraits.h"); } @@ -50,9 +51,9 @@ private void renderNamespaces(CppWriter writer, String serviceName) { writer.writeNamespaceOpen(serviceName); writer.write(""); - for (PaginationData data : paginatedOps) { + for (OperationData data : paginatedOps) { String opName = data.getOperation().getId().getName(); - writer.write("using %sPaginator = Aws::Utils::Pagination::PagePaginator<%sClient, Model::%sRequest, Pagination::%sPaginationTraits>;", + writer.write("using $LPaginator = Aws::Utils::Pagination::PagePaginator<$LClient, Model::$LRequest, Pagination::$LPaginationTraits>;", opName, serviceName, opName, opName); } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationTemplate.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java similarity index 63% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationTemplate.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java index 20e53fb6ff3..4e86c8a6fc2 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/HeaderCompilationTemplate.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java @@ -6,25 +6,28 @@ import software.amazon.smithy.model.shapes.*; import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import software.amazon.smithy.model.traits.PaginatedTrait; import java.util.*; -public class HeaderCompilationTemplate { +public class PaginationCompilationTestGenerator { private final List services; - private final List allPaginatedOps; + private final List> allPaginatedOps; - public HeaderCompilationTemplate(List services, List allPaginatedOps) { + public PaginationCompilationTestGenerator(List services, List> allPaginatedOps) { this.services = services; this.allPaginatedOps = allPaginatedOps; } public void render(CppWriter writer) { + String serviceName = getServiceName(services.get(0)); + writer.write("/**") .write(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.") .write(" * SPDX-License-Identifier: Apache-2.0.") .write(" */") .write("") - .write("// Header compilation test for ALL pagination headers") + .write("// Header compilation test for " + serviceName + " pagination headers") .write("// This test ensures all generated pagination headers compile successfully") .write(""); @@ -33,20 +36,22 @@ public void render(CppWriter writer) { writer.write("") .write("#include ") - .write("") - .write("class AllPaginationHeadersCompilationTest : public Aws::Testing::AwsCppSdkGTestSuite") - .write("{") - .write("};") - .write("") - .write("TEST_F(AllPaginationHeadersCompilationTest, AllPaginationHeadersCompile)") - .write("{") - .write(" // Test passes if compilation succeeds") - .write(" SUCCEED();") - .write("}"); + .write(""); + + writer.openBlock("class " + serviceName + "PaginationCompilationTest : public Aws::Testing::AwsCppSdkGTestSuite\n{", "};", () -> { + // Empty class body + }); + + writer.write(""); + + writer.openBlock("TEST_F(" + serviceName + "PaginationCompilationTest, " + serviceName + "PaginationHeadersCompile)\n{", "}", () -> { + writer.write(" // Test passes if compilation succeeds") + .write(" SUCCEED();"); + }); } private void writeIncludes(CppWriter writer) { - for (PaginationData paginationData : allPaginatedOps) { + for (OperationData paginationData : allPaginatedOps) { ServiceShape service = paginationData.getService(); String serviceName = getServiceName(service); diff --git a/tools/code-generation/smithy/codegen/cpp-pagination/smithy-build.json b/tools/code-generation/smithy/codegen/cpp-pagination/smithy-build.json index a3adf6fee9d..40328dc60a7 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination/smithy-build.json +++ b/tools/code-generation/smithy/codegen/cpp-pagination/smithy-build.json @@ -7,7 +7,17 @@ ], "plugins": { "cpp-codegen-pagination-plugin": { - "c2jMap": "{\"api-gateway\": \"apigateway\", \"application-auto-scaling\": \"application-autoscaling\", \"app-mesh\": \"appmesh\", \"auto-scaling\": \"autoscaling\", \"auto-scaling-plans\": \"autoscaling-plans\", \"cloudhsm-v2\": \"cloudhsmv2\", \"cloudsearch-domain\": \"cloudsearchdomain\", \"config-service\": \"config\", \"cost-and-usage-report-service\": \"cur\", \"data-pipeline\": \"datapipeline\", \"device-farm\": \"devicefarm\", \"direct-connect\": \"directconnect\", \"dynamodb-streams\": \"dynamodbstreams\", \"elastic-beanstalk\": \"elasticbeanstalk\", \"elastic-load-balancing\": \"elasticloadbalancing\", \"elastic-load-balancing-v2\": \"elasticloadbalancingv2\", \"global-accelerator\": \"globalaccelerator\", \"iot-1click-devices-service\": \"iot1click-devices\", \"iot-1click-projects\": \"iot1click-projects\", \"iot-data-plane\": \"iot-data\", \"iot-events-data\": \"iotevents-data\", \"iot-events\": \"iotevents\", \"iot-jobs-data-plane\": \"iot-jobs-data\", \"iot-wireless\": \"iotwireless\", \"kinesis-analytics\": \"kinesisanalytics\", \"kinesis-analytics-v2\": \"kinesisanalyticsv2\", \"kinesis-video\": \"kinesisvideo\", \"lex-models-v2\": \"lexv2-models\", \"lex-runtime-service\": \"lex\", \"lex-runtime-v2\": \"lexv2-runtime\", \"machine-learning\": \"machinelearning\", \"marketplace-commerce-analytics\": \"marketplacecommerceanalytics\", \"marketplace-entitlement-service\": \"marketplace-entitlement\", \"marketplace-metering\": \"meteringmarketplace\", \"migration-hub\": \"AWSMigrationHub\", \"mturk\": \"mturk-requester\", \"pinpoint-sms-voice\": \"sms-voice\", \"resource-groups-tagging-api\": \"resourcegroupstaggingapi\", \"route-53-domains\": \"route53domains\", \"route-53\": \"route53\", \"s3-control\": \"s3control\", \"sagemaker-runtime\": \"sagemaker-runtime\", \"secrets-manager\": \"secretsmanager\", \"serverlessapplicationrepository\": \"serverlessrepo\", \"service-catalog-appregistry\": \"servicecatalog-appregistry\", \"service-catalog\": \"servicecatalog\", \"transfer\": \"awstransfer\", \"cloudwatch\": \"monitoring\", \"cloudwatch-events\": \"events\", \"storage-gateway\": \"storagegateway\", \"efs\": \"elasticfilesystem\", \"emr\": \"elasticmapreduce\", \"ses\": \"email\", \"cognito-identity-provider\": \"cognito-idp\", \"cost-explorer\": \"ce\", \"application-discovery-service\": \"discovery\", \"database-migration-service\": \"dms\", \"sfn\": \"states\", \"lex-model-building-service\": \"lex-models\", \"cloudwatch-logs\": \"logs\", \"directory-service\": \"ds\", \"elasticsearch-service \": \"es\", \"importexport\": \"importexport\", \"sdb\": \"sdb\", \"transcribe-streaming\": \"transcribestreaming\"}" + "c2jMap": "{\"api-gateway\": \"apigateway\", \"application-auto-scaling\": \"application-autoscaling\", \"app-mesh\": \"appmesh\", \"auto-scaling\": \"autoscaling\", \"auto-scaling-plans\": \"autoscaling-plans\", \"cloudhsm-v2\": \"cloudhsmv2\", \"cloudsearch-domain\": \"cloudsearchdomain\", \"config-service\": \"config\", \"cost-and-usage-report-service\": \"cur\", \"data-pipeline\": \"datapipeline\", \"device-farm\": \"devicefarm\", \"direct-connect\": \"directconnect\", \"dynamodb-streams\": \"dynamodbstreams\", \"elastic-beanstalk\": \"elasticbeanstalk\", \"elastic-load-balancing\": \"elasticloadbalancing\", \"elastic-load-balancing-v2\": \"elasticloadbalancingv2\", \"global-accelerator\": \"globalaccelerator\", \"iot-1click-devices-service\": \"iot1click-devices\", \"iot-1click-projects\": \"iot1click-projects\", \"iot-data-plane\": \"iot-data\", \"iot-events-data\": \"iotevents-data\", \"iot-events\": \"iotevents\", \"iot-jobs-data-plane\": \"iot-jobs-data\", \"iot-wireless\": \"iotwireless\", \"kinesis-analytics\": \"kinesisanalytics\", \"kinesis-analytics-v2\": \"kinesisanalyticsv2\", \"kinesis-video\": \"kinesisvideo\", \"lex-models-v2\": \"lexv2-models\", \"lex-runtime-service\": \"lex\", \"lex-runtime-v2\": \"lexv2-runtime\", \"machine-learning\": \"machinelearning\", \"marketplace-commerce-analytics\": \"marketplacecommerceanalytics\", \"marketplace-entitlement-service\": \"marketplace-entitlement\", \"marketplace-metering\": \"meteringmarketplace\", \"migration-hub\": \"AWSMigrationHub\", \"mturk\": \"mturk-requester\", \"pinpoint-sms-voice\": \"sms-voice\", \"resource-groups-tagging-api\": \"resourcegroupstaggingapi\", \"route-53-domains\": \"route53domains\", \"route-53\": \"route53\", \"s3-control\": \"s3control\", \"sagemaker-runtime\": \"sagemaker-runtime\", \"secrets-manager\": \"secretsmanager\", \"serverlessapplicationrepository\": \"serverlessrepo\", \"service-catalog-appregistry\": \"servicecatalog-appregistry\", \"service-catalog\": \"servicecatalog\", \"transfer\": \"awstransfer\", \"cloudwatch\": \"monitoring\", \"cloudwatch-events\": \"events\", \"storage-gateway\": \"storagegateway\", \"efs\": \"elasticfilesystem\", \"emr\": \"elasticmapreduce\", \"ses\": \"email\", \"cognito-identity-provider\": \"cognito-idp\", \"cost-explorer\": \"ce\", \"application-discovery-service\": \"discovery\", \"database-migration-service\": \"dms\", \"sfn\": \"states\", \"lex-model-building-service\": \"lex-models\", \"cloudwatch-logs\": \"logs\", \"directory-service\": \"ds\", \"elasticsearch-service\": \"es\", \"importexport\": \"importexport\", \"sdb\": \"sdb\", \"transcribe-streaming\": \"transcribestreaming\"}" + } + } + }, + "dynamodb.2012-08-10": { + "imports": [ + "/Users/cailinn/Desktop/workspace/aws-sdk-cpp/tools/code-generation/smithy/api-descriptions/dynamodb.json" + ], + "plugins": { + "cpp-codegen-pagination-plugin": { + "c2jMap": "{\"api-gateway\": \"apigateway\", \"application-auto-scaling\": \"application-autoscaling\", \"app-mesh\": \"appmesh\", \"auto-scaling\": \"autoscaling\", \"auto-scaling-plans\": \"autoscaling-plans\", \"cloudhsm-v2\": \"cloudhsmv2\", \"cloudsearch-domain\": \"cloudsearchdomain\", \"config-service\": \"config\", \"cost-and-usage-report-service\": \"cur\", \"data-pipeline\": \"datapipeline\", \"device-farm\": \"devicefarm\", \"direct-connect\": \"directconnect\", \"dynamodb-streams\": \"dynamodbstreams\", \"elastic-beanstalk\": \"elasticbeanstalk\", \"elastic-load-balancing\": \"elasticloadbalancing\", \"elastic-load-balancing-v2\": \"elasticloadbalancingv2\", \"global-accelerator\": \"globalaccelerator\", \"iot-1click-devices-service\": \"iot1click-devices\", \"iot-1click-projects\": \"iot1click-projects\", \"iot-data-plane\": \"iot-data\", \"iot-events-data\": \"iotevents-data\", \"iot-events\": \"iotevents\", \"iot-jobs-data-plane\": \"iot-jobs-data\", \"iot-wireless\": \"iotwireless\", \"kinesis-analytics\": \"kinesisanalytics\", \"kinesis-analytics-v2\": \"kinesisanalyticsv2\", \"kinesis-video\": \"kinesisvideo\", \"lex-models-v2\": \"lexv2-models\", \"lex-runtime-service\": \"lex\", \"lex-runtime-v2\": \"lexv2-runtime\", \"machine-learning\": \"machinelearning\", \"marketplace-commerce-analytics\": \"marketplacecommerceanalytics\", \"marketplace-entitlement-service\": \"marketplace-entitlement\", \"marketplace-metering\": \"meteringmarketplace\", \"migration-hub\": \"AWSMigrationHub\", \"mturk\": \"mturk-requester\", \"pinpoint-sms-voice\": \"sms-voice\", \"resource-groups-tagging-api\": \"resourcegroupstaggingapi\", \"route-53-domains\": \"route53domains\", \"route-53\": \"route53\", \"s3-control\": \"s3control\", \"sagemaker-runtime\": \"sagemaker-runtime\", \"secrets-manager\": \"secretsmanager\", \"serverlessapplicationrepository\": \"serverlessrepo\", \"service-catalog-appregistry\": \"servicecatalog-appregistry\", \"service-catalog\": \"servicecatalog\", \"transfer\": \"awstransfer\", \"cloudwatch\": \"monitoring\", \"cloudwatch-events\": \"events\", \"storage-gateway\": \"storagegateway\", \"efs\": \"elasticfilesystem\", \"emr\": \"elasticmapreduce\", \"ses\": \"email\", \"cognito-identity-provider\": \"cognito-idp\", \"cost-explorer\": \"ce\", \"application-discovery-service\": \"discovery\", \"database-migration-service\": \"dms\", \"sfn\": \"states\", \"lex-model-building-service\": \"lex-models\", \"cloudwatch-logs\": \"logs\", \"directory-service\": \"ds\", \"elasticsearch-service\": \"es\", \"importexport\": \"importexport\", \"sdb\": \"sdb\", \"transcribe-streaming\": \"transcribestreaming\"}" } } } From 7c55bf5cc4fe972aa0b0981861588edd4a91c569 Mon Sep 17 00:00:00 2001 From: kai lin Date: Thu, 15 Jan 2026 16:02:07 -0500 Subject: [PATCH 08/19] changed parsers to be more generic --- ...Parser.java => CompilationTestParser.java} | 30 ++--- .../generators/CppWriter.java | 9 +- ...ginationParser.java => FeatureParser.java} | 42 +++--- .../generators/PaginationCodegenPlugin.java | 30 ++++- .../generators/PaginationHeaderWriter.java | 114 ---------------- ...a => PaginationClientHeaderGenerator.java} | 4 +- .../PaginationCompilationTestGenerator.java | 23 +++- .../templates/PaginationTraitsGenerator.java | 127 ++++++++++++++++++ 8 files changed, 215 insertions(+), 164 deletions(-) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{PaginationCompilationTestParser.java => CompilationTestParser.java} (59%) rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/{PaginationParser.java => FeatureParser.java} (63%) delete mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java rename tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/{PaginationClientTemplate.java => PaginationClientHeaderGenerator.java} (94%) create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCompilationTestParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CompilationTestParser.java similarity index 59% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCompilationTestParser.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CompilationTestParser.java index 146964ac3a3..4d7e1c5821c 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCompilationTestParser.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CompilationTestParser.java @@ -7,42 +7,42 @@ import software.amazon.smithy.build.PluginContext; import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.aws.traits.ServiceTrait; -import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationCompilationTestGenerator; -import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; -import software.amazon.smithy.model.traits.PaginatedTrait; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; import java.util.*; +import java.util.function.Consumer; -public class PaginationCompilationTestParser { +public class CompilationTestParser { private final PluginContext context; private final ServiceShape service; - private final List> paginatedOps; + private final List operations; private final CppWriterDelegator writerDelegator; + private final String testType; + private final Consumer renderFunction; - public PaginationCompilationTestParser(PluginContext context, ServiceShape service, List> paginatedOps) { + public CompilationTestParser(PluginContext context, ServiceShape service, List operations, + String testType, Consumer renderFunction) { this.context = context; this.service = service; - this.paginatedOps = paginatedOps; + this.operations = operations; this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); + this.testType = testType; + this.renderFunction = renderFunction; } public void run() { - List services = List.of(service); - generateSingleHeaderCompilationTest(services, paginatedOps); + generateCompilationTest(); writerDelegator.flushWriters(); } - private void generateSingleHeaderCompilationTest(List services, List> allPaginatedOps) { + private void generateCompilationTest() { String serviceName = getServiceName(service); String c2jServiceName = getC2jServiceName(service); - // Generate single compilation test for all pagination headers in service's client-gen-tests writerDelegator.useFileWriter( - "generated/tests/" + c2jServiceName + "-gen-tests/" + serviceName + "PaginationCompilationTests.cpp", - writer -> new PaginationCompilationTestGenerator(services, allPaginatedOps).render(writer) + "generated/tests/" + c2jServiceName + "-gen-tests/" + serviceName + testType + "CompilationTests.cpp", + renderFunction ); } - private String getServiceName(ServiceShape service) { return service.getTrait(ServiceTrait.class) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java index 950e772d793..bf1ad4ffc53 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java @@ -28,15 +28,18 @@ public CppWriter() { }); } - public void writeInclude(String header) { + public CppWriter writeInclude(String header) { write("#include <$L>", header); + return this; } - public void writeNamespaceOpen(String namespace) { + public CppWriter writeNamespaceOpen(String namespace) { write("namespace $L\n{", namespace); + return this; } - public void writeNamespaceClose(String namespace) { + public CppWriter writeNamespaceClose(String namespace) { write("} // namespace $L", namespace); + return this; } } \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java similarity index 63% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java index 389e2a6669e..53d2938e245 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationParser.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java @@ -10,26 +10,24 @@ import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.aws.traits.ServiceTrait; -import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; -import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; -import software.amazon.smithy.model.traits.PaginatedTrait; -import com.amazonaws.util.awsclientsmithygenerator.generators.PaginationHeaderWriter; -import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationClientTemplate; import java.util.*; +import java.util.function.Consumer; -public class PaginationParser { +public class FeatureParser { private final PluginContext context; private final Model model; private final ServiceShape service; - private final List> paginatedOps; + private final List operations; private final CppWriterDelegator writerDelegator; - private Map c2jMap; + private final Map c2jMap; + private final String featureName; - public PaginationParser(PluginContext context, ServiceShape service, List> paginatedOps) { + public FeatureParser(PluginContext context, ServiceShape service, List operations, String featureName) { this.context = context; this.model = context.getModel(); this.service = service; - this.paginatedOps = paginatedOps; + this.operations = operations; + this.featureName = featureName; this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); // Initialize c2j map @@ -47,26 +45,28 @@ public PaginationParser(PluginContext context, ServiceShape service, List> generationLogic) { + generationLogic.accept(this); writerDelegator.flushWriters(); } - private void generatePaginationFiles(ServiceShape service, List> paginatedOps) { + public void generateClientHeader(String fileName, Consumer generator) { String serviceName = getServiceName(service); String c2jServiceName = getC2jServiceName(service); - // Generate client pagination header writerDelegator.useFileWriter( - "include/aws/" + c2jServiceName + "/" + serviceName + "ClientPagination.h", - writer -> new PaginationClientTemplate(service, paginatedOps).render(writer) + "include/aws/" + c2jServiceName + "/" + fileName, + generator ); - - // Generate pagination traits headers - PaginationHeaderWriter headerWriter = new PaginationHeaderWriter(context, service, paginatedOps, c2jServiceName); - headerWriter.write(); } + public PluginContext getContext() { return context; } + public ServiceShape getService() { return service; } + public List getOperations() { return operations; } + public String getFeatureName() { return featureName; } + public String getServiceName() { return getServiceName(service); } + public String getC2jServiceName() { return getC2jServiceName(service); } + private String getServiceName(ServiceShape service) { return service.getTrait(ServiceTrait.class) .map(ServiceTrait::getSdkId) @@ -85,4 +85,4 @@ private String getC2jServiceName(ServiceShape service) { return c2jMap.getOrDefault(sdkId, sdkId); } -} +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java index 9a8cb71c83e..1681570a7a7 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java @@ -10,8 +10,11 @@ import software.amazon.smithy.model.traits.PaginatedTrait; import software.amazon.smithy.model.shapes.*; import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.FeatureParser; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationTraitsGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationClientHeaderGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationCompilationTestGenerator; import software.amazon.smithy.model.traits.PaginatedTrait; -import com.amazonaws.util.awsclientsmithygenerator.generators.PaginationCompilationTestParser; import java.util.List; import java.util.stream.Collectors; @@ -35,12 +38,29 @@ public void execute(PluginContext context) { if (!paginatedOps.isEmpty()) { // Generate pagination files - PaginationParser parser = new PaginationParser(context, service, paginatedOps); - parser.run(); + FeatureParser> parser = new FeatureParser<>(context, service, paginatedOps, "Pagination"); + parser.run(featureParser -> { + String serviceName = featureParser.getServiceName(); + + // Generate client pagination header + featureParser.generateClientHeader( + serviceName + "ClientPagination.h", + writer -> new PaginationClientHeaderGenerator(featureParser.getService(), featureParser.getOperations()).render(writer) + ); + + // Generate pagination traits headers + PaginationTraitsGenerator headerWriter = new PaginationTraitsGenerator( + featureParser.getContext(), + featureParser.getService(), + featureParser.getOperations(), + featureParser.getC2jServiceName() + ); + headerWriter.write(); + }); // Generate header compilation test - PaginationCompilationTestParser headerParser = new PaginationCompilationTestParser(context, service, paginatedOps); - headerParser.run(); + PaginationCompilationTestGenerator headerGenerator = new PaginationCompilationTestGenerator(context, service, paginatedOps); + headerGenerator.run(); } } } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java deleted file mode 100644 index c1c67d9ee06..00000000000 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationHeaderWriter.java +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -package com.amazonaws.util.awsclientsmithygenerator.generators; - -import software.amazon.smithy.build.PluginContext; -import software.amazon.smithy.codegen.core.SymbolProvider; -import software.amazon.smithy.model.shapes.*; -import software.amazon.smithy.model.traits.PaginatedTrait; -import software.amazon.smithy.aws.traits.ServiceTrait; -import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; -import software.amazon.smithy.model.traits.PaginatedTrait; -import java.nio.file.*; -import java.util.*; - -public class PaginationHeaderWriter { - private final PluginContext context; - private final ServiceShape service; - private final List> paginatedOps; - private final String c2jServiceName; - - public PaginationHeaderWriter(PluginContext context, ServiceShape service, List> paginatedOps, String c2jServiceName) { - this.context = context; - this.service = service; - this.paginatedOps = paginatedOps; - this.c2jServiceName = c2jServiceName; - } - - public void write() { - String serviceName = service.getTrait(ServiceTrait.class) - .map(ServiceTrait::getSdkId) - .orElse(service.getId().getName()) - .replace(" ", "") - .replace("-", ""); - Path outputPath = context.getFileManifest().getBaseDir() - .resolve("include/aws/" + c2jServiceName + "/model/pagination"); - - for (OperationData data : paginatedOps) { - String content = generateTraitsHeader(data, serviceName); - String fileName = data.getOperation().getId().getName() + "PaginationTraits.h"; - - try { - Files.createDirectories(outputPath); - Files.writeString(outputPath.resolve(fileName), content); - } catch (Exception e) { - throw new RuntimeException("Failed to write pagination traits header", e); - } - } - } - - private String generateTraitsHeader(OperationData data, String serviceName) { - OperationShape op = data.getOperation(); - PaginatedTrait trait = data.getTrait(); - String opName = op.getId().getName(); - - StringBuilder sb = new StringBuilder(); - sb.append("/**\n"); - sb.append(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n"); - sb.append(" * SPDX-License-Identifier: Apache-2.0.\n"); - sb.append(" */\n\n"); - sb.append("#pragma once\n"); - sb.append("#include \n"); - sb.append("#include \n"); - sb.append("#include \n"); - sb.append("#include \n\n"); - sb.append("namespace Aws\n{\nnamespace ").append(serviceName).append("\n{\nnamespace Pagination\n{\n\n"); - sb.append("struct ").append(opName).append("PaginationTraits\n{\n"); - sb.append(" using RequestType = Model::").append(opName).append("Request;\n"); - sb.append(" using ResultType = Model::").append(opName).append("Result;\n"); - sb.append(" using OutcomeType = Model::").append(opName).append("Outcome;\n"); - sb.append(" using ClientType = ").append(serviceName).append("Client;\n\n"); - - sb.append(" static OutcomeType Invoke(ClientType& client, const RequestType& request)\n {\n"); - sb.append(" return client.").append(opName).append("(request);\n }\n\n"); - - sb.append(" static bool HasMoreResults(const ResultType& result)\n {\n"); - // Use the output token to determine if there are more results - if (trait.getOutputToken().isPresent()) { - String outToken = trait.getOutputToken().get(); - // Handle different token types - strings use .empty(), numbers check for non-zero - if (outToken.toLowerCase().contains("marker") || outToken.toLowerCase().contains("number")) { - // Numeric tokens - check if they exist/are set - sb.append(" return result.Get").append(capitalize(outToken)).append("() != 0;\n"); - } else { - // String tokens - check if not empty - sb.append(" return !result.Get").append(capitalize(outToken)).append("().empty();\n"); - } - } else { - // Fallback to checking for IsTruncated if no output token - sb.append(" return result.GetIsTruncated();\n"); - } - sb.append(" }\n\n"); - - sb.append(" static void SetNextRequest(const ResultType& result, RequestType& request)\n {\n"); - if (trait.getInputToken().isPresent() && trait.getOutputToken().isPresent()) { - String inToken = trait.getInputToken().get(); - String outToken = trait.getOutputToken().get(); - sb.append(" request.Set").append(capitalize(inToken)).append("(result.Get").append(capitalize(outToken)).append("());\n"); - } - sb.append(" }\n"); - - sb.append("};\n\n"); - sb.append("} // namespace Pagination\n"); - sb.append("} // namespace ").append(serviceName).append("\n"); - sb.append("} // namespace Aws\n"); - - return sb.toString(); - } - - private String capitalize(String str) { - return str.substring(0, 1).toUpperCase() + str.substring(1); - } -} diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientHeaderGenerator.java similarity index 94% rename from tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java rename to tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientHeaderGenerator.java index 4b4d41e85b6..ff00f56872f 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientTemplate.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientHeaderGenerator.java @@ -11,11 +11,11 @@ import software.amazon.smithy.model.traits.PaginatedTrait; import java.util.List; -public class PaginationClientTemplate { +public class PaginationClientHeaderGenerator { private final ServiceShape service; private final List> paginatedOps; - public PaginationClientTemplate(ServiceShape service, List> paginatedOps) { + public PaginationClientHeaderGenerator(ServiceShape service, List> paginatedOps) { this.service = service; this.paginatedOps = paginatedOps; } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java index 4e86c8a6fc2..155d2bcdac2 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java @@ -4,23 +4,37 @@ */ package com.amazonaws.util.awsclientsmithygenerator.generators.templates; +import software.amazon.smithy.build.PluginContext; import software.amazon.smithy.model.shapes.*; import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.CompilationTestParser; import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; import software.amazon.smithy.model.traits.PaginatedTrait; import java.util.*; public class PaginationCompilationTestGenerator { - private final List services; + private final CompilationTestParser> parser; private final List> allPaginatedOps; - public PaginationCompilationTestGenerator(List services, List> allPaginatedOps) { - this.services = services; + public PaginationCompilationTestGenerator(PluginContext context, ServiceShape service, List> allPaginatedOps) { this.allPaginatedOps = allPaginatedOps; + this.parser = new CompilationTestParser<>( + context, + service, + allPaginatedOps, + "Pagination", + this::render + ); + } + + public void run() { + parser.run(); } public void render(CppWriter writer) { - String serviceName = getServiceName(services.get(0)); + // Get service from the first operation since all operations belong to the same service + ServiceShape service = allPaginatedOps.get(0).getService(); + String serviceName = getServiceName(service); writer.write("/**") .write(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.") @@ -72,4 +86,5 @@ private String getServiceName(ServiceShape service) { .replace("-", ""); } + } \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java new file mode 100644 index 00000000000..d90314a75e0 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java @@ -0,0 +1,127 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.templates; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.codegen.core.SymbolProvider; +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.model.traits.PaginatedTrait; +import software.amazon.smithy.aws.traits.ServiceTrait; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; +import java.util.*; + +public class PaginationTraitsGenerator { + private final PluginContext context; + private final ServiceShape service; + private final List> paginatedOps; + private final String c2jServiceName; + + private final CppWriterDelegator writerDelegator; + + public PaginationTraitsGenerator(PluginContext context, ServiceShape service, List> paginatedOps, String c2jServiceName) { + this.context = context; + this.service = service; + this.paginatedOps = paginatedOps; + this.c2jServiceName = c2jServiceName; + this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); + } + + public void write() { + String serviceName = service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .replace(" ", "") + .replace("-", ""); + + for (OperationData data : paginatedOps) { + String fileName = "include/aws/" + c2jServiceName + "/model/pagination/" + data.getOperation().getId().getName() + "PaginationTraits.h"; + + writerDelegator.useFileWriter(fileName, writer -> { + generateTraitsHeader(writer, data, serviceName); + }); + } + + writerDelegator.flushWriters(); + } + + private void generateTraitsHeader(CppWriter writer, OperationData data, String serviceName) { + OperationShape op = data.getOperation(); + PaginatedTrait trait = data.getTrait(); + String opName = op.getId().getName(); + + // Header comment + writer.write("/**") + .write(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.") + .write(" * SPDX-License-Identifier: Apache-2.0.") + .write(" */") + .write("") + .write("#pragma once"); + + // Includes + writer.writeInclude("aws/" + c2jServiceName + "/" + serviceName + "_EXPORTS.h") + .writeInclude("aws/" + c2jServiceName + "/model/" + opName + "Request.h") + .writeInclude("aws/" + c2jServiceName + "/model/" + opName + "Result.h") + .writeInclude("aws/" + c2jServiceName + "/" + serviceName + "Client.h") + .write(""); + + // Namespaces + writer.writeNamespaceOpen("Aws") + .writeNamespaceOpen(serviceName) + .writeNamespaceOpen("Pagination") + .write(""); + + // Struct definition + writer.openBlock("struct " + opName + "PaginationTraits\n{", "};", () -> { + writer.write(" using RequestType = Model::$LRequest;", opName) + .write(" using ResultType = Model::$LResult;", opName) + .write(" using OutcomeType = Model::$LOutcome;", opName) + .write(" using ClientType = $LClient;", serviceName) + .write(""); + + // Invoke method + writer.openBlock(" static OutcomeType Invoke(ClientType& client, const RequestType& request)\n {", " }", () -> { + writer.write(" return client.$L(request);", opName); + }); + + writer.write(""); + + // HasMoreResults method + writer.openBlock(" static bool HasMoreResults(const ResultType& result)\n {", " }", () -> { + if (trait.getOutputToken().isPresent()) { + String outToken = trait.getOutputToken().get(); + if (outToken.toLowerCase().contains("marker") || outToken.toLowerCase().contains("number")) { + writer.write(" return result.Get$L() != 0;", capitalize(outToken)); + } else { + writer.write(" return !result.Get$L().empty();", capitalize(outToken)); + } + } else { + writer.write(" return result.GetIsTruncated();"); + } + }); + + writer.write(""); + + // SetNextRequest method + writer.openBlock(" static void SetNextRequest(const ResultType& result, RequestType& request)\n {", " }", () -> { + if (trait.getInputToken().isPresent() && trait.getOutputToken().isPresent()) { + String inToken = trait.getInputToken().get(); + String outToken = trait.getOutputToken().get(); + writer.write(" request.Set$L(result.Get$L());", capitalize(inToken), capitalize(outToken)); + } + }); + }); + + writer.write("") + .writeNamespaceClose("Pagination") + .writeNamespaceClose(serviceName) + .writeNamespaceClose("Aws"); + } + + private String capitalize(String str) { + return str.substring(0, 1).toUpperCase() + str.substring(1); + } +} From 6b2953452dd6ef9abbfe5ba5d6bb73f50895ac34 Mon Sep 17 00:00:00 2001 From: kai lin Date: Thu, 15 Jan 2026 16:50:21 -0500 Subject: [PATCH 09/19] added service name util --- .../S3PaginationCompilationTests.cpp | 5 +-- .../generators/CompilationTestParser.java | 30 +++---------- .../generators/FeatureParser.java | 31 +++---------- .../generators/PaginationCodegenPlugin.java | 13 +++--- .../generators/ServiceNameUtil.java | 31 +++++++++++++ .../PaginationClientHeaderGenerator.java | 25 +++++------ .../PaginationCompilationTestGenerator.java | 44 +++++++++++-------- .../templates/PaginationTraitsGenerator.java | 8 +--- 8 files changed, 88 insertions(+), 99 deletions(-) create mode 100644 tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java diff --git a/generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp b/generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp index 0fa4ac48c38..9ea1602aebc 100644 --- a/generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp +++ b/generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp @@ -8,12 +8,9 @@ #include #include -#include #include -#include -#include -#include #include +#include #include diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CompilationTestParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CompilationTestParser.java index 4d7e1c5821c..afcaac07d93 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CompilationTestParser.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CompilationTestParser.java @@ -8,25 +8,24 @@ import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.aws.traits.ServiceTrait; import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; import java.util.*; import java.util.function.Consumer; public class CompilationTestParser { - private final PluginContext context; private final ServiceShape service; - private final List operations; private final CppWriterDelegator writerDelegator; private final String testType; private final Consumer renderFunction; + private final Map c2jMap; public CompilationTestParser(PluginContext context, ServiceShape service, List operations, - String testType, Consumer renderFunction) { - this.context = context; + String testType, Consumer renderFunction, Map c2jMap) { this.service = service; - this.operations = operations; this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); this.testType = testType; this.renderFunction = renderFunction; + this.c2jMap = c2jMap; } public void run() { @@ -35,29 +34,12 @@ public void run() { } private void generateCompilationTest() { - String serviceName = getServiceName(service); - String c2jServiceName = getC2jServiceName(service); + String serviceName = ServiceNameUtil.getServiceName(service); + String c2jServiceName = ServiceNameUtil.getC2jServiceName(service, c2jMap); writerDelegator.useFileWriter( "generated/tests/" + c2jServiceName + "-gen-tests/" + serviceName + testType + "CompilationTests.cpp", renderFunction ); } - - private String getServiceName(ServiceShape service) { - return service.getTrait(ServiceTrait.class) - .map(ServiceTrait::getSdkId) - .orElse(service.getId().getName()) - .replace(" ", "") - .replace("-", ""); - } - - private String getC2jServiceName(ServiceShape service) { - return service.getTrait(ServiceTrait.class) - .map(ServiceTrait::getSdkId) - .orElse(service.getId().getName()) - .trim() - .toLowerCase() - .replace(" ", "-"); - } } \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java index 53d2938e245..4d70ac642ef 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java @@ -5,7 +5,6 @@ package com.amazonaws.util.awsclientsmithygenerator.generators; import software.amazon.smithy.build.PluginContext; -import software.amazon.smithy.model.Model; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.shapes.*; @@ -15,7 +14,6 @@ public class FeatureParser { private final PluginContext context; - private final Model model; private final ServiceShape service; private final List operations; private final CppWriterDelegator writerDelegator; @@ -24,7 +22,6 @@ public class FeatureParser { public FeatureParser(PluginContext context, ServiceShape service, List operations, String featureName) { this.context = context; - this.model = context.getModel(); this.service = service; this.operations = operations; this.featureName = featureName; @@ -51,8 +48,8 @@ public void run(Consumer> generationLogic) { } public void generateClientHeader(String fileName, Consumer generator) { - String serviceName = getServiceName(service); - String c2jServiceName = getC2jServiceName(service); + String serviceName = ServiceNameUtil.getServiceName(service); + String c2jServiceName = ServiceNameUtil.getC2jServiceName(service, c2jMap); writerDelegator.useFileWriter( "include/aws/" + c2jServiceName + "/" + fileName, @@ -64,25 +61,7 @@ public void generateClientHeader(String fileName, Consumer generator) public ServiceShape getService() { return service; } public List getOperations() { return operations; } public String getFeatureName() { return featureName; } - public String getServiceName() { return getServiceName(service); } - public String getC2jServiceName() { return getC2jServiceName(service); } - - private String getServiceName(ServiceShape service) { - return service.getTrait(ServiceTrait.class) - .map(ServiceTrait::getSdkId) - .orElse(service.getId().getName()) - .replace(" ", "") - .replace("-", ""); - } - - private String getC2jServiceName(ServiceShape service) { - String sdkId = service.getTrait(ServiceTrait.class) - .map(ServiceTrait::getSdkId) - .orElse(service.getId().getName()) - .trim() - .toLowerCase() - .replace(" ", "-"); - - return c2jMap.getOrDefault(sdkId, sdkId); - } + public Map getC2jMap() { return c2jMap; } + public String getServiceName() { return ServiceNameUtil.getServiceName(service); } + public String getC2jServiceName() { return ServiceNameUtil.getC2jServiceName(service, c2jMap); } } \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java index 1681570a7a7..156bf97a7a3 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java @@ -14,7 +14,6 @@ import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationTraitsGenerator; import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationClientHeaderGenerator; import com.amazonaws.util.awsclientsmithygenerator.generators.templates.PaginationCompilationTestGenerator; -import software.amazon.smithy.model.traits.PaginatedTrait; import java.util.List; import java.util.stream.Collectors; @@ -45,22 +44,22 @@ public void execute(PluginContext context) { // Generate client pagination header featureParser.generateClientHeader( serviceName + "ClientPagination.h", - writer -> new PaginationClientHeaderGenerator(featureParser.getService(), featureParser.getOperations()).render(writer) + writer -> new PaginationClientHeaderGenerator(featureParser.getService(), featureParser.getOperations(), featureParser.getC2jMap()).render(writer) ); // Generate pagination traits headers - PaginationTraitsGenerator headerWriter = new PaginationTraitsGenerator( + PaginationTraitsGenerator traitsGenerator = new PaginationTraitsGenerator( featureParser.getContext(), featureParser.getService(), featureParser.getOperations(), featureParser.getC2jServiceName() ); - headerWriter.write(); + traitsGenerator.write(); }); - // Generate header compilation test - PaginationCompilationTestGenerator headerGenerator = new PaginationCompilationTestGenerator(context, service, paginatedOps); - headerGenerator.run(); + // Generate compilation test + PaginationCompilationTestGenerator testGenerator = new PaginationCompilationTestGenerator(context, service, paginatedOps, parser.getC2jMap()); + testGenerator.run(); } } } diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java new file mode 100644 index 00000000000..2eb603adca3 --- /dev/null +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java @@ -0,0 +1,31 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.aws.traits.ServiceTrait; +import java.util.Map; + +public final class ServiceNameUtil { + + public static String getServiceName(ServiceShape service) { + return service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .replace(" ", "") + .replace("-", ""); + } + + public static String getC2jServiceName(ServiceShape service, Map c2jMap) { + String sdkId = service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .trim() + .toLowerCase() + .replace(" ", "-"); + + return c2jMap != null ? c2jMap.getOrDefault(sdkId, sdkId) : sdkId; + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientHeaderGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientHeaderGenerator.java index ff00f56872f..e8d38763739 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientHeaderGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationClientHeaderGenerator.java @@ -9,19 +9,24 @@ import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.aws.traits.ServiceTrait; import software.amazon.smithy.model.traits.PaginatedTrait; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; import java.util.List; +import java.util.Map; public class PaginationClientHeaderGenerator { private final ServiceShape service; private final List> paginatedOps; + private final Map c2jMap; - public PaginationClientHeaderGenerator(ServiceShape service, List> paginatedOps) { + public PaginationClientHeaderGenerator(ServiceShape service, List> paginatedOps, Map c2jMap) { this.service = service; this.paginatedOps = paginatedOps; + this.c2jMap = c2jMap; } public void render(CppWriter writer) { - String serviceName = getServiceName(); + String serviceName = ServiceNameUtil.getServiceName(service); + String c2jServiceName = ServiceNameUtil.getC2jServiceName(service, c2jMap); // Header and includes writer.write("/**"); @@ -31,17 +36,17 @@ public void render(CppWriter writer) { writer.write(""); writer.write("#pragma once"); - renderIncludes(writer, serviceName); + renderIncludes(writer, serviceName, c2jServiceName); renderNamespaces(writer, serviceName); } - private void renderIncludes(CppWriter writer, String serviceName) { - writer.writeInclude("aws/" + serviceName.toLowerCase() + "/" + serviceName + "Client.h"); + private void renderIncludes(CppWriter writer, String serviceName, String c2jServiceName) { + writer.writeInclude("aws/" + c2jServiceName + "/" + serviceName + "Client.h"); writer.writeInclude("aws/core/utils/pagination/Paginator.h"); for (OperationData data : paginatedOps) { String opName = data.getOperation().getId().getName(); - writer.writeInclude("aws/" + serviceName.toLowerCase() + "/model/pagination/" + opName + "PaginationTraits.h"); + writer.writeInclude("aws/" + c2jServiceName + "/model/pagination/" + opName + "PaginationTraits.h"); } writer.write(""); } @@ -61,12 +66,4 @@ private void renderNamespaces(CppWriter writer, String serviceName) { writer.writeNamespaceClose(serviceName); writer.writeNamespaceClose("Aws"); } - - private String getServiceName() { - return service.getTrait(ServiceTrait.class) - .map(ServiceTrait::getSdkId) - .orElse(service.getId().getName()) - .replace(" ", "") - .replace("-", ""); - } } \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java index 155d2bcdac2..69c7ee22dc1 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationCompilationTestGenerator.java @@ -9,21 +9,25 @@ import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; import com.amazonaws.util.awsclientsmithygenerator.generators.CompilationTestParser; import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; import software.amazon.smithy.model.traits.PaginatedTrait; import java.util.*; public class PaginationCompilationTestGenerator { private final CompilationTestParser> parser; private final List> allPaginatedOps; + private final Map c2jMap; - public PaginationCompilationTestGenerator(PluginContext context, ServiceShape service, List> allPaginatedOps) { + public PaginationCompilationTestGenerator(PluginContext context, ServiceShape service, List> allPaginatedOps, Map c2jMap) { this.allPaginatedOps = allPaginatedOps; + this.c2jMap = c2jMap; this.parser = new CompilationTestParser<>( context, service, allPaginatedOps, "Pagination", - this::render + this::render, + c2jMap ); } @@ -34,7 +38,7 @@ public void run() { public void render(CppWriter writer) { // Get service from the first operation since all operations belong to the same service ServiceShape service = allPaginatedOps.get(0).getService(); - String serviceName = getServiceName(service); + String serviceName = ServiceNameUtil.getServiceName(service); writer.write("/**") .write(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.") @@ -65,26 +69,30 @@ public void render(CppWriter writer) { } private void writeIncludes(CppWriter writer) { + Set clientHeaders = new HashSet<>(); + Set traitHeaders = new HashSet<>(); + for (OperationData paginationData : allPaginatedOps) { ServiceShape service = paginationData.getService(); - String serviceName = getServiceName(service); + String serviceName = ServiceNameUtil.getServiceName(service); + String c2jServiceName = ServiceNameUtil.getC2jServiceName(service, c2jMap); - // Include pagination client header - writer.writeInclude("aws/" + serviceName.toLowerCase() + "/" + serviceName + "ClientPagination.h"); + // Collect unique client headers + clientHeaders.add("aws/" + c2jServiceName + "/" + serviceName + "ClientPagination.h"); - // Include pagination traits headers + // Collect unique trait headers String operationName = paginationData.getOperation().getId().getName(); - writer.writeInclude("aws/" + serviceName.toLowerCase() + "/model/pagination/" + operationName + "PaginationTraits.h"); + traitHeaders.add("aws/" + c2jServiceName + "/model/pagination/" + operationName + "PaginationTraits.h"); + } + + // Write unique client headers + for (String header : clientHeaders) { + writer.writeInclude(header); + } + + // Write unique trait headers + for (String header : traitHeaders) { + writer.writeInclude(header); } } - - private String getServiceName(ServiceShape service) { - return service.getTrait(software.amazon.smithy.aws.traits.ServiceTrait.class) - .map(software.amazon.smithy.aws.traits.ServiceTrait::getSdkId) - .orElse(service.getId().getName()) - .replace(" ", "") - .replace("-", ""); - } - - } \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java index d90314a75e0..e00baff6d8b 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java @@ -5,13 +5,13 @@ package com.amazonaws.util.awsclientsmithygenerator.generators.templates; import software.amazon.smithy.build.PluginContext; -import software.amazon.smithy.codegen.core.SymbolProvider; import software.amazon.smithy.model.shapes.*; import software.amazon.smithy.model.traits.PaginatedTrait; import software.amazon.smithy.aws.traits.ServiceTrait; import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; import java.util.*; public class PaginationTraitsGenerator { @@ -31,11 +31,7 @@ public PaginationTraitsGenerator(PluginContext context, ServiceShape service, Li } public void write() { - String serviceName = service.getTrait(ServiceTrait.class) - .map(ServiceTrait::getSdkId) - .orElse(service.getId().getName()) - .replace(" ", "") - .replace("-", ""); + String serviceName = ServiceNameUtil.getServiceName(service); for (OperationData data : paginatedOps) { String fileName = "include/aws/" + c2jServiceName + "/model/pagination/" + data.getOperation().getId().getName() + "PaginationTraits.h"; From 6084c35c4f940f887ad36245b9e8cfd560883759 Mon Sep 17 00:00:00 2001 From: kai lin Date: Thu, 15 Jan 2026 17:55:19 -0500 Subject: [PATCH 10/19] filter out deprecated service --- .../generators/PaginationCodegenPlugin.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java index 156bf97a7a3..bd64ffd5c9a 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/PaginationCodegenPlugin.java @@ -8,6 +8,7 @@ import software.amazon.smithy.build.SmithyBuildPlugin; import software.amazon.smithy.model.knowledge.TopDownIndex; import software.amazon.smithy.model.traits.PaginatedTrait; +import software.amazon.smithy.model.traits.DeprecatedTrait; import software.amazon.smithy.model.shapes.*; import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; import com.amazonaws.util.awsclientsmithygenerator.generators.FeatureParser; @@ -29,9 +30,10 @@ public void execute(PluginContext context) { var model = context.getModel(); for (ServiceShape service : model.getServiceShapes()) { - // Find paginated operations using TopDownIndex + // Find paginated operations using TopDownIndex, excluding deprecated operations List> paginatedOps = TopDownIndex.of(model).getContainedOperations(service).stream() .filter(op -> op.hasTrait(PaginatedTrait.class)) + .filter(op -> !op.hasTrait(DeprecatedTrait.class)) .map(op -> new OperationData<>(op, op.expectTrait(PaginatedTrait.class), service)) .collect(Collectors.toList()); From 6ef01e7be77bd63797a6946c1911b231a9f051d6 Mon Sep 17 00:00:00 2001 From: kai lin Date: Fri, 16 Jan 2026 15:20:46 -0500 Subject: [PATCH 11/19] edgecases for backwards compatibility --- .../generators/ServiceNameUtil.java | 30 +++++++++++++++++++ .../templates/PaginationTraitsGenerator.java | 24 +++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java index 2eb603adca3..e9f92b9ac54 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java @@ -6,11 +6,41 @@ import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.aws.traits.ServiceTrait; +import software.amazon.smithy.model.traits.TitleTrait; import java.util.Map; +import java.util.Set; public final class ServiceNameUtil { + // Legacy service IDs that need special handling to match what the legacy c2j code generator produced + // This logic is copied from C2jModelToGeneratorModelTransformer.convertMetadata() method + private static final Set LEGACY_SERVICE_IDS = Set.of( + "amp", "appintegrations", "amazonappintegrationservice", "billingconductor", "clouddirectory", "cloudfront", + "cloudsearch", "cloudsearchdomain", "codeartifact", "codestar-notifications", + "config", "databrew", "ec2", "elasticache", "emr-containers", + "entitlement.marketplace", "events", "evidently", "forecast", "forecastquery", + "grafana", "importexport", "inspector", "lambda", "location", "lookoutvision", + "m2", "migrationhubstrategy", "mobile", "mobileanalytics", "mq", "nimble", + "opensearch", "rbin", "rds-data", "redshift-data", "resiliencehub", "rum", + "sagemaker-a2i-runtime", "sagemaker-edge", "schemas", "sdb", "transcribe", + "transcribe-streaming", "wisdom", "lex", "lexv2-runtime", "lexv2-models", + "marketplace-entitlement", "sagemaker-runtime", "awstransfer", "transcribestreaming", + "dynamodbstreams" + ); + public static String getServiceName(ServiceShape service) { + String serviceName = service.getId().getName().toLowerCase(); + if (LEGACY_SERVICE_IDS.contains(serviceName)) { + // For legacy services, use title trait which includes "Service" suffix + String title = service.getTrait(TitleTrait.class) + .map(TitleTrait::getValue) + .orElse(null); + if (title != null) { + return title.replace(" ", "").replace("-", "").replace("Amazon", "").replace("AWS", ""); + } + } + + // For new services or legacy without title, use serviceId trait return service.getTrait(ServiceTrait.class) .map(ServiceTrait::getSdkId) .orElse(service.getId().getName()) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java index e00baff6d8b..ffe24b749a4 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java @@ -13,6 +13,7 @@ import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; import java.util.*; +import java.util.Arrays; public class PaginationTraitsGenerator { private final PluginContext context; @@ -57,10 +58,11 @@ private void generateTraitsHeader(CppWriter writer, OperationData { + // Use detected suffix to match C2J renameShape logic writer.write(" using RequestType = Model::$LRequest;", opName) - .write(" using ResultType = Model::$LResult;", opName) + .write(" using ResultType = Model::$L$L;", opName, resultSuffix) .write(" using OutcomeType = Model::$LOutcome;", opName) .write(" using ClientType = $LClient;", serviceName) .write(""); @@ -117,6 +120,21 @@ private void generateTraitsHeader(CppWriter writer, OperationData Date: Fri, 16 Jan 2026 15:25:32 -0500 Subject: [PATCH 12/19] edgecases for backwards compatibility --- .../generators/templates/PaginationTraitsGenerator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java index ffe24b749a4..d4470b62b13 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java @@ -120,6 +120,8 @@ private void generateTraitsHeader(CppWriter writer, OperationData Date: Fri, 16 Jan 2026 16:50:26 -0500 Subject: [PATCH 13/19] temporary fix for AccessAnalyzer which uses service-level pagination config --- .../generators/CppWriter.java | 4 +- .../templates/PaginationTraitsGenerator.java | 64 ++++++++++++++++++- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java index bf1ad4ffc53..d3729c6223e 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java @@ -34,12 +34,12 @@ public CppWriter writeInclude(String header) { } public CppWriter writeNamespaceOpen(String namespace) { - write("namespace $L\n{", namespace); + openBlock("namespace $L\n{", namespace); return this; } public CppWriter writeNamespaceClose(String namespace) { - write("} // namespace $L", namespace); + closeBlock("} // namespace $L", namespace); return this; } } \ No newline at end of file diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java index d4470b62b13..b7b4469992d 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java @@ -98,7 +98,21 @@ private void generateTraitsHeader(CppWriter writer, OperationData { + String inToken = null; + String outToken = null; + if (trait.getInputToken().isPresent() && trait.getOutputToken().isPresent()) { - String inToken = trait.getInputToken().get(); - String outToken = trait.getOutputToken().get(); + inToken = trait.getInputToken().get(); + outToken = trait.getOutputToken().get(); + } else { + // TODO: Check how legacy C2J code generation handles service-level pagination + // This is a temporary fix for AccessAnalyzer which uses service-level pagination config. + // We should investigate how the legacy generator in C2jModelToGeneratorModelTransformer + // or other legacy components handle service-level vs operation-level pagination traits + // and implement a more comprehensive solution that matches that behavior. + String serviceLevelInputToken = getServiceLevelInputToken(); + String serviceLevelOutputToken = getServiceLevelOutputToken(); + if (serviceLevelInputToken != null && serviceLevelOutputToken != null) { + inToken = serviceLevelInputToken; + outToken = serviceLevelOutputToken; + } + } + + if (inToken != null && outToken != null) { writer.write(" request.Set$L(result.Get$L());", capitalize(inToken), capitalize(outToken)); + } else { + // TODO: Check AWS SDK C++ standard for handling null pagination tokens + // Should we throw an exception, log a warning, or silently ignore? + // Verify behavior with other AWS SDK implementations. + writer.write(" (void)result; (void)request; // Unused parameters"); } }); }); @@ -137,6 +174,27 @@ private boolean isEc2Protocol() { return "ec2".equals(c2jServiceName); } + // TODO: These service-level pagination helper methods are a temporary solution. + // We should investigate how the legacy C2J code generation system handles the precedence + // between operation-level and service-level pagination traits, and implement a solution + // that matches that behavior. This may involve: + // 1. Checking how C2jModelToGeneratorModelTransformer processes pagination + // 2. Understanding the inheritance model for pagination traits + // 3. Implementing proper trait resolution that matches legacy behavior + private String getServiceLevelInputToken() { + // Check if service has service-level pagination configuration + return service.getTrait(software.amazon.smithy.model.traits.PaginatedTrait.class) + .map(trait -> trait.getInputToken().orElse(null)) + .orElse(null); + } + + private String getServiceLevelOutputToken() { + // Check if service has service-level pagination configuration + return service.getTrait(software.amazon.smithy.model.traits.PaginatedTrait.class) + .map(trait -> trait.getOutputToken().orElse(null)) + .orElse(null); + } + private String capitalize(String str) { return str.substring(0, 1).toUpperCase() + str.substring(1); } From 0ebc50f4807984bf9c4a8391b9d180e778018d75 Mon Sep 17 00:00:00 2001 From: kai lin Date: Fri, 16 Jan 2026 20:21:33 -0500 Subject: [PATCH 14/19] temporary fix for amp --- .../generators/ServiceNameUtil.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java index e9f92b9ac54..2dc27467827 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java @@ -17,7 +17,7 @@ public final class ServiceNameUtil { private static final Set LEGACY_SERVICE_IDS = Set.of( "amp", "appintegrations", "amazonappintegrationservice", "billingconductor", "clouddirectory", "cloudfront", "cloudsearch", "cloudsearchdomain", "codeartifact", "codestar-notifications", - "config", "databrew", "ec2", "elasticache", "emr-containers", + "config", "databrew", "elasticache", "emr-containers", "entitlement.marketplace", "events", "evidently", "forecast", "forecastquery", "grafana", "importexport", "inspector", "lambda", "location", "lookoutvision", "m2", "migrationhubstrategy", "mobile", "mobileanalytics", "mq", "nimble", @@ -29,23 +29,30 @@ public final class ServiceNameUtil { ); public static String getServiceName(ServiceShape service) { - String serviceName = service.getId().getName().toLowerCase(); - if (LEGACY_SERVICE_IDS.contains(serviceName)) { - // For legacy services, use title trait which includes "Service" suffix + // TODO: This logic should match C2jModelToGeneratorModelTransformer.convertMetadata() + // to ensure consistent service name generation between legacy and new generators + + String serviceId = service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()); + + if (LEGACY_SERVICE_IDS.contains(serviceId.toLowerCase())) { + // For legacy services, use title trait (serviceFullName equivalent) which includes "Service" suffix String title = service.getTrait(TitleTrait.class) .map(TitleTrait::getValue) .orElse(null); if (title != null) { - return title.replace(" ", "").replace("-", "").replace("Amazon", "").replace("AWS", ""); + return sanitizeServiceAbbreviation(title); } } // For new services or legacy without title, use serviceId trait - return service.getTrait(ServiceTrait.class) - .map(ServiceTrait::getSdkId) - .orElse(service.getId().getName()) - .replace(" ", "") - .replace("-", ""); + return sanitizeServiceAbbreviation(serviceId); + } + + // Match C2jModelToGeneratorModelTransformer.sanitizeServiceAbbreviation() exactly + private static String sanitizeServiceAbbreviation(String serviceAbbreviation) { + return serviceAbbreviation.replace(" ", "").replace("-", "").replace("_", "").replace("Amazon", "").replace("AWS", "").replace("/", ""); } public static String getC2jServiceName(ServiceShape service, Map c2jMap) { From 14d1c8bf952c8600a12b3c4c2d08328f40bde02c Mon Sep 17 00:00:00 2001 From: kai lin Date: Sat, 17 Jan 2026 01:20:02 -0500 Subject: [PATCH 15/19] temporary fix for B2BI --- .../generators/ServiceNameUtil.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java index 2dc27467827..748b719e05d 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java @@ -35,6 +35,14 @@ public static String getServiceName(ServiceShape service) { String serviceId = service.getTrait(ServiceTrait.class) .map(ServiceTrait::getSdkId) .orElse(service.getId().getName()); + + //TODO: bandage fix + // For B2BI and other services, check if we have a serviceAbbreviation equivalent + // The main generator uses serviceAbbreviation ("AWS B2BI") -> sanitized -> "B2BI" + // We need to simulate this for consistency + if ("b2bi".equals(serviceId.toLowerCase())) { + return "B2BI"; // Match the main generator's output + } if (LEGACY_SERVICE_IDS.contains(serviceId.toLowerCase())) { // For legacy services, use title trait (serviceFullName equivalent) which includes "Service" suffix From 619c29af89deb5f8f5e8fb4954ef03d92ec1d260 Mon Sep 17 00:00:00 2001 From: kai lin Date: Sat, 17 Jan 2026 02:01:51 -0500 Subject: [PATCH 16/19] harded for missing abbreviation trait --- .../generators/ServiceNameUtil.java | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java index 748b719e05d..94153fc6f0f 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java @@ -28,24 +28,44 @@ public final class ServiceNameUtil { "dynamodbstreams" ); + // TODO: Remove hardcoded mappings once Smithy models include serviceAbbreviation trait + // Smithy sdkId matches C2J serviceId, but C2J prioritizes serviceAbbreviation (which Smithy lacks). + // 18 of 66 services where C2J abbrev != serviceId require these mappings to match C2J output. + // Hardcoded mappings where Smithy sdkId doesn't match C2J serviceAbbreviation + private static final Map SMITHY_TO_C2J_NAMESPACE = Map.ofEntries( + Map.entry("b2bi", "B2BI"), + Map.entry("cloudcontrol", "CloudControlApi"), + Map.entry("ecrpublic", "ECRPublic"), + Map.entry("evs", "EVS"), + Map.entry("finspacedata", "FinSpaceData"), + Map.entry("fis", "FIS"), + Map.entry("identitystore", "IdentityStore"), + Map.entry("inspectorscan", "inspectorscan"), + Map.entry("iotdeviceadvisor", "IoTDeviceAdvisor"), + Map.entry("ivs", "IVS"), + Map.entry("ivsrealtime", "ivsrealtime"), + Map.entry("kinesisvideosignaling", "KinesisVideoSignalingChannels"), + Map.entry("marketplaceagreement", "AgreementService"), + Map.entry("mediapackagev2", "mediapackagev2"), + Map.entry("savingsplans", "SavingsPlans"), + Map.entry("servicecatalogappregistry", "AppRegistry"), + Map.entry("sesv2", "SESV2"), + Map.entry("synthetics", "Synthetics") + ); + public static String getServiceName(ServiceShape service) { - // TODO: This logic should match C2jModelToGeneratorModelTransformer.convertMetadata() - // to ensure consistent service name generation between legacy and new generators - String serviceId = service.getTrait(ServiceTrait.class) .map(ServiceTrait::getSdkId) .orElse(service.getId().getName()); - - //TODO: bandage fix - // For B2BI and other services, check if we have a serviceAbbreviation equivalent - // The main generator uses serviceAbbreviation ("AWS B2BI") -> sanitized -> "B2BI" - // We need to simulate this for consistency - if ("b2bi".equals(serviceId.toLowerCase())) { - return "B2BI"; // Match the main generator's output + + // Check hardcoded mappings first + String sanitized = sanitizeServiceAbbreviation(serviceId); + String mapped = SMITHY_TO_C2J_NAMESPACE.get(sanitized.toLowerCase()); + if (mapped != null) { + return mapped; } if (LEGACY_SERVICE_IDS.contains(serviceId.toLowerCase())) { - // For legacy services, use title trait (serviceFullName equivalent) which includes "Service" suffix String title = service.getTrait(TitleTrait.class) .map(TitleTrait::getValue) .orElse(null); @@ -54,8 +74,7 @@ public static String getServiceName(ServiceShape service) { } } - // For new services or legacy without title, use serviceId trait - return sanitizeServiceAbbreviation(serviceId); + return sanitized; } // Match C2jModelToGeneratorModelTransformer.sanitizeServiceAbbreviation() exactly From e742bc640275e76c16c29fcfca5753b7e2a5c58c Mon Sep 17 00:00:00 2001 From: kai lin Date: Sat, 17 Jan 2026 10:55:19 -0500 Subject: [PATCH 17/19] added new detection logic for conflicting service name and add sdk suffix --- .../templates/PaginationTraitsGenerator.java | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java index b7b4469992d..e772b769b4f 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java @@ -157,23 +157,69 @@ private void generateTraitsHeader(CppWriter writer, OperationData suffixOptions = Arrays.asList("Result", "SdkResult", "CppSdkResult"); + + for (String suffix : suffixOptions) { + String candidateName = opName + suffix; + + // Check if there would be a naming conflict with this suffix + if (!hasNamingConflict(candidateName, opName)) { + return suffix; + } + } + + // Fallback to "Result" if no conflicts detected return "Result"; } + // Replicate the conflict detection logic from C2jModelToGeneratorModelTransformer + private boolean hasNamingConflict(String candidateName, String opName) { + // Check if there's a shape that would conflict with this name + // This mimics the conflict detection in renameShape method lines 771-775 + + // Get all shapes in the model to check for conflicts + Set allShapes = context.getModel().toSet(); + + for (Shape shape : allShapes) { + String shapeName = shape.getId().getName(); + + // Check if the candidate name conflicts with existing shape names + if (candidateName.equals(shapeName)) { + // There's a direct name conflict, need to use next suffix + return true; + } + + // Check for "Get" + shapeName pattern conflicts (from C2J logic) + if (candidateName.equals("Get" + shapeName) || candidateName.equals("Set" + shapeName)) { + return true; + } + } + + return false; + } + + // Remove the hardcoded method - no longer needed + // private boolean isKnownConflictingOperation(String opName) { ... } + private boolean isEc2Protocol() { // EC2 protocol services rename all Result shapes to Response // This matches the logic in Ec2CppClientGenerator.legacyPatchEc2Model return "ec2".equals(c2jServiceName); } + // TODO: These service-level pagination helper methods are a temporary solution. // We should investigate how the legacy C2J code generation system handles the precedence // between operation-level and service-level pagination traits, and implement a solution From 08cd208f30aefe9d1d296b1a3ecaaa1527f68850 Mon Sep 17 00:00:00 2001 From: kai lin Date: Sat, 17 Jan 2026 12:35:11 -0500 Subject: [PATCH 18/19] added new new detection logic for conflicting service name and add sdk suffix --- .../templates/PaginationTraitsGenerator.java | 64 +++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java index e772b769b4f..585e7ae963b 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java @@ -158,7 +158,7 @@ private void generateTraitsHeader(CppWriter writer, OperationData suffixOptions = Arrays.asList("Result", "SdkResult", "CppSdkResult"); + // For now, use the simple approach that works: + // If the actual generated file exists, use Result; otherwise use SdkResult - for (String suffix : suffixOptions) { - String candidateName = opName + suffix; + // Check for known SdkResult cases (where data model conflicts exist) + Set allShapes = context.getModel().toSet(); + boolean hasDataModelConflict = allShapes.stream() + .anyMatch(shape -> { + String shapeName = shape.getId().getName(); + if (shapeName.equals(opName + "Result")) { + // Found a shape with the same name - check if it's a data model + if (shape instanceof StructureShape) { + StructureShape structShape = (StructureShape) shape; + // If it doesn't have NextToken, it's likely a data model + return !structShape.getAllMembers().keySet().contains("NextToken"); + } + } + return false; + }); - // Check if there would be a naming conflict with this suffix - if (!hasNamingConflict(candidateName, opName)) { - return suffix; - } - } - - // Fallback to "Result" if no conflicts detected - return "Result"; + return hasDataModelConflict ? "SdkResult" : "Result"; } - // Replicate the conflict detection logic from C2jModelToGeneratorModelTransformer + // TODO: Delete this method if it's not used - replaced by simpler conflict detection in getResultSuffix + // Replicate the precise conflict detection logic from C2jModelToGeneratorModelTransformer private boolean hasNamingConflict(String candidateName, String opName) { - // Check if there's a shape that would conflict with this name - // This mimics the conflict detection in renameShape method lines 771-775 - // Get all shapes in the model to check for conflicts Set allShapes = context.getModel().toSet(); for (Shape shape : allShapes) { String shapeName = shape.getId().getName(); - // Check if the candidate name conflicts with existing shape names + // Direct exact name conflict - this is the main case if (candidateName.equals(shapeName)) { - // There's a direct name conflict, need to use next suffix - return true; - } - - // Check for "Get" + shapeName pattern conflicts (from C2J logic) - if (candidateName.equals("Get" + shapeName) || candidateName.equals("Set" + shapeName)) { + // If this is a structure, check if it's already a suitable operation result + if (shape instanceof StructureShape) { + StructureShape structShape = (StructureShape) shape; + // If the existing shape has pagination tokens, it's already an operation result - no conflict + // Check for various pagination token field names + boolean hasNextToken = structShape.getAllMembers().keySet().stream() + .anyMatch(memberName -> memberName.toLowerCase().contains("nexttoken") || + memberName.toLowerCase().contains("token")); + + if (hasNextToken) { + // This is already an operation result shape, no conflict + return false; + } + + // If it doesn't have pagination tokens, it's a data model - conflict! + return true; + } return true; } } From 927dee57a739858e8f8783430fa672ebec1b7895 Mon Sep 17 00:00:00 2001 From: kai lin Date: Sat, 17 Jan 2026 14:06:11 -0500 Subject: [PATCH 19/19] added new new new detection logic (next/Next token) for conflicting service name and add sdk suffix --- .../generators/templates/PaginationTraitsGenerator.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java index 585e7ae963b..c2fd9c7b5aa 100644 --- a/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java +++ b/tools/code-generation/smithy/codegen/cpp-pagination-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/templates/PaginationTraitsGenerator.java @@ -179,8 +179,11 @@ private String getResultSuffix(String opName) { // Found a shape with the same name - check if it's a data model if (shape instanceof StructureShape) { StructureShape structShape = (StructureShape) shape; - // If it doesn't have NextToken, it's likely a data model - return !structShape.getAllMembers().keySet().contains("NextToken"); + // If it doesn't have NextToken/nextToken, it's likely a data model + Set memberNames = structShape.getAllMembers().keySet(); + // TODO: Sanitize member names for other edge cases (e.g., different casing, underscores, etc.) + boolean hasNextToken = memberNames.contains("NextToken") || memberNames.contains("nextToken"); + return !hasNextToken; } } return false;