From 326913bb9ae85a03e3389e1a4d06db55214362e1 Mon Sep 17 00:00:00 2001 From: Chase Coalwell <782571+srchase@users.noreply.github.com> Date: Tue, 9 May 2023 12:31:09 -0600 Subject: [PATCH 1/2] chore(codegen): add UnaryFunctionCall --- .../codegen/validation/UnaryFunctionCall.java | 61 +++++++++++++++++++ .../validation/UnaryFunctionCallTest.java | 36 +++++++++++ 2 files changed, 97 insertions(+) create mode 100644 codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCall.java create mode 100644 codegen/smithy-aws-typescript-codegen/src/test/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCallTest.java diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCall.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCall.java new file mode 100644 index 000000000000..daabc30edc6b --- /dev/null +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCall.java @@ -0,0 +1,61 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + + package software.amazon.smithy.aws.typescript.codegen.validation; + +import java.util.regex.Pattern; + +/** + * For handling expressions that may be unary function calls. + */ +public abstract class UnaryFunctionCall { + private static final Pattern CHECK_PATTERN = Pattern.compile("^(?!new ).+\\(((?!,).)*\\)$"); + private static final Pattern TO_REF_PATTERN = Pattern.compile("(.*)\\(.*\\)$"); + + /** + * @param expression - to be examined. + * @return whether the expression is a single-depth function call with a single parameter. + */ + public static boolean check(String expression) { + if (expression.equals("_")) { + // not a call per se, but this indicates a pass-through function. + return true; + } + return maxCallDepth(expression) == 1 && CHECK_PATTERN.matcher(expression).matches(); + } + + /** + * @param callExpression the call expression to be converted. Check that + * the expression is a unary call first. + * @return the unary function call converted to a function reference. + */ + public static String toRef(String callExpression) { + return TO_REF_PATTERN.matcher(callExpression).replaceAll("$1"); + } + + /** + * Estimates the call depth of a function call expression. + * + * @param expression A function call expression (e.g., "call() == 1", "call(call()) == 2", etc). + */ + private static int maxCallDepth(String expression) { + int depth = 0; + int maxDepth = 0; + for (int i = 0; i < expression.length(); ++i) { + char c = expression.charAt(i); + if (c == '(') { + depth += 1; + if (depth > maxDepth) { + maxDepth = depth; + } + continue; + } + if (c == ')') { + depth -= 1; + } + } + return maxDepth; + } +} diff --git a/codegen/smithy-aws-typescript-codegen/src/test/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCallTest.java b/codegen/smithy-aws-typescript-codegen/src/test/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCallTest.java new file mode 100644 index 000000000000..4549f8f32b7c --- /dev/null +++ b/codegen/smithy-aws-typescript-codegen/src/test/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCallTest.java @@ -0,0 +1,36 @@ +package software.amazon.smithy.aws.typescript.codegen.validation; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class UnaryFunctionCallTest { + @Test + void check() { + assertEquals(false, UnaryFunctionCall.check("")); + assertEquals(false, UnaryFunctionCall.check("5")); + assertEquals(false, UnaryFunctionCall.check("(param)")); + assertEquals(false, UnaryFunctionCall.check("x[5]")); + assertEquals(false, UnaryFunctionCall.check("new Date(timestamp)")); + assertEquals(false, UnaryFunctionCall.check("x(y(_))")); + assertEquals(false, UnaryFunctionCall.check("call(param).prop")); + assertEquals(false, UnaryFunctionCall.check("call(param, param2)")); + + assertEquals(true, UnaryFunctionCall.check("_")); + assertEquals(true, UnaryFunctionCall.check("x()")); + assertEquals(true, UnaryFunctionCall.check("x(_)")); + assertEquals(true, UnaryFunctionCall.check("long_function_name(long_parameter_name)")); + assertEquals(true, UnaryFunctionCall.check("container.function(param)")); + assertEquals(true, UnaryFunctionCall.check("factory(param)(param2)")); + } + + @Test + void toRef() { + assertEquals("_", UnaryFunctionCall.toRef("_")); + assertEquals("x", UnaryFunctionCall.toRef("x()")); + assertEquals("x", UnaryFunctionCall.toRef("x(_)")); + assertEquals("long_function_name", UnaryFunctionCall.toRef("long_function_name(long_parameter_name)")); + assertEquals("container.function", UnaryFunctionCall.toRef("container.function(param)")); + assertEquals("factory(param)", UnaryFunctionCall.toRef("factory(param)(param2)")); + } +} \ No newline at end of file From 99428ff69726200466e013c3eb66654e90771d6a Mon Sep 17 00:00:00 2001 From: Chase Coalwell <782571+srchase@users.noreply.github.com> Date: Tue, 9 May 2023 12:31:33 -0600 Subject: [PATCH 2/2] chore(codegen): use SerdeElision knowledge index --- .../typescript/codegen/JsonMemberDeserVisitor.java | 2 +- .../aws/typescript/codegen/JsonMemberSerVisitor.java | 2 +- .../typescript/codegen/JsonRpcProtocolGenerator.java | 4 ++-- .../aws/typescript/codegen/JsonShapeDeserVisitor.java | 11 +++++++---- .../aws/typescript/codegen/JsonShapeSerVisitor.java | 11 +++++++---- .../typescript/codegen/RestJsonProtocolGenerator.java | 8 +++++--- .../codegen/validation/UnaryFunctionCall.java | 4 ++-- 7 files changed, 25 insertions(+), 17 deletions(-) diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonMemberDeserVisitor.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonMemberDeserVisitor.java index 971110a4bec9..78b887ce4a6a 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonMemberDeserVisitor.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonMemberDeserVisitor.java @@ -44,7 +44,7 @@ final class JsonMemberDeserVisitor extends DocumentMemberDeserVisitor { super(context, dataSource, defaultTimestampFormat); this.memberShape = memberShape; context.getWriter().addImport("_json", null, "@aws-sdk/smithy-client"); - serdeElision.setEnabledForModel(!context.getSettings().generateServerSdk()); + this.serdeElisionEnabled = !context.getSettings().generateServerSdk(); } JsonMemberDeserVisitor(GenerationContext context, diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonMemberSerVisitor.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonMemberSerVisitor.java index 2a958c9d1f56..0bd299befa9e 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonMemberSerVisitor.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonMemberSerVisitor.java @@ -39,7 +39,7 @@ final class JsonMemberSerVisitor extends DocumentMemberSerVisitor { JsonMemberSerVisitor(GenerationContext context, String dataSource, Format defaultTimestampFormat) { super(context, dataSource, defaultTimestampFormat); context.getWriter().addImport("_json", null, "@aws-sdk/smithy-client"); - serdeElision.setEnabledForModel(!context.getSettings().generateServerSdk()); + this.serdeElisionEnabled = !context.getSettings().generateServerSdk(); } @Override diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonRpcProtocolGenerator.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonRpcProtocolGenerator.java index 03fc7f6d3a82..0def7d03e819 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonRpcProtocolGenerator.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonRpcProtocolGenerator.java @@ -67,14 +67,14 @@ protected Format getDocumentTimestampFormat() { protected void generateDocumentBodyShapeSerializers(GenerationContext context, Set shapes) { AwsProtocolUtils.generateDocumentBodyShapeSerde(context, shapes, // AWS JSON does not support jsonName - new JsonShapeSerVisitor(context, (shape, name) -> name)); + new JsonShapeSerVisitor(context, (shape, name) -> name, enableSerdeElision())); } @Override protected void generateDocumentBodyShapeDeserializers(GenerationContext context, Set shapes) { AwsProtocolUtils.generateDocumentBodyShapeSerde(context, shapes, // AWS JSON does not support jsonName - new JsonShapeDeserVisitor(context, (shape, name) -> name)); + new JsonShapeDeserVisitor(context, (shape, name) -> name, enableSerdeElision())); } @Override diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonShapeDeserVisitor.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonShapeDeserVisitor.java index a4c5035a12da..3e39896ab932 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonShapeDeserVisitor.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonShapeDeserVisitor.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.TreeMap; import java.util.function.BiFunction; +import software.amazon.smithy.aws.typescript.codegen.validation.UnaryFunctionCall; import software.amazon.smithy.codegen.core.SymbolProvider; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.shapes.CollectionShape; @@ -41,7 +42,6 @@ import software.amazon.smithy.typescript.codegen.integration.DocumentMemberDeserVisitor; import software.amazon.smithy.typescript.codegen.integration.DocumentShapeDeserVisitor; import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator.GenerationContext; -import software.amazon.smithy.typescript.codegen.validation.UnaryFunctionCall; import software.amazon.smithy.utils.SmithyInternalApi; /** @@ -58,16 +58,19 @@ final class JsonShapeDeserVisitor extends DocumentShapeDeserVisitor { private final BiFunction memberNameStrategy; - JsonShapeDeserVisitor(GenerationContext context) { + JsonShapeDeserVisitor(GenerationContext context, boolean serdeElisionEnabled) { this(context, // Use the jsonName trait value if present, otherwise use the member name. (memberShape, memberName) -> memberShape.getTrait(JsonNameTrait.class) .map(JsonNameTrait::getValue) - .orElse(memberName)); + .orElse(memberName), + serdeElisionEnabled); } - JsonShapeDeserVisitor(GenerationContext context, BiFunction memberNameStrategy) { + JsonShapeDeserVisitor(GenerationContext context, BiFunction memberNameStrategy, + boolean serdeElisionEnabled) { super(context); + this.serdeElisionEnabled = serdeElisionEnabled; this.memberNameStrategy = memberNameStrategy; } diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonShapeSerVisitor.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonShapeSerVisitor.java index d0fd89f4c1af..0555b383d884 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonShapeSerVisitor.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonShapeSerVisitor.java @@ -18,6 +18,7 @@ import java.util.Map; import java.util.TreeMap; import java.util.function.BiFunction; +import software.amazon.smithy.aws.typescript.codegen.validation.UnaryFunctionCall; import software.amazon.smithy.codegen.core.SymbolProvider; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.shapes.CollectionShape; @@ -37,7 +38,6 @@ import software.amazon.smithy.typescript.codegen.integration.DocumentMemberSerVisitor; import software.amazon.smithy.typescript.codegen.integration.DocumentShapeSerVisitor; import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator.GenerationContext; -import software.amazon.smithy.typescript.codegen.validation.UnaryFunctionCall; import software.amazon.smithy.utils.SmithyInternalApi; /** @@ -55,16 +55,19 @@ final class JsonShapeSerVisitor extends DocumentShapeSerVisitor { private final BiFunction memberNameStrategy; - JsonShapeSerVisitor(GenerationContext context) { + JsonShapeSerVisitor(GenerationContext context, boolean serdeElisionEnabled) { this(context, // Use the jsonName trait value if present, otherwise use the member name. (memberShape, memberName) -> memberShape.getTrait(JsonNameTrait.class) .map(JsonNameTrait::getValue) - .orElse(memberName)); + .orElse(memberName), + serdeElisionEnabled); } - JsonShapeSerVisitor(GenerationContext context, BiFunction memberNameStrategy) { + JsonShapeSerVisitor(GenerationContext context, BiFunction memberNameStrategy, + boolean serdeElisionEnabled) { super(context); + this.serdeElisionEnabled = serdeElisionEnabled; this.memberNameStrategy = memberNameStrategy; } diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/RestJsonProtocolGenerator.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/RestJsonProtocolGenerator.java index a7b5a8baf944..481e3b549f1c 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/RestJsonProtocolGenerator.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/RestJsonProtocolGenerator.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Set; +import software.amazon.smithy.aws.typescript.codegen.validation.UnaryFunctionCall; import software.amazon.smithy.codegen.core.SymbolProvider; import software.amazon.smithy.model.knowledge.HttpBinding; import software.amazon.smithy.model.shapes.DocumentShape; @@ -33,7 +34,6 @@ import software.amazon.smithy.typescript.codegen.integration.DocumentMemberDeserVisitor; import software.amazon.smithy.typescript.codegen.integration.DocumentMemberSerVisitor; import software.amazon.smithy.typescript.codegen.integration.HttpBindingProtocolGenerator; -import software.amazon.smithy.typescript.codegen.validation.UnaryFunctionCall; import software.amazon.smithy.utils.IoUtils; import software.amazon.smithy.utils.SmithyInternalApi; @@ -68,12 +68,14 @@ protected TimestampFormatTrait.Format getDocumentTimestampFormat() { @Override protected void generateDocumentBodyShapeSerializers(GenerationContext context, Set shapes) { - AwsProtocolUtils.generateDocumentBodyShapeSerde(context, shapes, new JsonShapeSerVisitor(context)); + AwsProtocolUtils.generateDocumentBodyShapeSerde(context, shapes, new JsonShapeSerVisitor(context, + (!context.getSettings().generateServerSdk() && enableSerdeElision()))); } @Override protected void generateDocumentBodyShapeDeserializers(GenerationContext context, Set shapes) { - AwsProtocolUtils.generateDocumentBodyShapeSerde(context, shapes, new JsonShapeDeserVisitor(context)); + AwsProtocolUtils.generateDocumentBodyShapeSerde(context, shapes, new JsonShapeDeserVisitor(context, + (!context.getSettings().generateServerSdk() && enableSerdeElision()))); } @Override diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCall.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCall.java index daabc30edc6b..086638ec1a75 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCall.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/validation/UnaryFunctionCall.java @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ - package software.amazon.smithy.aws.typescript.codegen.validation; +package software.amazon.smithy.aws.typescript.codegen.validation; import java.util.regex.Pattern; /** * For handling expressions that may be unary function calls. */ -public abstract class UnaryFunctionCall { +class UnaryFunctionCall { private static final Pattern CHECK_PATTERN = Pattern.compile("^(?!new ).+\\(((?!,).)*\\)$"); private static final Pattern TO_REF_PATTERN = Pattern.compile("(.*)\\(.*\\)$");