From 38228adcf01d1101556e068f16ff1e7fd252c3cd Mon Sep 17 00:00:00 2001 From: George Fu Date: Tue, 10 Sep 2024 15:59:38 +0000 Subject: [PATCH] slightly modify format of displayed types --- .../typescript/codegen/CommandGenerator.java | 328 ++++++++---------- 1 file changed, 144 insertions(+), 184 deletions(-) diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java index 320026b011c..f6ddc6786f6 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java @@ -1,16 +1,14 @@ /* * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except + * in compliance with the License. A copy of the License is located at * - * http://aws.amazon.com/apache2.0 + * http://aws.amazon.com/apache2.0 * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package software.amazon.smithy.typescript.codegen; @@ -86,14 +84,9 @@ final class CommandGenerator implements Runnable { private final ApplicationProtocol applicationProtocol; private final SensitiveDataFinder sensitiveDataFinder; - CommandGenerator( - TypeScriptSettings settings, - Model model, - OperationShape operation, - SymbolProvider symbolProvider, - TypeScriptWriter writer, - List runtimePlugins, - ProtocolGenerator protocolGenerator, + CommandGenerator(TypeScriptSettings settings, Model model, OperationShape operation, + SymbolProvider symbolProvider, TypeScriptWriter writer, + List runtimePlugins, ProtocolGenerator protocolGenerator, ApplicationProtocol applicationProtocol) { this.settings = settings; this.model = model; @@ -220,52 +213,57 @@ private void generateClientCommand() { Symbol baseOutput = symbolProvider.toSymbol(operationOutputShape); writer.write("/** @internal type navigation helper, not in runtime. */"); - writer.writeInline("declare protected static inputTypeRef: [$T, ", inputType); - if (operationInputShape.getAllMembers().isEmpty()) { - writer.writeInline("{}"); - } else { - writer.writeInline("$T", baseInput); - } - writer.write("];"); - - writer.write("/** @internal type navigation helper, not in runtime. */"); - writer.writeInline("declare protected static outputTypeRef: [$T, ", outputType); - if (operationOutputShape.getAllMembers().isEmpty()) { - writer.writeInline("{}"); - } else { - writer.writeInline("$T", baseOutput); - } - writer.write("];"); + writer.openBlock("declare protected static __types: {", "};", () -> { + String baseInputStr = operationInputShape.getAllMembers().isEmpty() + ? "{}" + : baseInput.getName(); + String baseOutputStr = operationOutputShape.getAllMembers().isEmpty() + ? "{}" + : baseOutput.getName(); + writer.write(""" + api: { + input: $L; + output: $L; + };""", baseInputStr, baseOutputStr); + writer.write(""" + sdk: { + input: $T; + output: $T; + };""", inputType, outputType); + }); } + writer.write("}"); // class close bracket. } - private String getCommandExample(String serviceName, String configName, String commandName, String commandInput, - String commandOutput) { + private String getCommandExample(String serviceName, String configName, String commandName, + String commandInput, String commandOutput) { String packageName = settings.getPackageName(); return "@example\n" + "Use a bare-bones client and the command you need to make an API call.\n" + "```javascript\n" - + String.format("import { %s, %s } from \"%s\"; // ES Modules import%n", serviceName, commandName, - packageName) - + String.format("// const { %s, %s } = require(\"%s\"); // CommonJS import%n", serviceName, commandName, - packageName) + + String.format("import { %s, %s } from \"%s\"; // ES Modules import%n", + serviceName, commandName, packageName) + + String.format("// const { %s, %s } = require(\"%s\"); // CommonJS import%n", + serviceName, commandName, packageName) + String.format("const client = new %s(config);%n", serviceName) + String.format("const input = %s%n", StructureExampleGenerator.generateStructuralHintDocumentation( - model.getShape(operation.getInputShape()).get(), model, false, true)) + model.getShape(operation.getInputShape()).get(), model, false, + true)) + String.format("const command = new %s(input);%n", commandName) + "const response = await client.send(command);\n" + String.format("%s%n", StructureExampleGenerator.generateStructuralHintDocumentation( - model.getShape(operation.getOutputShape()).get(), model, true, false)) - + "\n```\n" - + "\n" + model.getShape(operation.getOutputShape()).get(), model, true, + false)) + + "\n```\n" + "\n" + String.format("@param %s - {@link %s}%n", commandInput, commandInput) + String.format("@returns {@link %s}%n", commandOutput) + String.format("@see {@link %s} for command's `input` shape.%n", commandInput) + String.format("@see {@link %s} for command's `response` shape.%n", commandOutput) - + String.format("@see {@link %s | config} for %s's `config` shape.%n", configName, serviceName); + + String.format("@see {@link %s | config} for %s's `config` shape.%n", configName, + serviceName); } private String getThrownExceptions() { @@ -277,18 +275,20 @@ private String getThrownExceptions() { ErrorTrait errorTrait = errorShape.getTrait(ErrorTrait.class).get(); if (doc.isPresent()) { - buffer.append(String.format("@throws {@link %s} (%s fault)%n %s", - error.getName(), errorTrait.getValue(), doc.get().getValue())); + buffer.append(String.format("@throws {@link %s} (%s fault)%n %s", error.getName(), + errorTrait.getValue(), doc.get().getValue())); } else { - buffer.append(String.format("@throws {@link %s} (%s fault)", - error.getName(), errorTrait.getValue())); + buffer.append(String.format("@throws {@link %s} (%s fault)", error.getName(), + errorTrait.getValue())); } buffer.append("\n\n"); } String name = CodegenUtils.getServiceName(settings, model, symbolProvider); - buffer.append(String.format("@throws {@link %s}%n", CodegenUtils.getServiceExceptionName(name))); - buffer.append(String.format("

Base exception class for all service exceptions from %s service.

%n", name)); + buffer.append( + String.format("@throws {@link %s}%n", CodegenUtils.getServiceExceptionName(name))); + buffer.append(String.format( + "

Base exception class for all service exceptions from %s service.

%n", name)); return buffer.toString(); } @@ -297,13 +297,11 @@ private void generateEndpointParameterInstructionProvider() { if (!service.hasTrait(EndpointRuleSetTrait.class)) { return; } - writer.write(".ep({") - .indent(); + writer.write(".ep({").indent(); { - writer.addImport( - "commonParams", null, - Paths.get(".", CodegenUtils.SOURCE_FOLDER, "endpoint/EndpointParameters").toString() - ); + writer.addImport("commonParams", null, + Paths.get(".", CodegenUtils.SOURCE_FOLDER, "endpoint/EndpointParameters") + .toString()); writer.write("...commonParams,"); @@ -312,31 +310,26 @@ private void generateEndpointParameterInstructionProvider() { parameterFinder.getStaticContextParamValues(operation).forEach((name, value) -> { paramNames.add(name); - writer.write( - "$L: { type: \"staticContextParams\", value: $L },", - name, value); + writer.write("$L: { type: \"staticContextParams\", value: $L },", name, value); }); Shape operationInput = model.getShape(operation.getInputShape()).get(); parameterFinder.getContextParams(operationInput).forEach((name, memberName) -> { if (!paramNames.contains(name)) { - writer.write( - "$L: { type: \"contextParams\", name: \"$L\" },", - name, memberName); + writer.write("$L: { type: \"contextParams\", name: \"$L\" },", name, + memberName); } paramNames.add(name); }); - parameterFinder.getOperationContextParamValues(operation).forEach((name, jmesPathForInputInJs) -> { - writer.write( - """ - $L: { type: \"operationContextParams\", name: $L }, - """, - name, jmesPathForInputInJs); - }); + parameterFinder.getOperationContextParamValues(operation) + .forEach((name, jmesPathForInputInJs) -> { + writer.write(""" + $L: { type: \"operationContextParams\", name: $L }, + """, name, jmesPathForInputInJs); + }); } - writer.write("})") - .dedent(); + writer.write("})").dedent(); } private void generateCommandMiddlewareResolver(String configType) { @@ -346,88 +339,61 @@ private void generateCommandMiddlewareResolver(String configType) { if (sensitiveDataFinder.findsSensitiveDataIn(input)) { Symbol inputSymbol = symbolProvider.toSymbol(input); String filterFunctionName = inputSymbol.getName() + "FilterSensitiveLog"; - writer.addRelativeImport( - filterFunctionName, - null, - Paths.get(".", inputSymbol.getNamespace())); + writer.addRelativeImport(filterFunctionName, null, + Paths.get(".", inputSymbol.getNamespace())); return filterFunctionName; } return "void 0"; }; - String inputFilterFn = operationIndex - .getInput(operation) - .map(getFilterFunctionName) - .orElse("void 0"); - - String outputFilterFn = operationIndex - .getOutput(operation) - .map(getFilterFunctionName) - .orElse("void 0"); - - writer.pushState() - .putContext("client", symbolProvider.toSymbol(service).getName()) - .putContext("command", symbolProvider.toSymbol(operation).getName()) - .putContext("service", service.toShapeId().getName()) - .putContext("operation", operation.toShapeId().getName()) - .putContext("inputFilter", inputFilterFn) - .putContext("outputFilter", outputFilterFn) - .putContext("configType", configType) - .putContext("optionsType", applicationProtocol.getOptionsType()) - .putContext("inputType", inputType) - .putContext("outputType", outputType); - - writer.write( - """ - .m(function (this: any, Command: any, cs: any, config: $configType:L, o: any) { - return [ - """ - ); + String inputFilterFn = + operationIndex.getInput(operation).map(getFilterFunctionName).orElse("void 0"); + + String outputFilterFn = + operationIndex.getOutput(operation).map(getFilterFunctionName).orElse("void 0"); + + writer.pushState().putContext("client", symbolProvider.toSymbol(service).getName()) + .putContext("command", symbolProvider.toSymbol(operation).getName()) + .putContext("service", service.toShapeId().getName()) + .putContext("operation", operation.toShapeId().getName()) + .putContext("inputFilter", inputFilterFn).putContext("outputFilter", outputFilterFn) + .putContext("configType", configType) + .putContext("optionsType", applicationProtocol.getOptionsType()) + .putContext("inputType", inputType).putContext("outputType", outputType); + + writer.write(""" + .m(function (this: any, Command: any, cs: any, config: $configType:L, o: any) { + return [ + """); { // Add serialization and deserialization plugin. writer.write("$T(config, this.serialize, this.deserialize),", serde); // EndpointsV2 if (service.hasTrait(EndpointRuleSetTrait.class)) { - writer.addImport( - "getEndpointPlugin", - null, - TypeScriptDependency.MIDDLEWARE_ENDPOINTS_V2); - writer.write( - """ - getEndpointPlugin(config, Command.getEndpointParameterInstructions()),""" - ); + writer.addImport("getEndpointPlugin", null, + TypeScriptDependency.MIDDLEWARE_ENDPOINTS_V2); + writer.write(""" + getEndpointPlugin(config, Command.getEndpointParameterInstructions()),"""); } // Add customizations. addCommandSpecificPlugins(); } - writer.write( - """ - ]; - })""" - ); // end middleware. + writer.write(""" + ]; + })"""); // end middleware. // context, filters - writer.openBlock( - """ - .s($service:S, $operation:S, { - """, - """ - }) - .n($client:S, $command:S) - .f($inputFilter:L, $outputFilter:L)""", - () -> { - writer.pushState(SmithyContextCodeSection.builder() - .settings(settings) - .model(model) - .service(service) - .operation(operation) - .symbolProvider(symbolProvider) - .runtimeClientPlugins(runtimePlugins) - .protocolGenerator(protocolGenerator) - .applicationProtocol(applicationProtocol) - .build()); - writer.popState(); - } - ); + writer.openBlock(""" + .s($service:S, $operation:S, { + """, """ + }) + .n($client:S, $command:S) + .f($inputFilter:L, $outputFilter:L)""", () -> { + writer.pushState(SmithyContextCodeSection.builder().settings(settings).model(model) + .service(service).operation(operation).symbolProvider(symbolProvider) + .runtimeClientPlugins(runtimePlugins).protocolGenerator(protocolGenerator) + .applicationProtocol(applicationProtocol).build()); + writer.popState(); + }); writer.popState(); } @@ -437,29 +403,28 @@ private void addInputAndOutputTypes() { writer.write("export { $$Command };"); writeInputType(inputType.getName(), operationIndex.getInput(operation), symbol.getName()); - writeOutputType(outputType.getName(), operationIndex.getOutput(operation), symbol.getName()); + writeOutputType(outputType.getName(), operationIndex.getOutput(operation), + symbol.getName()); writer.write(""); } - private void writeInputType(String typeName, Optional inputShape, String commandName) { + private void writeInputType(String typeName, Optional inputShape, + String commandName) { if (inputShape.isPresent()) { StructureShape input = inputShape.get(); List blobStreamingMembers = getBlobStreamingMembers(model, input); List blobPayloadMembers = getBlobPayloadMembers(model, input); if (!blobStreamingMembers.isEmpty()) { - writeClientCommandStreamingInputType( - writer, symbolProvider.toSymbol(input), typeName, - blobStreamingMembers.get(0), commandName - ); + writeClientCommandStreamingInputType(writer, symbolProvider.toSymbol(input), + typeName, blobStreamingMembers.get(0), commandName); } else if (!blobPayloadMembers.isEmpty()) { - writeClientCommandBlobPayloadInputType( - writer, symbolProvider.toSymbol(input), typeName, - blobPayloadMembers.get(0), commandName - ); + writeClientCommandBlobPayloadInputType(writer, symbolProvider.toSymbol(input), + typeName, blobPayloadMembers.get(0), commandName); } else { writer.writeDocs("@public\n\nThe input for {@link " + commandName + "}."); - writer.write("export interface $L extends $T {}", typeName, symbolProvider.toSymbol(input)); + writer.write("export interface $L extends $T {}", typeName, + symbolProvider.toSymbol(input)); } } else { // If the input is non-existent, then use an empty object. @@ -468,7 +433,8 @@ private void writeInputType(String typeName, Optional inputShape } } - private void writeOutputType(String typeName, Optional outputShape, String commandName) { + private void writeOutputType(String typeName, Optional outputShape, + String commandName) { // Output types should always be MetadataBearers, possibly in addition // to a defined output shape. writer.addImport("MetadataBearer", "__MetadataBearer", TypeScriptDependency.SMITHY_TYPES); @@ -478,19 +444,15 @@ private void writeOutputType(String typeName, Optional outputSha List blobPayloadMembers = getBlobPayloadMembers(model, output); if (!blobStreamingMembers.isEmpty()) { - writeClientCommandStreamingOutputType( - writer, symbolProvider.toSymbol(output), typeName, - blobStreamingMembers.get(0), commandName - ); + writeClientCommandStreamingOutputType(writer, symbolProvider.toSymbol(output), + typeName, blobStreamingMembers.get(0), commandName); } else if (!blobPayloadMembers.isEmpty()) { - writeClientCommandBlobPayloadOutputType( - writer, symbolProvider.toSymbol(output), typeName, - blobPayloadMembers.get(0), commandName - ); + writeClientCommandBlobPayloadOutputType(writer, symbolProvider.toSymbol(output), + typeName, blobPayloadMembers.get(0), commandName); } else { writer.writeDocs("@public\n\nThe output of {@link " + commandName + "}."); - writer.write("export interface $L extends $T, __MetadataBearer {}", - typeName, symbolProvider.toSymbol(outputShape.get())); + writer.write("export interface $L extends $T, __MetadataBearer {}", typeName, + symbolProvider.toSymbol(outputShape.get())); } } else { writer.writeDocs("@public\n\nThe output of {@link " + commandName + "}."); @@ -506,8 +468,8 @@ private void addCommandSpecificPlugins() { for (RuntimeClientPlugin plugin : runtimePlugins) { plugin.getPluginFunction().ifPresent(pluginSymbol -> { // Construct additional parameters string - Map paramsMap = plugin.getAdditionalPluginFunctionParameters( - model, service, operation); + Map paramsMap = + plugin.getAdditionalPluginFunctionParameters(model, service, operation); // Construct writer context @@ -521,10 +483,12 @@ private void addCommandSpecificPlugins() { writer.pushState(); writer.putContext(symbolMap); writer.openBlock("$pluginFn:T(config", "),", () -> { - List additionalParameters = CodegenUtils.getFunctionParametersList(paramsMap); + List additionalParameters = + CodegenUtils.getFunctionParametersList(paramsMap); Map clientAddParamsWriterConsumers = - plugin.getOperationAddParamsWriterConsumers(); - if (additionalParameters.isEmpty() && clientAddParamsWriterConsumers.isEmpty()) { + plugin.getOperationAddParamsWriterConsumers(); + if (additionalParameters.isEmpty() + && clientAddParamsWriterConsumers.isEmpty()) { return; } writer.openBlock(", { ", " }", () -> { @@ -535,14 +499,12 @@ private void addCommandSpecificPlugins() { } clientAddParamsWriterConsumers.forEach((key, consumer) -> { writer.writeInline("$L: $C,", key, (Consumer) (w -> { - consumer.accept(w, CommandConstructorCodeSection.builder() - .settings(settings) - .model(model) - .service(service) - .symbolProvider(symbolProvider) - .runtimeClientPlugins(runtimePlugins) - .applicationProtocol(applicationProtocol) - .build()); + consumer.accept(w, + CommandConstructorCodeSection.builder().settings(settings) + .model(model).service(service) + .symbolProvider(symbolProvider) + .runtimeClientPlugins(runtimePlugins) + .applicationProtocol(applicationProtocol).build()); })); }); }); @@ -553,17 +515,15 @@ private void addCommandSpecificPlugins() { } private void writeSerde() { - writer - .write(".ser($L)", getSerdeDispatcher(true)) - .write(".de($L)", getSerdeDispatcher(false)); + writer.write(".ser($L)", getSerdeDispatcher(true)).write(".de($L)", + getSerdeDispatcher(false)); } private String getSerdeDispatcher(boolean isInput) { if (protocolGenerator == null) { return "() => { throw new Error(\"No supported protocol was found\"); }"; } else { - String serdeFunctionName = isInput - ? ProtocolGenerator.getSerFunctionShortName(symbol) + String serdeFunctionName = isInput ? ProtocolGenerator.getSerFunctionShortName(symbol) : ProtocolGenerator.getDeserFunctionShortName(symbol); writer.addRelativeImport(serdeFunctionName, null, Paths.get(".", CodegenUtils.SOURCE_FOLDER, ProtocolGenerator.PROTOCOLS_FOLDER, @@ -572,25 +532,25 @@ private String getSerdeDispatcher(boolean isInput) { } } - static void writeIndex( - Model model, - ServiceShape service, - SymbolProvider symbolProvider, + static void writeIndex(Model model, ServiceShape service, SymbolProvider symbolProvider, FileManifest fileManifest) { TypeScriptWriter writer = new TypeScriptWriter(""); TopDownIndex topDownIndex = TopDownIndex.of(model); - Set containedOperations = new TreeSet<>(topDownIndex.getContainedOperations(service)); + Set containedOperations = + new TreeSet<>(topDownIndex.getContainedOperations(service)); if (containedOperations.isEmpty()) { writer.write("export {};"); } else { for (OperationShape operation : containedOperations) { - writer.write("export * from \"./$L\";", symbolProvider.toSymbol(operation).getName()); + writer.write("export * from \"./$L\";", + symbolProvider.toSymbol(operation).getName()); } } fileManifest.writeFile( - Paths.get(CodegenUtils.SOURCE_FOLDER, CommandGenerator.COMMANDS_FOLDER, "index.ts").toString(), + Paths.get(CodegenUtils.SOURCE_FOLDER, CommandGenerator.COMMANDS_FOLDER, "index.ts") + .toString(), writer.toString()); } }