From 461dd3d9ffe60b4f4cfa346ad51d4b7d798013d0 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Fri, 20 Oct 2023 13:35:56 -0700 Subject: [PATCH 01/49] Fix UTF8 --- .../runtimes/java/src/main/java/UTF8/__default.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java b/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java index b39b871ec..e6a1b5b5d 100644 --- a/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java +++ b/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java @@ -25,6 +25,12 @@ // and reset the coder everytime. public class __default extends UTF8._ExternBase___default { + private static final dafny.TypeDescriptor> BYTE_SEQUENCE_TYPE_DESCRIPTOR = + dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.BYTE); + private static final dafny.TypeDescriptor> CHARACTER_SEQUENCE_TYPE_DESCRIPTOR = + dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR); + + // This is largely copied from Polymorph's dafny-java-conversion: // software.amazon.smithy.dafny.conversion.ToDafny.Simple.DafnyUtf8Bytes public static Result< @@ -42,9 +48,11 @@ DafnySequence> Encode( // By taking just the limit, we ensure we do not include // any allocated but un-filled space. return Result.create_Success( + BYTE_SEQUENCE_TYPE_DESCRIPTOR, CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, (DafnySequence) ByteSequence(outBuffer, 0, outBuffer.limit())); } catch (CharacterCodingException ex) { return Result.create_Failure( + BYTE_SEQUENCE_TYPE_DESCRIPTOR, CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, (DafnySequence) CharacterSequence("Could not encode input to Dafny Bytes.")); } } @@ -64,9 +72,11 @@ DafnySequence> Decode( CharBuffer outBuffer = coder.decode(inBuffer); outBuffer.position(0); return Result.create_Success( + CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, (DafnySequence) CharacterSequence(outBuffer.toString())); } catch (CharacterCodingException ex) { return Result.create_Failure( + CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, (DafnySequence) CharacterSequence("Could not encode input to Dafny Bytes.")); } } From c31cee8564e9e545c62e694651c0a0659ae8d37a Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Fri, 20 Oct 2023 13:36:25 -0700 Subject: [PATCH 02/49] Temporarily try CI on 4.3 --- .github/workflows/test_models_java_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_models_java_tests.yml b/.github/workflows/test_models_java_tests.yml index 4fcc1bd19..fc9bd5bbc 100644 --- a/.github/workflows/test_models_java_tests.yml +++ b/.github/workflows/test_models_java_tests.yml @@ -85,7 +85,7 @@ jobs: uses: dafny-lang/setup-dafny-action@v1.6.1 with: # A && B || C is the closest thing to an if .. then ... else ... or ?: expression the GitHub Actions syntax supports. - dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || '4.1.0' }} + dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || '4.3.0' }} - name: Setup Java uses: actions/setup-java@v3 From 478c043e300005f3aa29eff831bd96e9a6cb4058 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 23 Oct 2023 13:54:05 -0700 Subject: [PATCH 03/49] Get Resource test model working --- .../internaldafny/wrapped/__default.java | 2 +- .../smithyjava/generator/ToDafny.java | 7 ++++-- .../generator/awssdk/v1/ShimV1.java | 25 +++++++++++++------ .../generator/awssdk/v1/ToDafnyAwsV1.java | 1 + .../generator/awssdk/v2/ShimV2.java | 4 +-- .../smithyjava/modeled/Operation.java | 19 +++++++++----- 6 files changed, 39 insertions(+), 19 deletions(-) diff --git a/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java b/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java index c77ce7d4d..13cd02c00 100644 --- a/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java +++ b/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleResources(Simpl simple.resources.model.SimpleResourcesConfig wrappedConfig = ToNative.SimpleResourcesConfig(config); simple.resources.SimpleResources impl = SimpleResources.builder().SimpleResourcesConfig(wrappedConfig).build(); TestSimpleResources wrappedClient = TestSimpleResources.builder().impl(impl).build(); - return Result.create_Success(wrappedClient); + return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleResourcesClient.class), Error._typeDescriptor(), wrappedClient); } } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/ToDafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/ToDafny.java index 705cd5c4c..c8af80d9a 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/ToDafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/ToDafny.java @@ -194,13 +194,16 @@ protected CodeBlock memberAssign( isNullCheck, inputVar); } + CodeBlock typeDescriptor = subject.dafnyNameResolver.typeDescriptor(memberShape.getTarget()); return CodeBlock.of( - "$L = $L ?\n$T.create_Some($L)\n: $T.create_None()", + "$L = $L ?\n$T.create_Some($L, $L)\n: $T.create_None($L)", outputVar, isSetCheck, ClassName.get("Wrappers_Compile", "Option"), + typeDescriptor, memberConversion, - ClassName.get("Wrappers_Compile", "Option") + ClassName.get("Wrappers_Compile", "Option"), + typeDescriptor ); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java index fbfe15fc9..8d36456b7 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java @@ -3,6 +3,7 @@ package software.amazon.polymorph.smithyjava.generator.awssdk.v1; import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeName; @@ -138,32 +139,40 @@ Optional operation(final ShapeId operationShapeId) { subject.nativeNameResolver.typeForShape(inputShapeId), StringUtils.capitalize(inputShapeId.getName())) .beginControlFlow("try"); + CodeBlock successTypeDescriptor; if (outputShapeId.equals(SMITHY_API_UNIT)) { + successTypeDescriptor = CodeBlock.of(DAFNY_TUPLE0_CLASS_NAME + "._typeDescriptor()"); builder.addStatement("_impl.$L(converted)", StringUtils.uncapitalize(operationName)) - .addStatement("return $T.create_Success($T.create())", - DAFNY_RESULT_CLASS_NAME, DAFNY_TUPLE0_CLASS_NAME); + .addStatement("return $T.create_Success($L, Error._typeDescriptor(), $T.create())", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor, + DAFNY_TUPLE0_CLASS_NAME); } else { + successTypeDescriptor = subject.dafnyNameResolver.typeDescriptor(outputShapeId); builder.addStatement("$T result = _impl.$L(converted)", subject.nativeNameResolver.typeForOperationOutput(outputShapeId), StringUtils.uncapitalize(operationName)) .addStatement("$T dafnyResponse = ToDafny.$L(result)", dafnyOutput, StringUtils.capitalize(outputShapeId.getName())) - .addStatement("return $T.create_Success(dafnyResponse)", - DAFNY_RESULT_CLASS_NAME); + .addStatement("return $T.create_Success($L, Error._typeDescriptor(), dafnyResponse)", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor); } operationShape.getErrors().stream().sorted().forEach(shapeId -> builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.typeForShape(shapeId)) - .addStatement("return $T.create_Failure(ToDafny.Error(ex))", - DAFNY_RESULT_CLASS_NAME) + .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), ToDafny.Error(ex))", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor) ); return Optional.of(builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.baseErrorForService()) - .addStatement("return $T.create_Failure(ToDafny.Error(ex))", - DAFNY_RESULT_CLASS_NAME) + .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), ToDafny.Error(ex))", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor) .endControlFlow() .build()); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ToDafnyAwsV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ToDafnyAwsV1.java index 816a2e0fd..f7db9644f 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ToDafnyAwsV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ToDafnyAwsV1.java @@ -346,6 +346,7 @@ MethodSpec generateConvertOpaqueError() { ); // This is memberAssignment from above, // but with calls to dafnyNameResolver replaced with their expected response. +// CodeBlock typeDescriptor = subject.dafnyNameResolver.typeDescriptor(ShapeType.STRING); CodeBlock memberAssignment = CodeBlock.of( "$L = $T.nonNull($L) ?\n$T.create_Some($T.$L($L))\n: $T.create_None()", "message", diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java index 26cd5f267..9206fc1c2 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java @@ -164,12 +164,12 @@ Optional operation(final ShapeId operationShapeId) { builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.typeForShape(shapeId)) - .addStatement("return $T.create_Failure(ToDafny.Error(ex))", + .addStatement("return $T.create_Failure(Error._typeDescriptor(), ToDafny.Error(ex))", DAFNY_RESULT_CLASS_NAME); }); return Optional.of(builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.baseErrorForService()) - .addStatement("return $T.create_Failure(ToDafny.Error(ex))", + .addStatement("return $T.create_Failure(Error._typeDescriptor(), ToDafny.Error(ex))", DAFNY_RESULT_CLASS_NAME) .endControlFlow() .build()); diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/modeled/Operation.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/modeled/Operation.java index 27361229f..e58a88028 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/modeled/Operation.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/modeled/Operation.java @@ -57,27 +57,34 @@ public static MethodSpec operation( method.addStatement(declareNativeInputAndCovert(inputResolved, subject)); // Try native implementation method.beginControlFlow("try"); + CodeBlock successTypeDescriptor; if (outputResolved.resolvedId().equals(SMITHY_API_UNIT)) { // if operation is void + successTypeDescriptor = CodeBlock.of("dafny.Tuple0._typeDescriptor()"); method .addStatement(invoke(operationName)) - .addStatement("return $T.create_Success($T.create())", - DAFNY_RESULT_CLASS_NAME, DAFNY_TUPLE0_CLASS_NAME); + .addStatement("return $T.create_Success($L, Error._typeDescriptor(), $T.create())", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor, + DAFNY_TUPLE0_CLASS_NAME); } else { // operation is not void + successTypeDescriptor = subject.dafnyNameResolver.typeDescriptor(outputResolved.resolvedId()); TypeName nativeOutputType = preferNativeInterface(outputResolved, subject); method .addStatement(declareNativeOutputAndInvoke(operationName, nativeOutputType)) .addStatement(declareDafnyOutputAndConvert(outputResolved, subject)) - .addStatement("return $T.create_Success($L)", - DAFNY_RESULT_CLASS_NAME, DAFNY_OUTPUT); + .addStatement("return $T.create_Success($L, Error._typeDescriptor(), $L)", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor, + DAFNY_OUTPUT); } // catch Errors in this Namespace method .nextControlFlow("catch ($T ex)", ClassName.get(RuntimeException.class)) - .addStatement("return $T.create_Failure($T.Error(ex))", - DAFNY_RESULT_CLASS_NAME, shimLibrary.toDafnyClassName) + .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), $T.Error(ex))", + DAFNY_RESULT_CLASS_NAME, successTypeDescriptor, shimLibrary.toDafnyClassName) .endControlFlow(); return method.build(); } From fe5f975fb180be8fe57caf0c907bf9143c07cadf Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 23 Oct 2023 14:24:23 -0700 Subject: [PATCH 04/49] Handle aggregate type descriptors in general --- .../internaldafny/wrapped/__default.java | 2 +- .../polymorph/smithyjava/nameresolver/Dafny.java | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java b/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java index 56499c7b9..876c16b3d 100644 --- a/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java +++ b/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleConstraints(S simple.constraints.model.SimpleConstraintsConfig wrappedConfig = ToNative.SimpleConstraintsConfig(config); simple.constraints.SimpleConstraints impl = SimpleConstraints.builder().SimpleConstraintsConfig(wrappedConfig).build(); TestSimpleConstraints wrappedClient = TestSimpleConstraints.builder().impl(impl).build(); - return Result.create_Success(wrappedClient); + return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleConstraintsClient.class), Error._typeDescriptor(), wrappedClient); } } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index c80a984c7..76caa6b4a 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -259,6 +259,19 @@ public CodeBlock typeDescriptor(ShapeId shapeId) { return CodeBlock.of("$L", typeDescriptor); } } + if (shape.getType().isShapeType(ShapeType.LIST)) { + CodeBlock elementTypeDescriptor = typeDescriptor(shape.asListShape().get().getMember().getTarget()); + return CodeBlock.of("$T._typeDescriptor($L)", Constants.DAFNY_SEQUENCE_CLASS_NAME, elementTypeDescriptor); + } + if (shape.getType().isShapeType(ShapeType.SET)) { + CodeBlock elementTypeDescriptor = typeDescriptor(shape.asSetShape().get().getMember().getTarget()); + return CodeBlock.of("$T._typeDescriptor($L)", Constants.DAFNY_SET_CLASS_NAME, elementTypeDescriptor); + } + if (shape.getType().isShapeType(ShapeType.MAP)) { + CodeBlock keyTypeDescriptor = typeDescriptor(shape.asMapShape().get().getKey().getTarget()); + CodeBlock valueTypeDescriptor = typeDescriptor(shape.asMapShape().get().getValue().getTarget()); + return CodeBlock.of("$T._typeDescriptor($L, $L)", Constants.DAFNY_MAP_CLASS_NAME, keyTypeDescriptor, valueTypeDescriptor); + } return CodeBlock.of("$L()", new MethodReference(classForNotErrorNotUnitShape(shape), "_typeDescriptor").asNormalReference()); } From ea48656c97c8bdeb35a56a611eaf7768b12a2217 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 23 Oct 2023 14:59:21 -0700 Subject: [PATCH 05/49] Fix KMS --- .../services/kms/internal/__default.java | 16 ++++++------ .../generator/awssdk/v1/ToDafnyAwsV1.java | 9 ++++--- .../generator/awssdk/v2/ShimV2.java | 25 +++++++++++++------ .../generator/awssdk/v2/ToDafnyAwsV2.java | 7 ++++-- .../smithyjava/nameresolver/Dafny.java | 2 +- 5 files changed, 37 insertions(+), 22 deletions(-) diff --git a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java index 80d531aea..e8ac4e935 100644 --- a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java +++ b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java @@ -26,11 +26,11 @@ public static Result KMSClient() { String region = regionProvider.getRegion().toString(); KmsClient client = builder.build(); IKMSClient shim = new Shim(client, region); - return Result.create_Success(shim); + return Result.create_Success(dafny.TypeDescriptor.reference(IKMSClient.class), Error._typeDescriptor(), shim); } catch (Exception e) { Error dafny_error = Error.create_KMSInternalException( - Option.create_Some(CharacterSequence(e.getMessage()))); - return Result.create_Failure(dafny_error); + Option.create_Some(dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR), CharacterSequence(e.getMessage()))); + return Result.create_Failure(dafny.TypeDescriptor.reference(IKMSClient.class), Error._typeDescriptor(), dafny_error); } } @@ -39,11 +39,11 @@ public static Result KMSClient(final String region) { KmsClientBuilder builder = KmsClient.builder(); KmsClient client = builder.region(Region.of(region)).build(); IKMSClient shim = new Shim(client, region); - return Result.create_Success(shim); + return Result.create_Success(dafny.TypeDescriptor.reference(IKMSClient.class), Error._typeDescriptor(), shim); } catch (Exception e) { Error dafny_error = Error.create_KMSInternalException( - Option.create_Some(CharacterSequence(e.getMessage()))); - return Result.create_Failure(dafny_error); + Option.create_Some(dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR), CharacterSequence(e.getMessage()))); + return Result.create_Failure(dafny.TypeDescriptor.reference(IKMSClient.class), Error._typeDescriptor(), dafny_error); } } @@ -60,13 +60,13 @@ public static Wrappers_Compile.Option RegionMatch( // have no way to determine what region it is // configured with. if (shim.region() == null) { - return Option.create_None(); + return Option.create_None(dafny.TypeDescriptor.BOOLEAN); } // Otherwise we kept record of the region // when we created the client. String shimRegion = shim.region(); String regionStr = String(region); - return Option.create_Some(regionStr.equals(shimRegion)); + return Option.create_Some(dafny.TypeDescriptor.BOOLEAN, regionStr.equals(shimRegion)); } } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ToDafnyAwsV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ToDafnyAwsV1.java index f7db9644f..36f28c5de 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ToDafnyAwsV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ToDafnyAwsV1.java @@ -24,6 +24,7 @@ import software.amazon.polymorph.smithyjava.generator.ToDafny; import software.amazon.polymorph.smithyjava.nameresolver.Constants; +import software.amazon.polymorph.smithyjava.nameresolver.Dafny; import software.amazon.polymorph.utils.AwsSdkNameResolverHelpers; import software.amazon.polymorph.utils.DafnyNameResolverHelpers; import software.amazon.polymorph.utils.ModelUtils; @@ -346,17 +347,19 @@ MethodSpec generateConvertOpaqueError() { ); // This is memberAssignment from above, // but with calls to dafnyNameResolver replaced with their expected response. -// CodeBlock typeDescriptor = subject.dafnyNameResolver.typeDescriptor(ShapeType.STRING); + CodeBlock stringTypeDescriptor = Dafny.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING); CodeBlock memberAssignment = CodeBlock.of( - "$L = $T.nonNull($L) ?\n$T.create_Some($T.$L($L))\n: $T.create_None()", + "$L = $T.nonNull($L) ?\n$T.create_Some($L, $T.$L($L))\n: $T.create_None($L)", "message", ClassName.get(Objects.class), "nativeValue.getMessage()", ClassName.get("Wrappers_Compile", "Option"), + stringTypeDescriptor, COMMON_TO_DAFNY_SIMPLE, SIMPLE_CONVERSION_METHOD_FROM_SHAPE_TYPE.get(ShapeType.STRING).methodName(), "nativeValue.getMessage()", - ClassName.get("Wrappers_Compile", "Option") + ClassName.get("Wrappers_Compile", "Option"), + stringTypeDescriptor ); return MethodSpec.methodBuilder("Error") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java index 9206fc1c2..a17c8d639 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java @@ -3,6 +3,7 @@ package software.amazon.polymorph.smithyjava.generator.awssdk.v2; import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeName; @@ -138,20 +139,26 @@ Optional operation(final ShapeId operationShapeId) { subject.nativeNameResolver.typeForShape(inputShapeId), StringUtils.capitalize(inputShapeId.getName())) .beginControlFlow("try"); + CodeBlock successTypeDescriptor; if (outputShapeId.equals(SMITHY_API_UNIT)) { + successTypeDescriptor = CodeBlock.of(DAFNY_TUPLE0_CLASS_NAME + "._typeDescriptor()"); builder.addStatement("_impl.$L(converted)", StringUtils.uncapitalize(operationName)) - .addStatement("return $T.create_Success($T.create())", - DAFNY_RESULT_CLASS_NAME, DAFNY_TUPLE0_CLASS_NAME); + .addStatement("return $T.create_Success($L, Error._typeDescriptor(), $T.create())", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor, + DAFNY_TUPLE0_CLASS_NAME); } else { + successTypeDescriptor = subject.dafnyNameResolver.typeDescriptor(outputShapeId); builder.addStatement("$T result = _impl.$L(converted)", subject.nativeNameResolver.typeForOperationOutput(outputShapeId), StringUtils.uncapitalize(operationName)) .addStatement("$T dafnyResponse = ToDafny.$L(result)", dafnyOutput, StringUtils.capitalize(outputShapeId.getName())) - .addStatement("return $T.create_Success(dafnyResponse)", - DAFNY_RESULT_CLASS_NAME); + .addStatement("return $T.create_Success($L, Error._typeDescriptor(), dafnyResponse)", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor); } operationShape.getErrors().stream().sorted().forEach(shapeId -> { @@ -164,13 +171,15 @@ Optional operation(final ShapeId operationShapeId) { builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.typeForShape(shapeId)) - .addStatement("return $T.create_Failure(Error._typeDescriptor(), ToDafny.Error(ex))", - DAFNY_RESULT_CLASS_NAME); + .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), ToDafny.Error(ex))", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor); }); return Optional.of(builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.baseErrorForService()) - .addStatement("return $T.create_Failure(Error._typeDescriptor(), ToDafny.Error(ex))", - DAFNY_RESULT_CLASS_NAME) + .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), ToDafny.Error(ex))", + DAFNY_RESULT_CLASS_NAME, + successTypeDescriptor) .endControlFlow() .build()); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2.java index e2e24c408..4416cb78a 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2.java @@ -520,16 +520,19 @@ MethodSpec generateConvertOpaqueError() { ); // This is memberAssignment from above, // but with calls to dafnyNameResolver replaced with their expected response. + CodeBlock stringTypeDescriptor = Dafny.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING); CodeBlock memberAssignment = CodeBlock.of( - "$L = $T.nonNull($L) ?\n$T.create_Some($T.$L($L))\n: $T.create_None()", + "$L = $T.nonNull($L) ?\n$T.create_Some($L, $T.$L($L))\n: $T.create_None($L)", "message", ClassName.get(Objects.class), "nativeValue.getMessage()", ClassName.get("Wrappers_Compile", "Option"), + stringTypeDescriptor, COMMON_TO_DAFNY_SIMPLE, SIMPLE_CONVERSION_METHOD_FROM_SHAPE_TYPE.get(ShapeType.STRING).methodName(), "nativeValue.getMessage()", - ClassName.get("Wrappers_Compile", "Option") + ClassName.get("Wrappers_Compile", "Option"), + stringTypeDescriptor ); return MethodSpec.methodBuilder("Error") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index 76caa6b4a..6c7bc51c7 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -49,7 +49,7 @@ public class Dafny extends NameResolver { @SuppressWarnings("unused") private static final Logger LOGGER = LoggerFactory.getLogger(Dafny.class); - protected static final Map TYPE_DESCRIPTOR_BY_SHAPE_TYPE; + public static final Map TYPE_DESCRIPTOR_BY_SHAPE_TYPE; static { TYPE_DESCRIPTOR_BY_SHAPE_TYPE = Map.ofEntries( Map.entry(ShapeType.STRING, CodeBlock.of("$T._typeDescriptor($T.CHAR)", Constants.DAFNY_SEQUENCE_CLASS_NAME, Constants.DAFNY_TYPE_DESCRIPTOR_CLASS_NAME)), From 6ba962dd9afb905a3ef6f80fd0289156cb54142a Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 23 Oct 2023 15:06:33 -0700 Subject: [PATCH 06/49] Fix a few more model tests --- .../java/simple/errors/internaldafny/wrapped/__default.java | 2 +- .../simple/localservice/internaldafny/wrapped/__default.java | 2 +- .../services/dynamodb/internaldafny/__default.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java b/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java index 36610d07d..d2af0bbe8 100644 --- a/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java +++ b/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleErrors(SimpleError simple.errors.model.SimpleErrorsConfig wrappedConfig = ToNative.SimpleErrorsConfig(config); simple.errors.SimpleErrors impl = SimpleErrors.builder().SimpleErrorsConfig(wrappedConfig).build(); TestSimpleErrors wrappedClient = TestSimpleErrors.builder().impl(impl).build(); - return Result.create_Success(wrappedClient); + return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleErrorsClient.class), Error._typeDescriptor(), wrappedClient); } } diff --git a/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java b/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java index 51e85a21f..36f4697fd 100644 --- a/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java +++ b/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java @@ -18,7 +18,7 @@ public static Result WrappedSimpleLocalService simple.localservice.SimpleLocalService impl = SimpleLocalService.builder().SimpleLocalServiceConfig(wrappedConfig).build(); TestToNativeAndToDafnyLocalService(impl); TestSimpleLocalService wrappedClient = TestSimpleLocalService.builder().impl(impl).build(); - return Result.create_Success(wrappedClient); + return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleLocalServiceClient.class), Error._typeDescriptor(), wrappedClient); } // TODO: Determine how to replace this test with Dafny Source Code diff --git a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java index 926b5bd27..2f504c402 100644 --- a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java +++ b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java @@ -25,11 +25,11 @@ public static Result DynamoDBClient() { .build(); IDynamoDBClient shim = new Shim(ddbClient, region.toString()); - return Result.create_Success(shim); + return Result.create_Success(dafny.TypeDescriptor.reference(IDynamoDBClient.class), Error._typeDescriptor(), shim); } catch (Exception e) { Error dafny_error = Error.create_InternalServerError( Option.create_Some(CharacterSequence(e.getMessage()))); - return Result.create_Failure(dafny_error); + return Result.create_Failure(dafny.TypeDescriptor.reference(IDynamoDBClient.class), Error._typeDescriptor(), dafny_error); } } } From e841a8a81fc4aeb5fced7d262ff6031c0b22b85b Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 23 Oct 2023 15:14:51 -0700 Subject: [PATCH 07/49] Missing file --- .../extendable/resources/internaldafny/wrapped/__default.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java b/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java index 43c0d85f4..c56f6b616 100644 --- a/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java +++ b/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java @@ -22,7 +22,7 @@ public static Result WrappedSimpleExten simple.extendable.resources.model.SimpleExtendableResourcesConfig wrappedConfig = ToNative.SimpleExtendableResourcesConfig(config); simple.extendable.resources.SimpleExtendableResources impl = SimpleExtendableResources.builder().SimpleExtendableResourcesConfig(wrappedConfig).build(); TestSimpleExtendableResources wrappedClient = TestSimpleExtendableResources.builder().impl(impl).build(); - return Result.create_Success(wrappedClient); + return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleExtendableResourcesClient.class), Error._typeDescriptor(), wrappedClient); } /** From 213da2b66c6ee4eef6a3532badaca3bd4717a517 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 23 Oct 2023 15:21:25 -0700 Subject: [PATCH 08/49] Missed one in DDB --- .../cryptography/services/dynamodb/internaldafny/__default.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java index 2f504c402..03875861c 100644 --- a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java +++ b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java @@ -28,7 +28,7 @@ public static Result DynamoDBClient() { return Result.create_Success(dafny.TypeDescriptor.reference(IDynamoDBClient.class), Error._typeDescriptor(), shim); } catch (Exception e) { Error dafny_error = Error.create_InternalServerError( - Option.create_Some(CharacterSequence(e.getMessage()))); + Option.create_Some(dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR), CharacterSequence(e.getMessage()))); return Result.create_Failure(dafny.TypeDescriptor.reference(IDynamoDBClient.class), Error._typeDescriptor(), dafny_error); } } From 0a24bc8ce9f19bed9772265658075b13fdd605a9 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Sat, 28 Oct 2023 14:43:41 -0700 Subject: [PATCH 09/49] Add dafnyVersion parameter, make type descriptors conditional --- .../amazon/polymorph/CodegenEngine.java | 23 ++++++- .../smithyjava/generator/ToDafny.java | 9 +-- .../generator/awssdk/v1/ShimV1.java | 29 ++++---- .../generator/awssdk/v2/JavaAwsSdkV2.java | 4 +- .../generator/awssdk/v2/ShimV2.java | 29 ++++---- .../generator/awssdk/v2/ToDafnyAwsV2.java | 15 ++-- .../generator/library/JavaLibrary.java | 8 +-- .../generator/library/TestJavaLibrary.java | 4 +- .../smithyjava/modeled/Operation.java | 22 +++--- .../nameresolver/AwsSdkDafnyV1.java | 4 +- .../nameresolver/AwsSdkDafnyV2.java | 4 +- .../smithyjava/nameresolver/Constants.java | 1 + .../smithyjava/nameresolver/Dafny.java | 69 ++++++++++++++++++- .../codegen/DafnyClientCodegenEdition.java | 5 +- .../DafnyClientCodegenPluginSettings.java | 25 ++++++- .../smithyjava/ForEachDafnyTest.java | 19 +++++ .../generator/awssdk/TestSetupUtils.java | 8 +-- .../generator/awssdk/v2/ShimTest.java | 10 +-- .../generator/awssdk/v2/ToDafnyAwsV2Test.java | 16 +++-- .../generator/awssdk/v2/ToNativeTest.java | 18 +++-- .../generator/library/ModelCodegenTest.java | 8 +-- .../smithyjava/nameresolver/DafnyTest.java | 13 ++-- 22 files changed, 244 insertions(+), 99 deletions(-) create mode 100644 codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/CodegenEngine.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/CodegenEngine.java index 556d07511..4785710f6 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/CodegenEngine.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/CodegenEngine.java @@ -41,6 +41,7 @@ public class CodegenEngine { private final Path[] dependentModelPaths; private final String namespace; private final Map targetLangOutputDirs; + private final String dafnyVersion; // refactor this to only be required if generating Java private final AwsSdkVersion javaAwsSdkVersion; private final Optional includeDafnyFile; @@ -62,6 +63,7 @@ private CodegenEngine( final Path[] dependentModelPaths, final String namespace, final Map targetLangOutputDirs, + final String dafnyVersion, final AwsSdkVersion javaAwsSdkVersion, final Optional includeDafnyFile, final boolean awsSdkStyle, @@ -72,6 +74,7 @@ private CodegenEngine( this.dependentModelPaths = dependentModelPaths; this.namespace = namespace; this.targetLangOutputDirs = targetLangOutputDirs; + this.dafnyVersion = dafnyVersion; this.javaAwsSdkVersion = javaAwsSdkVersion; this.includeDafnyFile = includeDafnyFile; this.awsSdkStyle = awsSdkStyle; @@ -150,13 +153,13 @@ private void generateJava(final Path outputDir) { } private void javaLocalService(final Path outputDir) { - final JavaLibrary javaLibrary = new JavaLibrary(this.model, this.serviceShape, this.javaAwsSdkVersion); + final JavaLibrary javaLibrary = new JavaLibrary(this.model, this.serviceShape, this.javaAwsSdkVersion, this.dafnyVersion); IOUtils.writeTokenTreesIntoDir(javaLibrary.generate(), outputDir); LOGGER.info("Java code generated in {}", outputDir); } private void javaWrappedLocalService(final Path outputDir) { - final TestJavaLibrary testJavaLibrary = new TestJavaLibrary(model, serviceShape, this.javaAwsSdkVersion); + final TestJavaLibrary testJavaLibrary = new TestJavaLibrary(model, serviceShape, this.javaAwsSdkVersion, this.dafnyVersion); IOUtils.writeTokenTreesIntoDir(testJavaLibrary.generate(), outputDir); LOGGER.info("Java that tests a local service generated in {}", outputDir); } @@ -168,7 +171,7 @@ private void javaAwsSdkV1(Path outputDir) { } private void javaAwsSdkV2(final Path outputDir) { - final JavaAwsSdkV2 javaV2ShimCodegen = JavaAwsSdkV2.createJavaAwsSdkV2(serviceShape, model); + final JavaAwsSdkV2 javaV2ShimCodegen = JavaAwsSdkV2.createJavaAwsSdkV2(serviceShape, model, dafnyVersion); IOUtils.writeTokenTreesIntoDir(javaV2ShimCodegen.generate(), outputDir); LOGGER.info("Java V2 code generated in {}", outputDir); } @@ -245,6 +248,7 @@ public static class Builder { private Path[] dependentModelPaths; private String namespace; private Map targetLangOutputDirs; + private String dafnyVersion = "4.1.0"; private AwsSdkVersion javaAwsSdkVersion = AwsSdkVersion.V2; private Path includeDafnyFile; private boolean awsSdkStyle = false; @@ -286,6 +290,17 @@ public Builder withTargetLangOutputDirs(final Map targetLa return this; } + /** + * Sets the Dafny version for which generated code should be compatible. + * This is used to ensure both Dafny source compatibility + * and compatibility with the Dafny compiler and runtime internals, + * which shim code generation currently depends on. + */ + public Builder withDafnyVersion(final String dafnyVersion) { + this.dafnyVersion = dafnyVersion; + return this; + } + /** * Sets the version of the AWS SDK for Java for which generated code should be compatible. * This has no effect unless the engine is configured to generate Java code. @@ -341,6 +356,7 @@ public CodegenEngine build() { targetLangOutputDirsRaw.replaceAll((_lang, path) -> path.toAbsolutePath().normalize()); final Map targetLangOutputDirs = ImmutableMap.copyOf(targetLangOutputDirsRaw); + final String dafnyVersion = Objects.requireNonNull(this.dafnyVersion); final AwsSdkVersion javaAwsSdkVersion = Objects.requireNonNull(this.javaAwsSdkVersion); if (targetLangOutputDirs.containsKey(TargetLanguage.DAFNY) @@ -360,6 +376,7 @@ public CodegenEngine build() { dependentModelPaths, this.namespace, targetLangOutputDirs, + dafnyVersion, javaAwsSdkVersion, includeDafnyFile, this.awsSdkStyle, diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/ToDafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/ToDafny.java index c8af80d9a..18908b869 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/ToDafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/ToDafny.java @@ -196,14 +196,11 @@ protected CodeBlock memberAssign( } CodeBlock typeDescriptor = subject.dafnyNameResolver.typeDescriptor(memberShape.getTarget()); return CodeBlock.of( - "$L = $L ?\n$T.create_Some($L, $L)\n: $T.create_None($L)", + "$L = $L ?\n$L\n: $L", outputVar, isSetCheck, - ClassName.get("Wrappers_Compile", "Option"), - typeDescriptor, - memberConversion, - ClassName.get("Wrappers_Compile", "Option"), - typeDescriptor + subject.dafnyNameResolver.createSome(typeDescriptor, memberConversion), + subject.dafnyNameResolver.createNone(typeDescriptor) ); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java index 8d36456b7..6fa12edf5 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java @@ -144,10 +144,10 @@ Optional operation(final ShapeId operationShapeId) { successTypeDescriptor = CodeBlock.of(DAFNY_TUPLE0_CLASS_NAME + "._typeDescriptor()"); builder.addStatement("_impl.$L(converted)", StringUtils.uncapitalize(operationName)) - .addStatement("return $T.create_Success($L, Error._typeDescriptor(), $T.create())", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor, - DAFNY_TUPLE0_CLASS_NAME); + .addStatement("return $L", + subject.dafnyNameResolver.createSuccess( + successTypeDescriptor, + CodeBlock.of("$T.create()", DAFNY_TUPLE0_CLASS_NAME))); } else { successTypeDescriptor = subject.dafnyNameResolver.typeDescriptor(outputShapeId); builder.addStatement("$T result = _impl.$L(converted)", @@ -156,23 +156,26 @@ Optional operation(final ShapeId operationShapeId) { .addStatement("$T dafnyResponse = ToDafny.$L(result)", dafnyOutput, StringUtils.capitalize(outputShapeId.getName())) - .addStatement("return $T.create_Success($L, Error._typeDescriptor(), dafnyResponse)", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor); + .addStatement("return $L", + subject.dafnyNameResolver.createSuccess( + successTypeDescriptor, + CodeBlock.of("dafnyResponse"))); } operationShape.getErrors().stream().sorted().forEach(shapeId -> builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.typeForShape(shapeId)) - .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), ToDafny.Error(ex))", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor) + .addStatement("return $L", + subject.dafnyNameResolver.createFailure( + successTypeDescriptor, + CodeBlock.of("ToDafny.Error(ex)"))) ); return Optional.of(builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.baseErrorForService()) - .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), ToDafny.Error(ex))", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor) + .addStatement("return $L", + subject.dafnyNameResolver.createFailure( + successTypeDescriptor, + CodeBlock.of("ToDafny.Error(ex)"))) .endControlFlow() .build()); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/JavaAwsSdkV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/JavaAwsSdkV2.java index 28e45b6a2..4651bda80 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/JavaAwsSdkV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/JavaAwsSdkV2.java @@ -47,8 +47,8 @@ private JavaAwsSdkV2( this.packageName = dafnyNameResolver.packageName(); } - public static JavaAwsSdkV2 createJavaAwsSdkV2(ServiceShape serviceShape, Model model) { - final AwsSdkDafnyV2 dafnyNameResolver = new AwsSdkDafnyV2(serviceShape, model); + public static JavaAwsSdkV2 createJavaAwsSdkV2(ServiceShape serviceShape, Model model, String dafnyVersion) { + final AwsSdkDafnyV2 dafnyNameResolver = new AwsSdkDafnyV2(serviceShape, model, dafnyVersion); final AwsSdkNativeV2 nativeNameResolver = new AwsSdkNativeV2(serviceShape, model); return new JavaAwsSdkV2(serviceShape, model, dafnyNameResolver, nativeNameResolver); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java index a17c8d639..e36eb3ee0 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java @@ -144,10 +144,10 @@ Optional operation(final ShapeId operationShapeId) { successTypeDescriptor = CodeBlock.of(DAFNY_TUPLE0_CLASS_NAME + "._typeDescriptor()"); builder.addStatement("_impl.$L(converted)", StringUtils.uncapitalize(operationName)) - .addStatement("return $T.create_Success($L, Error._typeDescriptor(), $T.create())", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor, - DAFNY_TUPLE0_CLASS_NAME); + .addStatement("return $L", + subject.dafnyNameResolver.createSuccess( + successTypeDescriptor, + CodeBlock.of("$T.create()", DAFNY_TUPLE0_CLASS_NAME))); } else { successTypeDescriptor = subject.dafnyNameResolver.typeDescriptor(outputShapeId); builder.addStatement("$T result = _impl.$L(converted)", @@ -156,9 +156,10 @@ Optional operation(final ShapeId operationShapeId) { .addStatement("$T dafnyResponse = ToDafny.$L(result)", dafnyOutput, StringUtils.capitalize(outputShapeId.getName())) - .addStatement("return $T.create_Success($L, Error._typeDescriptor(), dafnyResponse)", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor); + .addStatement("return $L", + subject.dafnyNameResolver.createSuccess( + successTypeDescriptor, + CodeBlock.of("dafnyResponse"))); } operationShape.getErrors().stream().sorted().forEach(shapeId -> { @@ -171,15 +172,17 @@ Optional operation(final ShapeId operationShapeId) { builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.typeForShape(shapeId)) - .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), ToDafny.Error(ex))", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor); + .addStatement("return $L", + subject.dafnyNameResolver.createFailure( + successTypeDescriptor, + CodeBlock.of("ToDafny.Error(ex)"))); }); return Optional.of(builder .nextControlFlow("catch ($T ex)", subject.nativeNameResolver.baseErrorForService()) - .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), ToDafny.Error(ex))", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor) + .addStatement("return $L", + subject.dafnyNameResolver.createFailure( + successTypeDescriptor, + CodeBlock.of("ToDafny.Error(ex)"))) .endControlFlow() .build()); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2.java index 4416cb78a..1d830b5d4 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2.java @@ -522,17 +522,16 @@ MethodSpec generateConvertOpaqueError() { // but with calls to dafnyNameResolver replaced with their expected response. CodeBlock stringTypeDescriptor = Dafny.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING); CodeBlock memberAssignment = CodeBlock.of( - "$L = $T.nonNull($L) ?\n$T.create_Some($L, $T.$L($L))\n: $T.create_None($L)", + "$L = $T.nonNull($L) ?\n$L\n: $L", "message", ClassName.get(Objects.class), "nativeValue.getMessage()", - ClassName.get("Wrappers_Compile", "Option"), - stringTypeDescriptor, - COMMON_TO_DAFNY_SIMPLE, - SIMPLE_CONVERSION_METHOD_FROM_SHAPE_TYPE.get(ShapeType.STRING).methodName(), - "nativeValue.getMessage()", - ClassName.get("Wrappers_Compile", "Option"), - stringTypeDescriptor + subject.dafnyNameResolver.createSome(stringTypeDescriptor, + CodeBlock.of("$T.$L($L)", + COMMON_TO_DAFNY_SIMPLE, + SIMPLE_CONVERSION_METHOD_FROM_SHAPE_TYPE.get(ShapeType.STRING).methodName(), + "nativeValue.getMessage()")), + subject.dafnyNameResolver.createNone(stringTypeDescriptor) ); return MethodSpec.methodBuilder("Error") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/JavaLibrary.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/JavaLibrary.java index 4c29f856f..4b8c332d6 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/JavaLibrary.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/JavaLibrary.java @@ -61,8 +61,8 @@ public class JavaLibrary extends CodegenSubject { public final ToDafnyLibrary toDafnyLibrary; public final ToNativeLibrary toNativeLibrary; - public JavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVersion) { - super(model, serviceShape, initDafny(model, serviceShape, sdkVersion), initNative(model, serviceShape, sdkVersion), sdkVersion); + public JavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVersion, String dafnyVersion) { + super(model, serviceShape, initDafny(model, serviceShape, sdkVersion, dafnyVersion), initNative(model, serviceShape, sdkVersion), sdkVersion); packageName = NamespaceHelper.standardize(serviceShape.getId().getNamespace()); modelPackageName = packageName + ".model"; try { @@ -77,9 +77,9 @@ public JavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVers toNativeLibrary = new ToNativeLibrary(this); } - static Dafny initDafny(Model model, ServiceShape serviceShape, AwsSdkVersion awsSdkVersion) { + static Dafny initDafny(Model model, ServiceShape serviceShape, AwsSdkVersion awsSdkVersion, String dafnyVersion) { String packageName = DafnyNameResolverHelpers.packageNameForNamespace(serviceShape.getId().getNamespace()); - return new Dafny(packageName, model, serviceShape, awsSdkVersion); + return new Dafny(packageName, model, serviceShape, awsSdkVersion, dafnyVersion); } static Native initNative(Model model, ServiceShape serviceShape, AwsSdkVersion awsSdkVersion) { diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/TestJavaLibrary.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/TestJavaLibrary.java index d2926fc38..34b06c7d8 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/TestJavaLibrary.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/TestJavaLibrary.java @@ -19,8 +19,8 @@ public class TestJavaLibrary extends JavaLibrary { @SuppressWarnings("unused") private static final Logger LOGGER = LoggerFactory.getLogger(TestJavaLibrary.class); - public TestJavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVersion) { - super(model, serviceShape, sdkVersion); + public TestJavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVersion, String dafnyVersion) { + super(model, serviceShape, sdkVersion, dafnyVersion); } @Override diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/modeled/Operation.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/modeled/Operation.java index e58a88028..ef75c1283 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/modeled/Operation.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/modeled/Operation.java @@ -63,10 +63,10 @@ public static MethodSpec operation( successTypeDescriptor = CodeBlock.of("dafny.Tuple0._typeDescriptor()"); method .addStatement(invoke(operationName)) - .addStatement("return $T.create_Success($L, Error._typeDescriptor(), $T.create())", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor, - DAFNY_TUPLE0_CLASS_NAME); + .addStatement("return $L", + subject.dafnyNameResolver.createSuccess( + successTypeDescriptor, + CodeBlock.of("$T.create()", DAFNY_TUPLE0_CLASS_NAME))); } else { // operation is not void successTypeDescriptor = subject.dafnyNameResolver.typeDescriptor(outputResolved.resolvedId()); @@ -74,17 +74,19 @@ public static MethodSpec operation( method .addStatement(declareNativeOutputAndInvoke(operationName, nativeOutputType)) .addStatement(declareDafnyOutputAndConvert(outputResolved, subject)) - .addStatement("return $T.create_Success($L, Error._typeDescriptor(), $L)", - DAFNY_RESULT_CLASS_NAME, - successTypeDescriptor, - DAFNY_OUTPUT); + .addStatement("return $L", + subject.dafnyNameResolver.createSuccess( + successTypeDescriptor, + CodeBlock.of(DAFNY_OUTPUT))); } // catch Errors in this Namespace method .nextControlFlow("catch ($T ex)", ClassName.get(RuntimeException.class)) - .addStatement("return $T.create_Failure($L, Error._typeDescriptor(), $T.Error(ex))", - DAFNY_RESULT_CLASS_NAME, successTypeDescriptor, shimLibrary.toDafnyClassName) + .addStatement("return $L", + subject.dafnyNameResolver.createFailure( + successTypeDescriptor, + CodeBlock.of("$T.Error(ex)", shimLibrary.toDafnyClassName))) .endControlFlow(); return method.build(); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV1.java index e1bdfa790..a2b3bbfc9 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV1.java @@ -18,8 +18,8 @@ public class AwsSdkDafnyV1 extends Dafny { - public AwsSdkDafnyV1(ServiceShape serviceShape, Model model) { - super(packageNameForServiceShape(serviceShape), model, serviceShape, CodegenSubject.AwsSdkVersion.V1); + public AwsSdkDafnyV1(ServiceShape serviceShape, Model model, String dafnyVersion) { + super(packageNameForServiceShape(serviceShape), model, serviceShape, CodegenSubject.AwsSdkVersion.V1, dafnyVersion); } @Override diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV2.java index 496ddbc16..f735a5185 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV2.java @@ -25,8 +25,8 @@ public class AwsSdkDafnyV2 extends Dafny { - public AwsSdkDafnyV2(ServiceShape serviceShape, Model model) { - super(packageNameForServiceShape(serviceShape), model, serviceShape, CodegenSubject.AwsSdkVersion.V2); + public AwsSdkDafnyV2(ServiceShape serviceShape, Model model, String dafnyVersion) { + super(packageNameForServiceShape(serviceShape), model, serviceShape, CodegenSubject.AwsSdkVersion.V2, dafnyVersion); } @Override diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Constants.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Constants.java index de79b77c8..9739abe8e 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Constants.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Constants.java @@ -11,6 +11,7 @@ public class Constants { public static final ShapeId SMITHY_API_UNIT = ShapeId.fromParts("smithy.api", "Unit"); + public static final ClassName DAFNY_OPTION_CLASS_NAME = ClassName.get("Wrappers_Compile", "Option"); public static final ClassName DAFNY_RESULT_CLASS_NAME = ClassName.get("Wrappers_Compile", "Result"); public static final ClassName DAFNY_TUPLE0_CLASS_NAME = ClassName.get("dafny", "Tuple0"); public static final ClassName DAFNY_TYPE_DESCRIPTOR_CLASS_NAME = ClassName.get("dafny", "TypeDescriptor"); diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index 6c7bc51c7..3f337f552 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -65,17 +65,21 @@ public class Dafny extends NameResolver { ); } + private final String dafnyVersion; + public Dafny( final String packageName, final Model model, final ServiceShape serviceShape, - CodegenSubject.AwsSdkVersion awsSdkVersion) { + CodegenSubject.AwsSdkVersion awsSdkVersion, + final String dafnyVersion) { super( packageName, serviceShape, model, modelPackageNameForServiceShape(serviceShape), awsSdkVersion); + this.dafnyVersion = dafnyVersion; } /** @@ -92,6 +96,69 @@ public static String datatypeConstructorCreate(String name, boolean isRecordType return "create_" + DafnyNameResolverHelpers.dafnyCompilesExtra_(name); } + private boolean datatypeConstructorsNeedTypeDescriptors() { + // TODO: proper version comparison + return dafnyVersion.compareTo("4.2") >= 0; + } + + public CodeBlock createNone(CodeBlock typeDescriptor) { + if (datatypeConstructorsNeedTypeDescriptors()) { + return CodeBlock.of( + "$T.create_None($L)", + ClassName.get("Wrappers_Compile", "Option"), + typeDescriptor); + } else { + return CodeBlock.of( + "$T.create_None()", + ClassName.get("Wrappers_Compile", "Option")); + } + } + + public CodeBlock createSome(CodeBlock typeDescriptor, CodeBlock value) { + if (datatypeConstructorsNeedTypeDescriptors()) { + return CodeBlock.of( + "$T.create_Some($L, $L)", + Constants.DAFNY_OPTION_CLASS_NAME, + typeDescriptor, + value); + } else { + return CodeBlock.of( + "$T.create_Some($L)", + Constants.DAFNY_OPTION_CLASS_NAME, + value); + } + } + + public CodeBlock createSuccess(CodeBlock valueTypeDescriptor, CodeBlock value) { + if (datatypeConstructorsNeedTypeDescriptors()) { + return CodeBlock.of( + "$T.create_Success($L, Error._typeDescriptor(), $L)", + Constants.DAFNY_RESULT_CLASS_NAME, + valueTypeDescriptor, + value); + } else { + return CodeBlock.of( + "$T.create_Success($L)", + Constants.DAFNY_RESULT_CLASS_NAME, + value); + } + } + + public CodeBlock createFailure(CodeBlock typeDescriptor, CodeBlock error) { + if (datatypeConstructorsNeedTypeDescriptors()) { + return CodeBlock.of( + "$T.create_Failure($L, Error._typeDescriptor(), $L)", + Constants.DAFNY_RESULT_CLASS_NAME, + typeDescriptor, + error); + } else { + return CodeBlock.of( + "$T.create_Failure($L)", + Constants.DAFNY_RESULT_CLASS_NAME, + error); + } + } + public static String datatypeConstructorIs(String name) { String dafnyEnumName = DafnyNameResolverHelpers.dafnyCompilesExtra_(name); return "is_" + dafnyEnumName; diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenEdition.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenEdition.java index 5cb4dd0f6..a38214176 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenEdition.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenEdition.java @@ -6,7 +6,8 @@ public enum DafnyClientCodegenEdition { // Java identifiers (including enum values) cannot start with a number, but edition names are typically numeric. - EDITION_2023; + EDITION_2023, + EDITION_2023_10; // 2023.10 /** * Returns the enum value corresponding to the given numeric string, e.g. "2023". @@ -15,6 +16,6 @@ public enum DafnyClientCodegenEdition { */ public static DafnyClientCodegenEdition fromNumeric(final String edition) { Objects.requireNonNull(edition); - return DafnyClientCodegenEdition.valueOf("EDITION_" + edition); + return DafnyClientCodegenEdition.valueOf("EDITION_" + edition.replace(".", "_")); } } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenPluginSettings.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenPluginSettings.java index 92b85a11b..1ff8d6ea0 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenPluginSettings.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenPluginSettings.java @@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory; import software.amazon.polymorph.CodegenEngine; import software.amazon.smithy.build.FileManifest; +import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; import software.amazon.smithy.model.node.StringNode; import software.amazon.smithy.model.shapes.ShapeId; @@ -52,16 +53,27 @@ class DafnyClientCodegenPluginSettings { */ public final Path includeDafnyFile; + /** + * The Dafny version to generate code compatible with. + * This is used to ensure both Dafny source compatibility + * and compatibility with the Dafny compiler and runtime internals, + * which shim code generation currently depends on. + * Required when the edition is 2023.10 or later. + */ + public final String dafnyVersion; + private DafnyClientCodegenPluginSettings( final DafnyClientCodegenEdition edition, final ShapeId serviceId, final Set targetLanguages, - final Path includeDafnyFile + final Path includeDafnyFile, + final String dafnyVersion ) { this.edition = edition; this.serviceId = serviceId; this.targetLanguages = targetLanguages; this.includeDafnyFile = includeDafnyFile; + this.dafnyVersion = dafnyVersion; } static Optional fromObject(final ObjectNode node, final FileManifest manifest) { @@ -107,8 +119,17 @@ static Optional fromObject(final ObjectNode no includeDafnyFileNormalized); } + final String dafnyVersion; + if (edition.ordinal() >= DafnyClientCodegenEdition.EDITION_2023_10.ordinal()) { + // Required from this edition on + dafnyVersion = node.expectStringMember("dafnyVersion").getValue(); + } else { + dafnyVersion = node.getStringMemberOrDefault("dafnyVersion", "4.1"); + } + return Optional.of( - new DafnyClientCodegenPluginSettings(edition, serviceId, targetLanguages, includeDafnyFileNormalized)); + new DafnyClientCodegenPluginSettings(edition, serviceId, targetLanguages, includeDafnyFileNormalized, + dafnyVersion)); } /** diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java new file mode 100644 index 000000000..493c2a72e --- /dev/null +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java @@ -0,0 +1,19 @@ +package software.amazon.polymorph.smithyjava; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +public abstract class ForEachDafnyTest { + + @Parameterized.Parameters(name = "dafnyVersion = {0}") + public static Collection dafnies() { + return Arrays.asList(new Object[][] { + { "4.1" }, + { "4.3" }, + }); + } +} diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/TestSetupUtils.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/TestSetupUtils.java index a9f1a0632..793d5ff52 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/TestSetupUtils.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/TestSetupUtils.java @@ -32,13 +32,13 @@ public static JavaAwsSdkV1 setupAwsSdkV1(Model localModel, String awsName) { localModel, namespaceForService(awsName)); return JavaAwsSdkV1.createJavaAwsSdkV1(serviceShape, localModel); } - public static JavaAwsSdkV2 setupAwsSdkV2(Model localModel, String awsName) { + public static JavaAwsSdkV2 setupAwsSdkV2(Model localModel, String awsName, String dafnyVersion) { ServiceShape serviceShape = serviceFromNamespace( localModel, namespaceForService(awsName)); - return JavaAwsSdkV2.createJavaAwsSdkV2(serviceShape, localModel); + return JavaAwsSdkV2.createJavaAwsSdkV2(serviceShape, localModel, dafnyVersion); } - public static JavaLibrary setupLibrary(Model localModel, String namespace) { + public static JavaLibrary setupLibrary(Model localModel, String namespace, String dafnyVersion) { ServiceShape serviceShape = serviceFromNamespace(localModel, namespace); - return new JavaLibrary(localModel, serviceShape, CodegenSubject.AwsSdkVersion.V1); + return new JavaLibrary(localModel, serviceShape, CodegenSubject.AwsSdkVersion.V1, dafnyVersion); } } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java index 2b674170e..153e2d6d4 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java @@ -14,6 +14,9 @@ import javax.lang.model.element.Modifier; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.awssdk.TestSetupUtils; import software.amazon.polymorph.util.Tokenizer; @@ -27,15 +30,14 @@ import static software.amazon.polymorph.smithyjava.generator.awssdk.v2.Constants.DoVoidOperation; import static software.amazon.polymorph.smithyjava.generator.awssdk.v2.Constants.MockKmsShim; -public class ShimTest { +public class ShimTest extends ForEachDafnyTest { protected ShimV2 underTest; protected Model model; protected JavaAwsSdkV2 subject; - @Before - public void setup() { + public ShimTest(String dafnyVersion) { model = TestSetupUtils.setupLocalModel(ModelConstants.MOCK_KMS); - subject = TestSetupUtils.setupAwsSdkV2(model, "kms"); + subject = TestSetupUtils.setupAwsSdkV2(model, "kms", dafnyVersion); underTest = new ShimV2(subject); } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java index 63f97ab54..b59d8ea8a 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java @@ -10,6 +10,7 @@ import java.nio.file.Path; import java.util.Map; +import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.awssdk.TestSetupUtils; import software.amazon.polymorph.utils.TokenTree; @@ -21,14 +22,15 @@ import static org.junit.Assert.assertThrows; import static software.amazon.polymorph.util.Tokenizer.tokenizeAndAssertEqual; -public class ToDafnyAwsV2Test { - protected ToDafnyAwsV2 underTest; - protected Model model; +public class ToDafnyAwsV2Test extends ForEachDafnyTest { + protected final ToDafnyAwsV2 underTest; + protected final Model model; + protected final String dafnyVersion; - @Before - public void setup() { + public ToDafnyAwsV2Test(String dafnyVersion) { + this.dafnyVersion = dafnyVersion; model = TestSetupUtils.setupTwoLocalModel(ModelConstants.KMS_KITCHEN, ModelConstants.OTHER_NAMESPACE); - underTest = new ToDafnyAwsV2(TestSetupUtils.setupAwsSdkV2(model, "kms")); + underTest = new ToDafnyAwsV2(TestSetupUtils.setupAwsSdkV2(model, "kms", dafnyVersion)); } @Test @@ -80,7 +82,7 @@ public void generateConvertOpaqueError() { @Test public void generate() { Model localModel = TestSetupUtils.setupLocalModel(ModelConstants.KMS_A_STRING_OPERATION); - ToDafnyAwsV2 localUnderTest = new ToDafnyAwsV2(TestSetupUtils.setupAwsSdkV2(localModel, "kms")); + ToDafnyAwsV2 localUnderTest = new ToDafnyAwsV2(TestSetupUtils.setupAwsSdkV2(localModel, "kms", dafnyVersion)); final Map actual = localUnderTest.generate(); final Path expectedPath = Path.of("software/amazon/cryptography/services/kms/internaldafny/ToDafny.java"); Path[] temp = new Path[1]; diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToNativeTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToNativeTest.java index 6d7c3ac1c..9b1924ff3 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToNativeTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToNativeTest.java @@ -10,9 +10,14 @@ import org.junit.Test; import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collection; import java.util.Map; import java.util.Set; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.MethodReference; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.awssdk.TestSetupUtils; @@ -35,7 +40,7 @@ import static software.amazon.polymorph.util.Tokenizer.tokenizeAndAssertEqual; @SuppressWarnings("OptionalGetWithoutIsPresent") -public class ToNativeTest { +public class ToNativeTest extends ForEachDafnyTest { // Why two underTests? // As we refactor ToNativeAwsV2 and abstract ToNative, // we are going to bump into permission issues in unit tests @@ -49,6 +54,7 @@ public class ToNativeTest { protected ToNativeAwsV2 underTest; protected ToNativeTestImpl underTestAbstract; protected Model model; + protected final String dafnyVersion; class ToNativeTestImpl extends ToNativeAwsV2 { @@ -93,11 +99,11 @@ protected CodeBlock setWithConversionCall(MemberShape member, CodeBlock getMembe } } - @Before - public void setup() { + public ToNativeTest(String dafnyVersion) { + this.dafnyVersion = dafnyVersion; model = TestSetupUtils.setupTwoLocalModel(ModelConstants.KMS_KITCHEN, ModelConstants.OTHER_NAMESPACE); - underTest = new ToNativeAwsV2(TestSetupUtils.setupAwsSdkV2(model, "kms")); - underTestAbstract = new ToNativeTestImpl(TestSetupUtils.setupAwsSdkV2(model, "kms")); + underTest = new ToNativeAwsV2(TestSetupUtils.setupAwsSdkV2(model, "kms", dafnyVersion)); + underTestAbstract = new ToNativeTestImpl(TestSetupUtils.setupAwsSdkV2(model, "kms", dafnyVersion)); } @Test @@ -231,7 +237,7 @@ public void generateConvert() { @Test public void generate() { Model model = TestSetupUtils.setupLocalModel(ModelConstants.KMS_A_STRING_OPERATION); - ToNativeAwsV2 underTest = new ToNativeAwsV2(TestSetupUtils.setupAwsSdkV2(model, "kms")); + ToNativeAwsV2 underTest = new ToNativeAwsV2(TestSetupUtils.setupAwsSdkV2(model, "kms", dafnyVersion)); final Map actual = underTest.generate(); final Path expectedPath = Path.of("software/amazon/cryptography/services/kms/internaldafny/ToNative.java"); Path[] temp = new Path[1]; diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/library/ModelCodegenTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/library/ModelCodegenTest.java index ac2d029ba..900ccae81 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/library/ModelCodegenTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/library/ModelCodegenTest.java @@ -7,6 +7,7 @@ import org.junit.Before; import org.junit.Test; +import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.awssdk.TestSetupUtils; import software.amazon.smithy.model.Model; @@ -15,14 +16,13 @@ import static software.amazon.polymorph.util.Tokenizer.tokenizeAndAssertEqual; -public class ModelCodegenTest { +public class ModelCodegenTest extends ForEachDafnyTest { protected ModelCodegen underTest; protected Model model; - @Before - public void setup() { + public ModelCodegenTest(String dafnyVersion) { model = TestSetupUtils.setupLocalModel(ModelConstants.CRYPTOGRAPHY_A_STRING_OPERATION); - underTest = new ModelCodegen(TestSetupUtils.setupLibrary(model, "aws.cryptography.test")); + underTest = new ModelCodegen(TestSetupUtils.setupLibrary(model, "aws.cryptography.test", dafnyVersion)); } @Test diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/nameresolver/DafnyTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/nameresolver/DafnyTest.java index da1991ebe..eabbbf321 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/nameresolver/DafnyTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/nameresolver/DafnyTest.java @@ -8,6 +8,9 @@ import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.CodegenSubject; import software.amazon.polymorph.smithyjava.generator.awssdk.TestSetupUtils; @@ -19,15 +22,17 @@ import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.shapes.StructureShape; +import java.util.Arrays; +import java.util.Collection; + import static org.junit.Assert.assertEquals; import static software.amazon.polymorph.util.Tokenizer.tokenizeAndAssertEqual; -public class DafnyTest { +public class DafnyTest extends ForEachDafnyTest { Dafny underTest; protected Model model; - @Before - public void setup() { + public DafnyTest(String dafnyVersion) { String rawModel = """ namespace smithy.example service Example {} @@ -40,7 +45,7 @@ public void setup() { (builder, modelAssembler) -> modelAssembler .addUnparsedModel("test.smithy", rawModel)); ServiceShape serviceShape = ModelUtils.serviceFromNamespace(model, "smithy.example"); - underTest = new Dafny("Dafny.Smithy.Example", model, serviceShape, CodegenSubject.AwsSdkVersion.V2); + underTest = new Dafny("Dafny.Smithy.Example", model, serviceShape, CodegenSubject.AwsSdkVersion.V2, dafnyVersion); } @Test From 6d8b29274ab2b96725585ff5bba3a0bbe064a799 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Sun, 29 Oct 2023 09:09:09 -0700 Subject: [PATCH 10/49] =?UTF-8?q?Add=20=E2=80=94dafny-version=20to=20CLI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TestModels/Resource/Makefile | 1 + TestModels/SharedMakefile.mk | 2 ++ .../software/amazon/polymorph/CodegenCli.java | 15 ++++++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/TestModels/Resource/Makefile b/TestModels/Resource/Makefile index 54f4b648f..3b4ca443d 100644 --- a/TestModels/Resource/Makefile +++ b/TestModels/Resource/Makefile @@ -6,6 +6,7 @@ CORES=2 include ../SharedMakefile.mk NAMESPACE=simple.resources +DAFNY_VERSION=--dafny-version 4.3 # This project has no dependencies # DEPENDENT-MODELS:= diff --git a/TestModels/SharedMakefile.mk b/TestModels/SharedMakefile.mk index d2cdb7c25..d3f9fc510 100644 --- a/TestModels/SharedMakefile.mk +++ b/TestModels/SharedMakefile.mk @@ -151,6 +151,7 @@ _polymorph: @: $(if ${CODEGEN_CLI_ROOT},,$(error You must pass the path CODEGEN_CLI_ROOT: CODEGEN_CLI_ROOT=/path/to/smithy-dafny/codegen/smithy-dafny-codegen-cli)); cd $(CODEGEN_CLI_ROOT); \ $(GRADLEW) run --args="\ + $(DAFNY_VERSION) \ $(OUTPUT_DAFNY) \ $(OUTPUT_DOTNET) \ $(OUTPUT_JAVA) \ @@ -164,6 +165,7 @@ _polymorph_wrapped: @: $(if ${CODEGEN_CLI_ROOT},,$(error You must pass the path CODEGEN_CLI_ROOT: CODEGEN_CLI_ROOT=/path/to/smithy-dafny/codegen/smithy-dafny-codegen-cli)); cd $(CODEGEN_CLI_ROOT); \ $(GRADLEW) run --args="\ + $(DAFNY_VERSION) \ $(OUTPUT_DAFNY_WRAPPED) \ $(OUTPUT_DOTNET_WRAPPED) \ $(OUTPUT_JAVA_WRAPPED) \ diff --git a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java index 2e3869077..036cd49ef 100644 --- a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java +++ b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java @@ -75,6 +75,7 @@ public static void main(String[] args) { .withAwsSdkStyle(cliArguments.awsSdkStyle) .withLocalServiceTest(cliArguments.localServiceTest); cliArguments.javaAwsSdkVersion.ifPresent(engineBuilder::withJavaAwsSdkVersion); + cliArguments.dafnyVersion.ifPresent(engineBuilder::withDafnyVersion); cliArguments.includeDafnyFile.ifPresent(engineBuilder::withIncludeDafnyFile); final CodegenEngine engine = engineBuilder.build(); engine.run(); @@ -119,6 +120,11 @@ private static Options getCliOptions() { .desc(" AWS SDK for Java version to use: v1, or v2 (default)") .hasArg() .build()) + .addOption(Option.builder() + .longOpt("dafny-version") + .desc(" Dafny version to use. Defaults to 4.1.") + .hasArg() + .build()) .addOption(Option.builder() .longOpt("aws-sdk") .desc(" generate AWS SDK-style API and shims") @@ -152,6 +158,7 @@ private record CliArguments( Optional outputJavaDir, Optional outputDafnyDir, Optional javaAwsSdkVersion, + Optional dafnyVersion, Optional includeDafnyFile, boolean awsSdkStyle, boolean localServiceTest @@ -205,6 +212,12 @@ static Optional parse(String[] args) throws ParseException { } } + Optional dafnyVersion = Optional.empty(); + if (commandLine.hasOption("dafny-version")) { + final String versionStr = commandLine.getOptionValue("dafny-version").trim().toUpperCase(); + dafnyVersion = Optional.of(versionStr); + } + Optional includeDafnyFile = Optional.empty(); if (outputDafnyDir.isPresent()) { includeDafnyFile = Optional.of(Paths.get(commandLine.getOptionValue("include-dafny"))); @@ -213,7 +226,7 @@ static Optional parse(String[] args) throws ParseException { return Optional.of(new CliArguments( modelPath, dependentModelPaths, namespace, outputDotnetDir, outputJavaDir, outputDafnyDir, - javaAwsSdkVersion, includeDafnyFile, awsSdkStyle, + javaAwsSdkVersion, dafnyVersion, includeDafnyFile, awsSdkStyle, localServiceTest )); } From 180d29c9f69464fcd69d3289d27b01745cc653ce Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Sun, 29 Oct 2023 11:18:22 -0700 Subject: [PATCH 11/49] Test multiple Dafny versions in CI --- .github/workflows/test_models_java_tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_models_java_tests.yml b/.github/workflows/test_models_java_tests.yml index fc9bd5bbc..ae0ad026d 100644 --- a/.github/workflows/test_models_java_tests.yml +++ b/.github/workflows/test_models_java_tests.yml @@ -29,6 +29,10 @@ jobs: if: github.event_name != 'schedule' || github.repository_owner == 'smithy-lang' strategy: matrix: + dafny-version: [ + 4.1.0, + 4.3.0 + ] library: [ TestModels/dafny-dependencies/StandardLibrary, # This stores current Polymorph dependencies that all TestModels depend on # TestModels/Aggregate, @@ -85,7 +89,7 @@ jobs: uses: dafny-lang/setup-dafny-action@v1.6.1 with: # A && B || C is the closest thing to an if .. then ... else ... or ?: expression the GitHub Actions syntax supports. - dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || '4.3.0' }} + dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || matrix.dafny-version }} - name: Setup Java uses: actions/setup-java@v3 From 5c65aa7dff49c8efbe99dae6cc81ca3f259a3964 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Sun, 29 Oct 2023 11:54:43 -0700 Subject: [PATCH 12/49] =?UTF-8?q?Specify=20=E2=80=94dafny-version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test_models_java_tests.yml | 2 +- TestModels/Resource/Makefile | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test_models_java_tests.yml b/.github/workflows/test_models_java_tests.yml index ae0ad026d..20455d94f 100644 --- a/.github/workflows/test_models_java_tests.yml +++ b/.github/workflows/test_models_java_tests.yml @@ -114,7 +114,7 @@ jobs: working-directory: ./${{ matrix.library }} run: | make polymorph_dafny - make polymorph_java + make polymorph_java DAFNY_VERSION="--dafny-version ${{ matrix.dafny-version }}" - name: Setup Java 8 for running tests uses: actions/setup-java@v3 diff --git a/TestModels/Resource/Makefile b/TestModels/Resource/Makefile index 3b4ca443d..54f4b648f 100644 --- a/TestModels/Resource/Makefile +++ b/TestModels/Resource/Makefile @@ -6,7 +6,6 @@ CORES=2 include ../SharedMakefile.mk NAMESPACE=simple.resources -DAFNY_VERSION=--dafny-version 4.3 # This project has no dependencies # DEPENDENT-MODELS:= From 05327d88dcabda0e7e1c3cdf0a004c1a179a7bb3 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Sun, 29 Oct 2023 12:37:11 -0700 Subject: [PATCH 13/49] Avoid conditional type descriptors in UTF8 --- .../java/src/main/java/UTF8/__default.java | 12 ++++-------- .../StandardLibrary/src/UTF8.dfy | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java b/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java index e6a1b5b5d..2e14f9592 100644 --- a/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java +++ b/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java @@ -47,12 +47,10 @@ DafnySequence> Encode( // outBuffer's capacity can be much higher than the limit. // By taking just the limit, we ensure we do not include // any allocated but un-filled space. - return Result.create_Success( - BYTE_SEQUENCE_TYPE_DESCRIPTOR, CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, + return CreateEncodeSuccess( (DafnySequence) ByteSequence(outBuffer, 0, outBuffer.limit())); } catch (CharacterCodingException ex) { - return Result.create_Failure( - BYTE_SEQUENCE_TYPE_DESCRIPTOR, CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, + return CreateEncodeFailure( (DafnySequence) CharacterSequence("Could not encode input to Dafny Bytes.")); } } @@ -71,12 +69,10 @@ DafnySequence> Decode( try { CharBuffer outBuffer = coder.decode(inBuffer); outBuffer.position(0); - return Result.create_Success( - CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, + return CreateDecodeSuccess( (DafnySequence) CharacterSequence(outBuffer.toString())); } catch (CharacterCodingException ex) { - return Result.create_Failure( - CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, CHARACTER_SEQUENCE_TYPE_DESCRIPTOR, + return CreateDecodeFailure( (DafnySequence) CharacterSequence("Could not encode input to Dafny Bytes.")); } } diff --git a/TestModels/dafny-dependencies/StandardLibrary/src/UTF8.dfy b/TestModels/dafny-dependencies/StandardLibrary/src/UTF8.dfy index cabfe05d1..a52f0b5d6 100644 --- a/TestModels/dafny-dependencies/StandardLibrary/src/UTF8.dfy +++ b/TestModels/dafny-dependencies/StandardLibrary/src/UTF8.dfy @@ -29,6 +29,14 @@ module {:extern "UTF8"} UTF8 { // If it weren't, then data would be lost. ensures res.Success? ==> Decode(res.value).Success? && Decode(res.value).value == s + function method CreateEncodeSuccess(bytes: ValidUTF8Bytes): Result { + Success(bytes) + } + + function method CreateEncodeFailure(error: string): Result { + Failure(error) + } + // Decode return a Result, therefore doesn't need to require utf8 input function method {:extern "Decode"} Decode(b: seq): (res: Result) ensures res.Success? ==> ValidUTF8Seq(b) @@ -37,6 +45,14 @@ module {:extern "UTF8"} UTF8 { forall i :: 0 <= i < |s| ==> s[i] as int < 128 } + function method CreateDecodeSuccess(s: string): Result { + Success(s) + } + + function method CreateDecodeFailure(error: string): Result { + Failure(error) + } + // Encode ASCII as UTF8 in a function, to allow use in ensures clause function method {:opaque} {:tailrecursion} EncodeAscii(s : string) : (ret : ValidUTF8Bytes) requires IsASCIIString(s) From 4d67a3de1112a6286f9d0eb3e03715efdfc09db7 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Sun, 29 Oct 2023 16:36:49 -0700 Subject: [PATCH 14/49] Working around create_Success in test services --- .../internaldafny/wrapped/__default.java | 2 +- .../errors/internaldafny/wrapped/__default.java | 2 +- .../internaldafny/wrapped/__default.java | 4 +++- .../internaldafny/wrapped/__default.java | 2 +- .../generator/library/shims/TestServiceShim.java | 16 ++++++++++++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java b/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java index 876c16b3d..cbf416d20 100644 --- a/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java +++ b/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleConstraints(S simple.constraints.model.SimpleConstraintsConfig wrappedConfig = ToNative.SimpleConstraintsConfig(config); simple.constraints.SimpleConstraints impl = SimpleConstraints.builder().SimpleConstraintsConfig(wrappedConfig).build(); TestSimpleConstraints wrappedClient = TestSimpleConstraints.builder().impl(impl).build(); - return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleConstraintsClient.class), Error._typeDescriptor(), wrappedClient); + return TestSimpleConstraints.createSuccessOfClient(wrappedClient); } } diff --git a/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java b/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java index d2af0bbe8..6721902d3 100644 --- a/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java +++ b/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleErrors(SimpleError simple.errors.model.SimpleErrorsConfig wrappedConfig = ToNative.SimpleErrorsConfig(config); simple.errors.SimpleErrors impl = SimpleErrors.builder().SimpleErrorsConfig(wrappedConfig).build(); TestSimpleErrors wrappedClient = TestSimpleErrors.builder().impl(impl).build(); - return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleErrorsClient.class), Error._typeDescriptor(), wrappedClient); + TestSimpleErrors.createSuccessOfClient(wrappedClient); } } diff --git a/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java b/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java index c56f6b616..3dbf1dc5d 100644 --- a/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java +++ b/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java @@ -16,13 +16,15 @@ import static simple.extendable.resources.internaldafny.nativeresourcefactory.__default.DafnyFactory; +import UTF8._ExternBase___default; + public class __default extends _ExternBase___default { public static Result WrappedSimpleExtendableResources(SimpleExtendableResourcesConfig config) { TestUnwrapExtendable(); simple.extendable.resources.model.SimpleExtendableResourcesConfig wrappedConfig = ToNative.SimpleExtendableResourcesConfig(config); simple.extendable.resources.SimpleExtendableResources impl = SimpleExtendableResources.builder().SimpleExtendableResourcesConfig(wrappedConfig).build(); TestSimpleExtendableResources wrappedClient = TestSimpleExtendableResources.builder().impl(impl).build(); - return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleExtendableResourcesClient.class), Error._typeDescriptor(), wrappedClient); + return TestSimpleExtendableResources.createSuccessOfClient(wrappedClient); } /** diff --git a/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java b/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java index 13cd02c00..3b518ad70 100644 --- a/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java +++ b/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleResources(Simpl simple.resources.model.SimpleResourcesConfig wrappedConfig = ToNative.SimpleResourcesConfig(config); simple.resources.SimpleResources impl = SimpleResources.builder().SimpleResourcesConfig(wrappedConfig).build(); TestSimpleResources wrappedClient = TestSimpleResources.builder().impl(impl).build(); - return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleResourcesClient.class), Error._typeDescriptor(), wrappedClient); + return TestSimpleResources.createSuccessOfClient(wrappedClient); } } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java index ef5d82595..9a6739900 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java @@ -3,6 +3,7 @@ package software.amazon.polymorph.smithyjava.generator.library.shims; import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; @@ -22,6 +23,7 @@ import static javax.lang.model.element.Modifier.PROTECTED; import static javax.lang.model.element.Modifier.PUBLIC; +import static javax.lang.model.element.Modifier.STATIC; public class TestServiceShim extends ServiceShim { /** The Service Shape this Shim Tests. */ @@ -59,6 +61,8 @@ protected TypeSpec shim() { spec.addMethod(testServiceConstructor(builderSpecs)); // Add public static method for creating a builder spec.addMethod(builderSpecs.builderMethod()); + // Add public static method for creating a Success(client) + spec.addMethod(successOfTestServiceConstructor()); spec.addMethods(getOperationsForTarget().stream() .map(shape -> Operation.AsDafny.operation(shape, this.subject, this)) @@ -108,4 +112,16 @@ private MethodSpec testServiceConstructor(BuilderSpecs builderSpecs) { return method.build(); } + private MethodSpec successOfTestServiceConstructor() { + MethodSpec.Builder method = MethodSpec + .methodBuilder("createSuccessOfClient") + .addModifiers(STATIC, PROTECTED) + .addParameter(thisClassName, "client"); + method.addStatement("return $L", + subject.dafnyNameResolver.createSuccess( + subject.dafnyNameResolver.typeDescriptor(targetShape.toShapeId()), + CodeBlock.of("client"))); + return method.build(); + } + } From ad4ac89aee96d971a6dfdfd8b68b2277a2320ee0 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 05:50:07 -0700 Subject: [PATCH 15/49] Fix KMS --- .../services/kms/internal/__default.java | 16 ++-- .../smithyjava/generator/awssdk/Shim.java | 87 +++++++++++++++++++ .../generator/awssdk/v1/ShimV1.java | 10 ++- .../generator/awssdk/v2/ShimV2.java | 10 ++- .../library/shims/TestServiceShim.java | 3 +- .../smithyjava/nameresolver/Dafny.java | 7 ++ 6 files changed, 114 insertions(+), 19 deletions(-) create mode 100644 codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java diff --git a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java index e8ac4e935..c1b75fa1b 100644 --- a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java +++ b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java @@ -26,11 +26,9 @@ public static Result KMSClient() { String region = regionProvider.getRegion().toString(); KmsClient client = builder.build(); IKMSClient shim = new Shim(client, region); - return Result.create_Success(dafny.TypeDescriptor.reference(IKMSClient.class), Error._typeDescriptor(), shim); + return Shim.createSuccessOfClient(shim); } catch (Exception e) { - Error dafny_error = Error.create_KMSInternalException( - Option.create_Some(dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR), CharacterSequence(e.getMessage()))); - return Result.create_Failure(dafny.TypeDescriptor.reference(IKMSClient.class), Error._typeDescriptor(), dafny_error); + return Shim.createFailureOfError(e); } } @@ -39,11 +37,9 @@ public static Result KMSClient(final String region) { KmsClientBuilder builder = KmsClient.builder(); KmsClient client = builder.region(Region.of(region)).build(); IKMSClient shim = new Shim(client, region); - return Result.create_Success(dafny.TypeDescriptor.reference(IKMSClient.class), Error._typeDescriptor(), shim); + return Shim.createSuccessOfClient(shim); } catch (Exception e) { - Error dafny_error = Error.create_KMSInternalException( - Option.create_Some(dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR), CharacterSequence(e.getMessage()))); - return Result.create_Failure(dafny.TypeDescriptor.reference(IKMSClient.class), Error._typeDescriptor(), dafny_error); + return Shim.createFailureOfError(e); } } @@ -60,13 +56,13 @@ public static Wrappers_Compile.Option RegionMatch( // have no way to determine what region it is // configured with. if (shim.region() == null) { - return Option.create_None(dafny.TypeDescriptor.BOOLEAN); + return Shim.createBooleanNone(); } // Otherwise we kept record of the region // when we created the client. String shimRegion = shim.region(); String regionStr = String(region); - return Option.create_Some(dafny.TypeDescriptor.BOOLEAN, regionStr.equals(shimRegion)); + return Shim.createBooleanSome(regionStr.equals(shimRegion)); } } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java new file mode 100644 index 000000000..f23b30b7e --- /dev/null +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java @@ -0,0 +1,87 @@ +package software.amazon.polymorph.smithyjava.generator.awssdk; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeName; +import software.amazon.polymorph.smithyjava.generator.CodegenSubject; +import software.amazon.polymorph.smithyjava.generator.Generator; +import software.amazon.polymorph.smithyjava.nameresolver.Dafny; +import software.amazon.smithy.model.shapes.ShapeType; + +import static javax.lang.model.element.Modifier.PUBLIC; +import static javax.lang.model.element.Modifier.STATIC; + +public abstract class Shim extends Generator { + public Shim(CodegenSubject subject) { + super(subject); + } + + protected MethodSpec successOfClientConstructor() { + ClassName clientType = subject.dafnyNameResolver.classNameForInterface(subject.serviceShape); + MethodSpec.Builder method = MethodSpec + .methodBuilder("createSuccessOfClient") + .addModifiers(STATIC, PUBLIC) + .addParameter(clientType, "client") + .returns(Dafny.asDafnyResult( + clientType, + subject.dafnyNameResolver.abstractClassForError() + )); + method.addStatement("return $L", + subject.dafnyNameResolver.createSuccess( + subject.dafnyNameResolver.typeDescriptor(subject.serviceShape.toShapeId()), + CodeBlock.of("client"))); + return method.build(); + } + + protected MethodSpec failureOfExceptionConstructor() { + ClassName clientType = subject.dafnyNameResolver.classNameForInterface(subject.serviceShape); + MethodSpec.Builder method = MethodSpec + .methodBuilder("createFailureOfException") + .addModifiers(STATIC, PUBLIC) + .addParameter(ClassName.get(Exception.class), "exception") + .returns(Dafny.asDafnyResult( + clientType, + subject.dafnyNameResolver.abstractClassForError() + )); + CodeBlock stringTypeDescriptor = Dafny.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING); + method.addStatement("Error dafny_error = Error.create_InternalServerError($L)", + subject.dafnyNameResolver.createSome(stringTypeDescriptor, + CodeBlock.of("CharacterSequence(exception.getMessage())"))); + method.addStatement("return $L", + subject.dafnyNameResolver.createFailure( + subject.dafnyNameResolver.typeDescriptor(subject.serviceShape.toShapeId()), + CodeBlock.of("dafny_error"))); + return method.build(); + } + + protected MethodSpec booleanSomeConstructor() { + TypeName booleanType = TypeName.BOOLEAN.box(); + MethodSpec.Builder method = MethodSpec + .methodBuilder("createBooleanSome") + .addModifiers(STATIC, PUBLIC) + .addParameter(booleanType, "b") + .returns(Dafny.asDafnyOption( + booleanType + )); + method.addStatement("return $L", + subject.dafnyNameResolver.createSome( + subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.BOOLEAN), + CodeBlock.of("b"))); + return method.build(); + } + + protected MethodSpec booleanNoneConstructor() { + TypeName booleanType = TypeName.BOOLEAN.box(); + MethodSpec.Builder method = MethodSpec + .methodBuilder("createBooleanNone") + .addModifiers(STATIC, PUBLIC) + .returns(Dafny.asDafnyOption( + booleanType + )); + method.addStatement("return $L", + subject.dafnyNameResolver.createNone( + subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.BOOLEAN))); + return method.build(); + } +} diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java index 6fa12edf5..06450e56e 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java @@ -19,7 +19,7 @@ import javax.lang.model.element.Modifier; -import software.amazon.polymorph.smithyjava.generator.Generator; +import software.amazon.polymorph.smithyjava.generator.awssdk.Shim; import software.amazon.polymorph.utils.DafnyNameResolverHelpers; import software.amazon.polymorph.smithyjava.nameresolver.Dafny; import software.amazon.smithy.model.shapes.OperationShape; @@ -27,16 +27,14 @@ import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.utils.StringUtils; -import static software.amazon.polymorph.smithyjava.nameresolver.Constants.DAFNY_RESULT_CLASS_NAME; import static software.amazon.polymorph.smithyjava.nameresolver.Constants.DAFNY_TUPLE0_CLASS_NAME; import static software.amazon.polymorph.smithyjava.nameresolver.Constants.SMITHY_API_UNIT; -//TODO: Create abstract class for V1 & V2 to extend /** * Generates an AWS SDK Shim for the AWS SKD for Java V1 * exposing an AWS Service's operations to Dafny Generated Java. */ -public class ShimV1 extends Generator { +public class ShimV1 extends Shim { public static final String SHIM = "Shim"; // Hack to override CodegenSubject // See code comment on ../library/ModelCodegen for details. @@ -71,6 +69,10 @@ TypeSpec shim() { .addField( ClassName.get(String.class), "region", Modifier.PRIVATE, Modifier.FINAL) + .addMethod(successOfClientConstructor()) + .addMethod(failureOfExceptionConstructor()) + .addMethod(booleanSomeConstructor()) + .addMethod(booleanNoneConstructor()) .addMethod(constructor()) .addMethod(impl()) .addMethod(region()) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java index e36eb3ee0..24ff6991a 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java @@ -19,7 +19,7 @@ import javax.lang.model.element.Modifier; -import software.amazon.polymorph.smithyjava.generator.Generator; +import software.amazon.polymorph.smithyjava.generator.awssdk.Shim; import software.amazon.polymorph.utils.DafnyNameResolverHelpers; import software.amazon.polymorph.smithyjava.nameresolver.Dafny; import software.amazon.smithy.model.shapes.OperationShape; @@ -27,16 +27,14 @@ import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.utils.StringUtils; -import static software.amazon.polymorph.smithyjava.nameresolver.Constants.DAFNY_RESULT_CLASS_NAME; import static software.amazon.polymorph.smithyjava.nameresolver.Constants.DAFNY_TUPLE0_CLASS_NAME; import static software.amazon.polymorph.smithyjava.nameresolver.Constants.SMITHY_API_UNIT; -//TODO: Create abstract class for V1 & V2 to extend /** * Generates an AWS SDK Shim for the AWS SDK for Java V2 * exposing an AWS Service's operations to Dafny Generated Java. */ -public class ShimV2 extends Generator { +public class ShimV2 extends Shim { public static final String SHIM = "Shim"; // Hack to override CodegenSubject // See code comment on ../library/ModelCodegen for details. @@ -72,6 +70,10 @@ TypeSpec shim() { .addField( ClassName.get(String.class), "region", Modifier.PRIVATE, Modifier.FINAL) + .addMethod(successOfClientConstructor()) + .addMethod(failureOfExceptionConstructor()) + .addMethod(booleanSomeConstructor()) + .addMethod(booleanNoneConstructor()) .addMethod(constructor()) .addMethod(impl()) .addMethod(region()) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java index 9a6739900..0b09ce84c 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java @@ -116,7 +116,8 @@ private MethodSpec successOfTestServiceConstructor() { MethodSpec.Builder method = MethodSpec .methodBuilder("createSuccessOfClient") .addModifiers(STATIC, PROTECTED) - .addParameter(thisClassName, "client"); + .addParameter(thisClassName, "client") + .returns(subject.dafnyNameResolver.classNameForInterface(this.targetShape)); method.addStatement("return $L", subject.dafnyNameResolver.createSuccess( subject.dafnyNameResolver.typeDescriptor(targetShape.toShapeId()), diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index 3f337f552..b7fa32d81 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -213,6 +213,13 @@ public static TypeName asDafnyResult(TypeName success, TypeName failure) { ); } + public static TypeName asDafnyOption(TypeName value) { + return ParameterizedTypeName.get( + Constants.DAFNY_OPTION_CLASS_NAME, + value + ); + } + public String packageName() { return this.packageName; } From 49c7de33f400006749d2780d2020c70db8a25080 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 06:12:46 -0700 Subject: [PATCH 16/49] Fix test shim type descriptor --- .../smithyjava/generator/library/shims/TestServiceShim.java | 6 +++++- .../amazon/polymorph/smithyjava/nameresolver/Dafny.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java index 0b09ce84c..b08984d4c 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java @@ -19,6 +19,7 @@ import software.amazon.polymorph.smithyjava.BuilderSpecs; import software.amazon.polymorph.smithyjava.generator.library.JavaLibrary; import software.amazon.polymorph.smithyjava.modeled.Operation; +import software.amazon.polymorph.smithyjava.nameresolver.Dafny; import software.amazon.smithy.model.shapes.ServiceShape; import static javax.lang.model.element.Modifier.PROTECTED; @@ -117,7 +118,10 @@ private MethodSpec successOfTestServiceConstructor() { .methodBuilder("createSuccessOfClient") .addModifiers(STATIC, PROTECTED) .addParameter(thisClassName, "client") - .returns(subject.dafnyNameResolver.classNameForInterface(this.targetShape)); + .returns(Dafny.asDafnyResult( + subject.dafnyNameResolver.classNameForInterface(this.targetShape), + subject.dafnyNameResolver.abstractClassForError() + )); method.addStatement("return $L", subject.dafnyNameResolver.createSuccess( subject.dafnyNameResolver.typeDescriptor(targetShape.toShapeId()), diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index b7fa32d81..a383b0d8c 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -313,7 +313,7 @@ public CodeBlock typeDescriptor(ShapeId shapeId) { return CodeBlock.of("$L()", new MethodReference(abstractClassForError(), "_typeDescriptor").asNormalReference()); } - if (shape.hasTrait(ReferenceTrait.class)) { + if (shape.hasTrait(ReferenceTrait.class) || shape.isServiceShape()) { // It is safe to use typeForShape here, as ReferenceTrait will always turn into a Resource or Service TypeName interfaceClassName = typeForShape(shapeId); return CodeBlock.of("$T.reference($T.class)", Constants.DAFNY_TYPE_DESCRIPTOR_CLASS_NAME, interfaceClassName); From ae8d542f3db3b8775c20d633de944e14a1e40f16 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 11:00:58 -0700 Subject: [PATCH 17/49] public --- .../smithyjava/generator/library/shims/TestServiceShim.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java index b08984d4c..7c04a0890 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java @@ -116,7 +116,7 @@ private MethodSpec testServiceConstructor(BuilderSpecs builderSpecs) { private MethodSpec successOfTestServiceConstructor() { MethodSpec.Builder method = MethodSpec .methodBuilder("createSuccessOfClient") - .addModifiers(STATIC, PROTECTED) + .addModifiers(STATIC, PUBLIC) .addParameter(thisClassName, "client") .returns(Dafny.asDafnyResult( subject.dafnyNameResolver.classNameForInterface(this.targetShape), From 9e2cb475894621a8105ab16eea545d39301b4c1b Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 11:51:41 -0700 Subject: [PATCH 18/49] Fix unit tests and local service --- .../internaldafny/wrapped/__default.java | 2 +- .../smithyjava/nameresolver/Dafny.java | 6 +- .../generator/awssdk/v2/Constants.java | 196 +++++++++++++++--- .../generator/awssdk/v2/ShimTest.java | 15 +- .../awssdk/v2/ToDafnyAwsV2Constants.java | 12 ++ .../generator/awssdk/v2/ToDafnyAwsV2Test.java | 6 +- 6 files changed, 196 insertions(+), 41 deletions(-) diff --git a/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java b/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java index 36f4697fd..4fc673448 100644 --- a/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java +++ b/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java @@ -18,7 +18,7 @@ public static Result WrappedSimpleLocalService simple.localservice.SimpleLocalService impl = SimpleLocalService.builder().SimpleLocalServiceConfig(wrappedConfig).build(); TestToNativeAndToDafnyLocalService(impl); TestSimpleLocalService wrappedClient = TestSimpleLocalService.builder().impl(impl).build(); - return Result.create_Success(dafny.TypeDescriptor.reference(ISimpleLocalServiceClient.class), Error._typeDescriptor(), wrappedClient); + return TestSimpleLocalService.createSuccessOfClient(wrappedClient); } // TODO: Determine how to replace this test with Dafny Source Code diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index a383b0d8c..5d553888e 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -96,11 +96,15 @@ public static String datatypeConstructorCreate(String name, boolean isRecordType return "create_" + DafnyNameResolverHelpers.dafnyCompilesExtra_(name); } - private boolean datatypeConstructorsNeedTypeDescriptors() { + public static boolean datatypeConstructorsNeedTypeDescriptors(String dafnyVersion) { // TODO: proper version comparison return dafnyVersion.compareTo("4.2") >= 0; } + private boolean datatypeConstructorsNeedTypeDescriptors() { + return datatypeConstructorsNeedTypeDescriptors(dafnyVersion); + } + public CodeBlock createNone(CodeBlock typeDescriptor) { if (datatypeConstructorsNeedTypeDescriptors()) { return CodeBlock.of( diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java index bdd7f39b1..251948e1e 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java @@ -2,6 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 package software.amazon.polymorph.smithyjava.generator.awssdk.v2; +import software.amazon.polymorph.smithyjava.nameresolver.Dafny; + public class Constants { static String DoSomethingOperation = """ @Override @@ -19,6 +21,27 @@ public Result DoSomething(DoSomethingRequest input) } """; + static String DoSomethingOperationWithTypeDescriptors = """ + @Override + public Result DoSomething(DoSomethingRequest input) { + software.amazon.awssdk.services.kms.model.DoSomethingRequest converted = ToNative.DoSomethingRequest(input); + try { + software.amazon.awssdk.services.kms.model.DoSomethingResponse result = _impl.doSomething(converted); + DoSomethingResponse dafnyResponse = ToDafny.DoSomethingResponse(result); + return Result.create_Success(DoSomethingResponse._typeDescriptor(), Error._typeDescriptor(), dafnyResponse); + } catch (DependencyTimeoutException ex) { + return Result.create_Failure(DoSomethingResponse._typeDescriptor(), Error._typeDescriptor(), ToDafny.Error(ex)); + } catch (KmsException ex) { + return Result.create_Failure(DoSomethingResponse._typeDescriptor(), Error._typeDescriptor(), ToDafny.Error(ex)); + } + } + """; + + static String DoSomethingOperation(String dafnyVersion) { + return Dafny.datatypeConstructorsNeedTypeDescriptors(dafnyVersion) ? + DoSomethingOperationWithTypeDescriptors : DoSomethingOperation; + } + static String DoVoidOperation = """ @Override public Result DoVoid(DoVoidRequest input) { @@ -34,43 +57,152 @@ public Result DoVoid(DoVoidRequest input) { } """; + static String DoVoidOperationWithTypeDescriptors = """ + @Override + public Result DoVoid(DoVoidRequest input) { + software.amazon.awssdk.services.kms.model.DoVoidRequest converted = ToNative.DoVoidRequest(input); + try { + _impl.doVoid(converted); + return Result.create_Success(dafny.Tuple0._typeDescriptor(), Error._typeDescriptor(), Tuple0.create()); + } catch (DependencyTimeoutException ex) { + return Result.create_Failure(dafny.Tuple0._typeDescriptor(), Error._typeDescriptor(), ToDafny.Error(ex)); + } catch (KmsException ex) { + return Result.create_Failure(dafny.Tuple0._typeDescriptor(), Error._typeDescriptor(), ToDafny.Error(ex)); + } + } + """; + + static String DoVoidOperation(String dafnyVersion) { + return Dafny.datatypeConstructorsNeedTypeDescriptors(dafnyVersion) ? + DoVoidOperationWithTypeDescriptors : DoVoidOperation; + } + static String MockKmsShim = """ - package software.amazon.cryptography.services.kms.internaldafny; - - import Wrappers_Compile.Result; - import dafny.Tuple0; - import java.lang.Override; - import java.lang.String; - import software.amazon.awssdk.services.kms.KmsClient; - import software.amazon.awssdk.services.kms.model.DependencyTimeoutException; - import software.amazon.awssdk.services.kms.model.KmsException; - import software.amazon.cryptography.services.kms.internaldafny.types.DoSomethingRequest; - import software.amazon.cryptography.services.kms.internaldafny.types.DoSomethingResponse; - import software.amazon.cryptography.services.kms.internaldafny.types.DoVoidRequest; - import software.amazon.cryptography.services.kms.internaldafny.types.Error; - import software.amazon.cryptography.services.kms.internaldafny.types.IKeyManagementServiceClient; - - public class Shim implements IKeyManagementServiceClient { - private final KmsClient _impl; + package software.amazon.cryptography.services.kms.internaldafny; + + import Wrappers_Compile.Option; + import Wrappers_Compile.Result; + import dafny.Tuple0; + import java.lang.Boolean; + import java.lang.Exception; + import java.lang.Override; + import java.lang.String; + import software.amazon.awssdk.services.kms.KmsClient; + import software.amazon.awssdk.services.kms.model.DependencyTimeoutException; + import software.amazon.awssdk.services.kms.model.KmsException; + import software.amazon.cryptography.services.kms.internaldafny.types.DoSomethingRequest; + import software.amazon.cryptography.services.kms.internaldafny.types.DoSomethingResponse; + import software.amazon.cryptography.services.kms.internaldafny.types.DoVoidRequest; + import software.amazon.cryptography.services.kms.internaldafny.types.Error; + import software.amazon.cryptography.services.kms.internaldafny.types.IKeyManagementServiceClient; + + public class Shim implements IKeyManagementServiceClient { + private final KmsClient _impl; + + private final String region; + + public Shim(final KmsClient impl, final String region) { + this._impl = impl; + this.region = region; + } + + public static Result createSuccessOfClient( + IKeyManagementServiceClient client) { + return Result.create_Success(client); + } - private final String region; + public static Result createFailureOfException( + Exception exception) { + Error dafny_error = Error.create_InternalServerError(Option.create_Some(CharacterSequence(exception.getMessage()))); + return Result.create_Failure(dafny_error); + } - public Shim(final KmsClient impl, final String region) { - this._impl = impl; - this.region = region; - } + public static Option createBooleanSome(Boolean b) { + return Option.create_Some(b); + } - public KmsClient impl() { - return this._impl; - } + public static Option createBooleanNone() { + return Option.create_None(); + } + + public KmsClient impl() { + return this._impl; + } + + public String region() { + return this.region; + } + + %s + %s + } + """.formatted(DoSomethingOperation, DoVoidOperation); + + static String MockKmsShimWithTypeDescriptors = """ + package software.amazon.cryptography.services.kms.internaldafny; + + import Wrappers_Compile.Option; + import Wrappers_Compile.Result; + import dafny.DafnySequence; + import dafny.Tuple0; + import dafny.TypeDescriptor; + import java.lang.Boolean; + import java.lang.Exception; + import java.lang.Override; + import java.lang.String; + import software.amazon.awssdk.services.kms.KmsClient; + import software.amazon.awssdk.services.kms.model.DependencyTimeoutException; + import software.amazon.awssdk.services.kms.model.KmsException; + import software.amazon.cryptography.services.kms.internaldafny.types.DoSomethingRequest; + import software.amazon.cryptography.services.kms.internaldafny.types.DoSomethingResponse; + import software.amazon.cryptography.services.kms.internaldafny.types.DoVoidRequest; + import software.amazon.cryptography.services.kms.internaldafny.types.Error; + import software.amazon.cryptography.services.kms.internaldafny.types.IKeyManagementServiceClient; + + public class Shim implements IKeyManagementServiceClient { + private final KmsClient _impl; + + private final String region; + + public Shim(final KmsClient impl, final String region) { + this._impl = impl; + this.region = region; + } + + public static Result createSuccessOfClient( + IKeyManagementServiceClient client) { + return Result.create_Success(TypeDescriptor.reference(IKeyManagementServiceClient.class), Error._typeDescriptor(), client); + } - public String region() { - return this.region; - } + public static Result createFailureOfException( + Exception exception) { + Error dafny_error = Error.create_InternalServerError(Option.create_Some(DafnySequence._typeDescriptor(TypeDescriptor.CHAR), CharacterSequence(exception.getMessage()))); + return Result.create_Failure(TypeDescriptor.reference(IKeyManagementServiceClient.class), Error._typeDescriptor(), dafny_error); + } - %s - %s - } - """.formatted(DoSomethingOperation, DoVoidOperation); + public static Option createBooleanSome(Boolean b) { + return Option.create_Some(TypeDescriptor.BOOLEAN, b); + } + + public static Option createBooleanNone() { + return Option.create_None(TypeDescriptor.BOOLEAN); + } + + public KmsClient impl() { + return this._impl; + } + + public String region() { + return this.region; + } + + %s + %s + } + """.formatted(DoSomethingOperationWithTypeDescriptors, DoVoidOperationWithTypeDescriptors); + static String MockKmsShim(String dafnyVersion) { + return Dafny.datatypeConstructorsNeedTypeDescriptors(dafnyVersion) ? + MockKmsShimWithTypeDescriptors : MockKmsShim; + } } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java index 153e2d6d4..8c714cf43 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java @@ -34,8 +34,10 @@ public class ShimTest extends ForEachDafnyTest { protected ShimV2 underTest; protected Model model; protected JavaAwsSdkV2 subject; + protected final String dafnyVersion; public ShimTest(String dafnyVersion) { + this.dafnyVersion = dafnyVersion; model = TestSetupUtils.setupLocalModel(ModelConstants.MOCK_KMS); subject = TestSetupUtils.setupAwsSdkV2(model, "kms", dafnyVersion); underTest = new ShimV2(subject); @@ -69,9 +71,9 @@ public void operation() { Expected: %s""").formatted( - actualString, DoSomethingOperation + actualString, DoSomethingOperation(dafnyVersion) ), - actualString.contains(DoSomethingOperation) + actualString.contains(DoSomethingOperation(dafnyVersion)) ); } @@ -103,9 +105,9 @@ public void operationVoid() { Expected: %s""").formatted( - actualString, DoVoidOperation + actualString, DoVoidOperation(dafnyVersion) ), - actualString.contains(DoVoidOperation) + actualString.contains(DoVoidOperation(dafnyVersion)) ); } @@ -119,8 +121,9 @@ public void generate() { final Path actualPath = actual.keySet().toArray(temp)[0]; assertEquals(expectedPath, actualPath); final String actualSource = actual.get(actualPath).toString(); + final String mockKmsShim = MockKmsShim(dafnyVersion); System.out.println(actualSource); - System.out.print(MockKmsShim); - Tokenizer.tokenizeAndAssertEqual(MockKmsShim, actualSource); + System.out.print(mockKmsShim); + Tokenizer.tokenizeAndAssertEqual(mockKmsShim, actualSource); } } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Constants.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Constants.java index 25db5d140..8fcc67b2d 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Constants.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Constants.java @@ -108,6 +108,18 @@ public static software.amazon.cryptography.services.kms.internaldafny.types.Erro } """; + protected static String GENERATE_CONVERT_OPAQUE_ERROR_WITH_TYPE_DESCRIPTORS = """ + public static software.amazon.cryptography.services.kms.internaldafny.types.Error Error( + software.amazon.awssdk.services.kms.model.KmsException nativeValue + ) { + Wrappers_Compile.Option> message; + message = java.util.Objects.nonNull(nativeValue.getMessage()) ? + Wrappers_Compile.Option.create_Some(dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR), software.amazon.smithy.dafny.conversion.ToDafny.Simple.CharacterSequence(nativeValue.getMessage())) + : Wrappers_Compile.Option.create_None(dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR)); + return new software.amazon.cryptography.services.kms.internaldafny.types.Error_Opaque(message); + } + """; + protected static final String KMS_A_STRING_OPERATION_JAVA_FILE = """ package software.amazon.cryptography.services.kms.internaldafny; diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java index b59d8ea8a..cee2ae73b 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java @@ -13,6 +13,7 @@ import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.awssdk.TestSetupUtils; +import software.amazon.polymorph.smithyjava.nameresolver.Dafny; import software.amazon.polymorph.utils.TokenTree; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.shapes.ShapeId; @@ -76,7 +77,10 @@ public void generateConvert() { @Test public void generateConvertOpaqueError() { - tokenizeAndAssertEqual(ToDafnyAwsV2Constants.GENERATE_CONVERT_OPAQUE_ERROR, underTest.generateConvertOpaqueError().toString()); + final String expected = Dafny.datatypeConstructorsNeedTypeDescriptors(dafnyVersion) ? + ToDafnyAwsV2Constants.GENERATE_CONVERT_OPAQUE_ERROR_WITH_TYPE_DESCRIPTORS + : ToDafnyAwsV2Constants.GENERATE_CONVERT_OPAQUE_ERROR; + tokenizeAndAssertEqual(expected, underTest.generateConvertOpaqueError().toString()); } @Test From 33f74af21887b895e705691b29831b36c6f44ac8 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 12:09:52 -0700 Subject: [PATCH 19/49] Fix DDB and Errors --- .../java/simple/errors/internaldafny/wrapped/__default.java | 2 +- .../services/dynamodb/internaldafny/__default.java | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java b/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java index 6721902d3..3e482c594 100644 --- a/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java +++ b/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleErrors(SimpleError simple.errors.model.SimpleErrorsConfig wrappedConfig = ToNative.SimpleErrorsConfig(config); simple.errors.SimpleErrors impl = SimpleErrors.builder().SimpleErrorsConfig(wrappedConfig).build(); TestSimpleErrors wrappedClient = TestSimpleErrors.builder().impl(impl).build(); - TestSimpleErrors.createSuccessOfClient(wrappedClient); + return TestSimpleErrors.createSuccessOfClient(wrappedClient); } } diff --git a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java index 03875861c..3922467b3 100644 --- a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java +++ b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java @@ -25,11 +25,9 @@ public static Result DynamoDBClient() { .build(); IDynamoDBClient shim = new Shim(ddbClient, region.toString()); - return Result.create_Success(dafny.TypeDescriptor.reference(IDynamoDBClient.class), Error._typeDescriptor(), shim); + return Shim.createSuccessOfClient(shim); } catch (Exception e) { - Error dafny_error = Error.create_InternalServerError( - Option.create_Some(dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR), CharacterSequence(e.getMessage()))); - return Result.create_Failure(dafny.TypeDescriptor.reference(IDynamoDBClient.class), Error._typeDescriptor(), dafny_error); + return Shim.createFailureOfError(e); } } } From f0493fbd40e1bccb0c3ac3f8eea1d5f72181baf2 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 12:53:31 -0700 Subject: [PATCH 20/49] License headers, typos --- .../services/dynamodb/internaldafny/__default.java | 2 +- .../amazon/cryptography/services/kms/internal/__default.java | 4 ++-- .../amazon/polymorph/smithyjava/generator/awssdk/Shim.java | 4 +++- .../amazon/polymorph/smithyjava/ForEachDafnyTest.java | 2 ++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java index 3922467b3..53fd285fb 100644 --- a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java +++ b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java @@ -27,7 +27,7 @@ public static Result DynamoDBClient() { IDynamoDBClient shim = new Shim(ddbClient, region.toString()); return Shim.createSuccessOfClient(shim); } catch (Exception e) { - return Shim.createFailureOfError(e); + return Shim.createFailureOfException(e); } } } diff --git a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java index c1b75fa1b..81a091a27 100644 --- a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java +++ b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java @@ -28,7 +28,7 @@ public static Result KMSClient() { IKMSClient shim = new Shim(client, region); return Shim.createSuccessOfClient(shim); } catch (Exception e) { - return Shim.createFailureOfError(e); + return Shim.createFailureOfException(e); } } @@ -39,7 +39,7 @@ public static Result KMSClient(final String region) { IKMSClient shim = new Shim(client, region); return Shim.createSuccessOfClient(shim); } catch (Exception e) { - return Shim.createFailureOfError(e); + return Shim.createFailureOfException(e); } } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java index f23b30b7e..932c85c7a 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java @@ -1,3 +1,5 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 package software.amazon.polymorph.smithyjava.generator.awssdk; import com.squareup.javapoet.ClassName; @@ -47,7 +49,7 @@ protected MethodSpec failureOfExceptionConstructor() { CodeBlock stringTypeDescriptor = Dafny.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING); method.addStatement("Error dafny_error = Error.create_InternalServerError($L)", subject.dafnyNameResolver.createSome(stringTypeDescriptor, - CodeBlock.of("CharacterSequence(exception.getMessage())"))); + CodeBlock.of("software.amazon.smithy.dafny.conversion.ToDafny.Simple.CharacterSequence(exception.getMessage())"))); method.addStatement("return $L", subject.dafnyNameResolver.createFailure( subject.dafnyNameResolver.typeDescriptor(subject.serviceShape.toShapeId()), diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java index 493c2a72e..da204c38d 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java @@ -1,3 +1,5 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 package software.amazon.polymorph.smithyjava; import org.junit.runner.RunWith; From efed9b2e205ddde1a4076a7cc2dd8140d07b3c51 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 13:26:46 -0700 Subject: [PATCH 21/49] Shim.createFailureOfException -> Shim.createFailureOfError --- .../dynamodb/internaldafny/__default.java | 4 +- .../services/kms/internal/__default.java | 8 +++- .../smithyjava/generator/awssdk/Shim.java | 46 ++++++++++++++---- .../generator/awssdk/v1/ShimV1.java | 4 +- .../generator/awssdk/v2/ShimV2.java | 4 +- .../smithyjava/nameresolver/Dafny.java | 2 +- .../generator/awssdk/v2/Constants.java | 47 ++++++++++++------- .../amazon/polymorph/util/Tokenizer.java | 1 + 8 files changed, 85 insertions(+), 31 deletions(-) diff --git a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java index 53fd285fb..6a25d75ed 100644 --- a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java +++ b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java @@ -27,7 +27,9 @@ public static Result DynamoDBClient() { IDynamoDBClient shim = new Shim(ddbClient, region.toString()); return Shim.createSuccessOfClient(shim); } catch (Exception e) { - return Shim.createFailureOfException(e); + Error dafny_error = Error.create_InternalServerError( + Shim.createStringSome(CharacterSequence(e.getMessage()))); + return Shim.createFailureOfError(e); } } } diff --git a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java index 81a091a27..375648370 100644 --- a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java +++ b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java @@ -28,7 +28,9 @@ public static Result KMSClient() { IKMSClient shim = new Shim(client, region); return Shim.createSuccessOfClient(shim); } catch (Exception e) { - return Shim.createFailureOfException(e); + Error dafny_error = Error.create_KMSInternalException( + Shim.createStringSome(CharacterSequence(e.getMessage()))); + return Shim.createFailureOfError(dafny_error); } } @@ -39,7 +41,9 @@ public static Result KMSClient(final String region) { IKMSClient shim = new Shim(client, region); return Shim.createSuccessOfClient(shim); } catch (Exception e) { - return Shim.createFailureOfException(e); + Error dafny_error = Error.create_KMSInternalException( + Shim.createStringSome(CharacterSequence(e.getMessage()))); + return Shim.createFailureOfError(dafny_error); } } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java index 932c85c7a..c12ecbd46 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java @@ -21,13 +21,14 @@ public Shim(CodegenSubject subject) { protected MethodSpec successOfClientConstructor() { ClassName clientType = subject.dafnyNameResolver.classNameForInterface(subject.serviceShape); + ClassName errorType = subject.dafnyNameResolver.abstractClassForError(); MethodSpec.Builder method = MethodSpec .methodBuilder("createSuccessOfClient") .addModifiers(STATIC, PUBLIC) .addParameter(clientType, "client") .returns(Dafny.asDafnyResult( clientType, - subject.dafnyNameResolver.abstractClassForError() + errorType )); method.addStatement("return $L", subject.dafnyNameResolver.createSuccess( @@ -36,24 +37,51 @@ protected MethodSpec successOfClientConstructor() { return method.build(); } - protected MethodSpec failureOfExceptionConstructor() { + protected MethodSpec failureOfErrorConstructor() { ClassName clientType = subject.dafnyNameResolver.classNameForInterface(subject.serviceShape); + ClassName errorType = subject.dafnyNameResolver.abstractClassForError(); MethodSpec.Builder method = MethodSpec - .methodBuilder("createFailureOfException") + .methodBuilder("createFailureOfError") .addModifiers(STATIC, PUBLIC) - .addParameter(ClassName.get(Exception.class), "exception") + .addParameter(errorType, "error") .returns(Dafny.asDafnyResult( clientType, subject.dafnyNameResolver.abstractClassForError() )); - CodeBlock stringTypeDescriptor = Dafny.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING); - method.addStatement("Error dafny_error = Error.create_InternalServerError($L)", - subject.dafnyNameResolver.createSome(stringTypeDescriptor, - CodeBlock.of("software.amazon.smithy.dafny.conversion.ToDafny.Simple.CharacterSequence(exception.getMessage())"))); method.addStatement("return $L", subject.dafnyNameResolver.createFailure( subject.dafnyNameResolver.typeDescriptor(subject.serviceShape.toShapeId()), - CodeBlock.of("dafny_error"))); + CodeBlock.of("error"))); + return method.build(); + } + + protected MethodSpec stringSomeConstructor() { + TypeName stringType = subject.dafnyNameResolver.typeForCharacterSequence(); + MethodSpec.Builder method = MethodSpec + .methodBuilder("createStringSome") + .addModifiers(STATIC, PUBLIC) + .addParameter(stringType, "s") + .returns(Dafny.asDafnyOption( + stringType + )); + method.addStatement("return $L", + subject.dafnyNameResolver.createSome( + subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.BOOLEAN), + CodeBlock.of("s"))); + return method.build(); + } + + protected MethodSpec stringNoneConstructor() { + TypeName stringType = subject.dafnyNameResolver.typeForCharacterSequence(); + MethodSpec.Builder method = MethodSpec + .methodBuilder("createStringNone") + .addModifiers(STATIC, PUBLIC) + .returns(Dafny.asDafnyOption( + stringType + )); + method.addStatement("return $L", + subject.dafnyNameResolver.createNone( + subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.BOOLEAN))); return method.build(); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java index 06450e56e..041db765a 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java @@ -70,7 +70,9 @@ TypeSpec shim() { ClassName.get(String.class), "region", Modifier.PRIVATE, Modifier.FINAL) .addMethod(successOfClientConstructor()) - .addMethod(failureOfExceptionConstructor()) + .addMethod(failureOfErrorConstructor()) + .addMethod(stringSomeConstructor()) + .addMethod(stringNoneConstructor()) .addMethod(booleanSomeConstructor()) .addMethod(booleanNoneConstructor()) .addMethod(constructor()) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java index 24ff6991a..d573d09c5 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java @@ -71,7 +71,9 @@ TypeSpec shim() { ClassName.get(String.class), "region", Modifier.PRIVATE, Modifier.FINAL) .addMethod(successOfClientConstructor()) - .addMethod(failureOfExceptionConstructor()) + .addMethod(failureOfErrorConstructor()) + .addMethod(stringSomeConstructor()) + .addMethod(stringNoneConstructor()) .addMethod(booleanSomeConstructor()) .addMethod(booleanNoneConstructor()) .addMethod(constructor()) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index 5d553888e..fc4cbdb48 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -395,7 +395,7 @@ TypeName typeForString(StringShape shape) { return typeForCharacterSequence(); } - TypeName typeForCharacterSequence() { + public TypeName typeForCharacterSequence() { return ParameterizedTypeName.get( Constants.DAFNY_SEQUENCE_CLASS_NAME, WildcardTypeName.subtypeOf(Character.class) diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java index 251948e1e..e0af84f43 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java @@ -82,9 +82,10 @@ static String DoVoidOperation(String dafnyVersion) { import Wrappers_Compile.Option; import Wrappers_Compile.Result; + import dafny.DafnySequence; import dafny.Tuple0; import java.lang.Boolean; - import java.lang.Exception; + import java.lang.Character; import java.lang.Override; import java.lang.String; import software.amazon.awssdk.services.kms.KmsClient; @@ -110,17 +111,24 @@ public static Result createSuccessOfClient( IKeyManagementServiceClient client) { return Result.create_Success(client); } - - public static Result createFailureOfException( - Exception exception) { - Error dafny_error = Error.create_InternalServerError(Option.create_Some(CharacterSequence(exception.getMessage()))); - return Result.create_Failure(dafny_error); + + public static Result createFailureOfError(Error error) { + return Result.create_Failure(error); + } + + public static Option> createStringSome( + DafnySequence s) { + return Option.create_Some(s); + } + + public static Option> createStringNone() { + return Option.create_None(); } - + public static Option createBooleanSome(Boolean b) { return Option.create_Some(b); } - + public static Option createBooleanNone() { return Option.create_None(); } @@ -147,7 +155,7 @@ public String region() { import dafny.Tuple0; import dafny.TypeDescriptor; import java.lang.Boolean; - import java.lang.Exception; + import java.lang.Character; import java.lang.Override; import java.lang.String; import software.amazon.awssdk.services.kms.KmsClient; @@ -173,17 +181,24 @@ public static Result createSuccessOfClient( IKeyManagementServiceClient client) { return Result.create_Success(TypeDescriptor.reference(IKeyManagementServiceClient.class), Error._typeDescriptor(), client); } - - public static Result createFailureOfException( - Exception exception) { - Error dafny_error = Error.create_InternalServerError(Option.create_Some(DafnySequence._typeDescriptor(TypeDescriptor.CHAR), CharacterSequence(exception.getMessage()))); - return Result.create_Failure(TypeDescriptor.reference(IKeyManagementServiceClient.class), Error._typeDescriptor(), dafny_error); + + public static Result createFailureOfError(Error error) { + return Result.create_Failure(TypeDescriptor.reference(IKeyManagementServiceClient.class), Error._typeDescriptor(), error); + } + + public static Option> createStringSome( + DafnySequence s) { + return Option.create_Some(TypeDescriptor.BOOLEAN, s); + } + + public static Option> createStringNone() { + return Option.create_None(TypeDescriptor.BOOLEAN); } - + public static Option createBooleanSome(Boolean b) { return Option.create_Some(TypeDescriptor.BOOLEAN, b); } - + public static Option createBooleanNone() { return Option.create_None(TypeDescriptor.BOOLEAN); } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/util/Tokenizer.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/util/Tokenizer.java index 2573a240b..7b282f14d 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/util/Tokenizer.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/util/Tokenizer.java @@ -31,6 +31,7 @@ public static List tokenize(final String source) { public static record ParseToken(String text, int type) {} public static void tokenizeAndAssertEqual(String expected, String actual) { +// Assert.assertEquals(expected, actual); final List actualTokens = tokenize(actual); final List expectedTokens = tokenize(expected); Assert.assertEquals(expectedTokens, actualTokens); From b6f4f09f725e59ddf7403771cbe4a546dc6e695e Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 13:30:53 -0700 Subject: [PATCH 22/49] Typo --- .../cryptography/services/dynamodb/internaldafny/__default.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java index 6a25d75ed..da91c1dba 100644 --- a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java +++ b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java @@ -29,7 +29,7 @@ public static Result DynamoDBClient() { } catch (Exception e) { Error dafny_error = Error.create_InternalServerError( Shim.createStringSome(CharacterSequence(e.getMessage()))); - return Shim.createFailureOfError(e); + return Shim.createFailureOfError(dafny_error); } } } From fb538e01be604e24fe2d1bad0ce97c673e4e445b Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 13:38:09 -0700 Subject: [PATCH 23/49] =?UTF-8?q?Typos,=20typos=20everywhere=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extendable/resources/internaldafny/wrapped/__default.java | 2 -- .../amazon/polymorph/smithyjava/generator/awssdk/Shim.java | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java b/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java index 3dbf1dc5d..991c6b7ec 100644 --- a/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java +++ b/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java @@ -16,8 +16,6 @@ import static simple.extendable.resources.internaldafny.nativeresourcefactory.__default.DafnyFactory; -import UTF8._ExternBase___default; - public class __default extends _ExternBase___default { public static Result WrappedSimpleExtendableResources(SimpleExtendableResourcesConfig config) { TestUnwrapExtendable(); diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java index c12ecbd46..b72972130 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java @@ -66,7 +66,7 @@ protected MethodSpec stringSomeConstructor() { )); method.addStatement("return $L", subject.dafnyNameResolver.createSome( - subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.BOOLEAN), + subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING), CodeBlock.of("s"))); return method.build(); } @@ -81,7 +81,7 @@ protected MethodSpec stringNoneConstructor() { )); method.addStatement("return $L", subject.dafnyNameResolver.createNone( - subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.BOOLEAN))); + subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING))); return method.build(); } From c8f245eb429d278b8b455f4e36f7553ee01bcb9a Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 13:43:52 -0700 Subject: [PATCH 24/49] Fix test --- .../smithyjava/generator/awssdk/v2/Constants.java | 4 ++-- .../java/software/amazon/polymorph/util/Tokenizer.java | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java index e0af84f43..2143d2748 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java @@ -188,11 +188,11 @@ public static Result createFailureOfError(Er public static Option> createStringSome( DafnySequence s) { - return Option.create_Some(TypeDescriptor.BOOLEAN, s); + return Option.create_Some(DafnySequence._typeDescriptor(TypeDescriptor.CHAR), s); } public static Option> createStringNone() { - return Option.create_None(TypeDescriptor.BOOLEAN); + return Option.create_None(DafnySequence._typeDescriptor(TypeDescriptor.CHAR)); } public static Option createBooleanSome(Boolean b) { diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/util/Tokenizer.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/util/Tokenizer.java index 7b282f14d..de00cd881 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/util/Tokenizer.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/util/Tokenizer.java @@ -10,6 +10,7 @@ import software.amazon.polymorph.antlr.CSharpLexer; import java.util.List; +import java.util.Objects; import org.junit.Assert; @@ -31,9 +32,13 @@ public static List tokenize(final String source) { public static record ParseToken(String text, int type) {} public static void tokenizeAndAssertEqual(String expected, String actual) { -// Assert.assertEquals(expected, actual); final List actualTokens = tokenize(actual); final List expectedTokens = tokenize(expected); - Assert.assertEquals(expectedTokens, actualTokens); + if (!Objects.equals(expectedTokens, actualTokens)) { + // If the tokens aren't equal, assert the original strings are equal + // knowing it is guaranteed to fail, + // just so that we get a much more readable diff in tooling. + Assert.assertEquals(expected, actual); + } } } From 8a1786b58a49438d22693350e9b9a9113911f970 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 30 Oct 2023 13:51:07 -0700 Subject: [PATCH 25/49] Cleanup --- .../java/src/main/java/UTF8/__default.java | 6 ------ .../StandardLibrary/src/UTF8.dfy | 21 ++++++++++++------- .../software/amazon/polymorph/CodegenCli.java | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java b/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java index 2e14f9592..c3171cdd8 100644 --- a/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java +++ b/TestModels/dafny-dependencies/StandardLibrary/runtimes/java/src/main/java/UTF8/__default.java @@ -25,12 +25,6 @@ // and reset the coder everytime. public class __default extends UTF8._ExternBase___default { - private static final dafny.TypeDescriptor> BYTE_SEQUENCE_TYPE_DESCRIPTOR = - dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.BYTE); - private static final dafny.TypeDescriptor> CHARACTER_SEQUENCE_TYPE_DESCRIPTOR = - dafny.DafnySequence._typeDescriptor(dafny.TypeDescriptor.CHAR); - - // This is largely copied from Polymorph's dafny-java-conversion: // software.amazon.smithy.dafny.conversion.ToDafny.Simple.DafnyUtf8Bytes public static Result< diff --git a/TestModels/dafny-dependencies/StandardLibrary/src/UTF8.dfy b/TestModels/dafny-dependencies/StandardLibrary/src/UTF8.dfy index a52f0b5d6..ca889813e 100644 --- a/TestModels/dafny-dependencies/StandardLibrary/src/UTF8.dfy +++ b/TestModels/dafny-dependencies/StandardLibrary/src/UTF8.dfy @@ -29,6 +29,15 @@ module {:extern "UTF8"} UTF8 { // If it weren't, then data would be lost. ensures res.Success? ==> Decode(res.value).Success? && Decode(res.value).value == s + // Decode return a Result, therefore doesn't need to require utf8 input + function method {:extern "Decode"} Decode(b: seq): (res: Result) + ensures res.Success? ==> ValidUTF8Seq(b) + + // The next four functions are for the benefit of the extern implementation to call, + // avoiding direct references to generic datatype constructors + // since their calling pattern is different between different versions of Dafny + // (i.e. after 4.2, explicit type descriptors are required). + function method CreateEncodeSuccess(bytes: ValidUTF8Bytes): Result { Success(bytes) } @@ -37,14 +46,6 @@ module {:extern "UTF8"} UTF8 { Failure(error) } - // Decode return a Result, therefore doesn't need to require utf8 input - function method {:extern "Decode"} Decode(b: seq): (res: Result) - ensures res.Success? ==> ValidUTF8Seq(b) - - predicate method IsASCIIString(s: string) { - forall i :: 0 <= i < |s| ==> s[i] as int < 128 - } - function method CreateDecodeSuccess(s: string): Result { Success(s) } @@ -52,6 +53,10 @@ module {:extern "UTF8"} UTF8 { function method CreateDecodeFailure(error: string): Result { Failure(error) } + + predicate method IsASCIIString(s: string) { + forall i :: 0 <= i < |s| ==> s[i] as int < 128 + } // Encode ASCII as UTF8 in a function, to allow use in ensures clause function method {:opaque} {:tailrecursion} EncodeAscii(s : string) : (ret : ValidUTF8Bytes) diff --git a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java index 036cd49ef..6a37a25e7 100644 --- a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java +++ b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java @@ -122,7 +122,7 @@ private static Options getCliOptions() { .build()) .addOption(Option.builder() .longOpt("dafny-version") - .desc(" Dafny version to use. Defaults to 4.1.") + .desc(" Dafny version to use. Defaults to 4.1.0") .hasArg() .build()) .addOption(Option.builder() From 6e64b307267459914365667c072902155badbe02 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Tue, 31 Oct 2023 12:42:34 -0700 Subject: [PATCH 26/49] Refactor CI to handle nightly builds correctly --- .github/workflows/manual.yml | 26 +++++++++++++ .github/workflows/nightly_dafny.yml | 29 ++++++++++++++ .github/workflows/pull.yml | 37 ++++++++++++++++++ .github/workflows/push.yml | 39 +++++++++++++++++++ .../test_models_dafny_verification.yml | 29 +++----------- .github/workflows/test_models_java_tests.yml | 33 +++++----------- .github/workflows/test_models_net_tests.yml | 29 +++----------- .gitignore | 5 ++- 8 files changed, 157 insertions(+), 70 deletions(-) create mode 100644 .github/workflows/manual.yml create mode 100644 .github/workflows/nightly_dafny.yml create mode 100644 .github/workflows/pull.yml create mode 100644 .github/workflows/push.yml diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml new file mode 100644 index 000000000..22febd0bd --- /dev/null +++ b/.github/workflows/manual.yml @@ -0,0 +1,26 @@ +# This workflow invokes other workflows with the requested Dafny build. +# It is primarily meant for manual compatibility testing, +# such as trying out what the next pending nightly build will do ahead of time. +name: Manual CI + +on: + workflow_dispatch: + inputs: + dafny: + description: 'The Dafny version to use' + required: true + type: string + +jobs: + manual-ci-verification: + uses: ./.github/workflows/test_models_dafny_verification.yml + with: + dafny: ${{ inputs.dafny }} + manual-ci-java: + uses: ./.github/workflows/test_models_java_tests.yml + with: + dafny: ${{ inputs.dafny }} + manual-ci-net: + uses: ./.github/workflows/test_models_net_tests.yml + with: + dafny: ${{ inputs.dafny }} diff --git a/.github/workflows/nightly_dafny.yml b/.github/workflows/nightly_dafny.yml new file mode 100644 index 000000000..f202460f0 --- /dev/null +++ b/.github/workflows/nightly_dafny.yml @@ -0,0 +1,29 @@ +# This workflow invokes other workflows with the nightly Dafny build +name: Dafny Nightly + +on: + schedule: + # Nightly build against Dafny's nightly prereleases, + # for early warning of verification issues or regressions. + # Timing chosen to be adequately after Dafny's own nightly build, + # but this might need to be tweaked: + # https://github.com/dafny-lang/dafny/blob/master/.github/workflows/deep-tests.yml#L16 + - cron: "30 16 * * *" + +jobs: + dafny-nightly-verification: + # Don't run the cron builds on forks + if: github.event_name != 'schedule' || github.repository_owner == 'smithy-lang' + uses: ./.github/workflows/test_models_dafny_verification.yml + with: + dafny: 'nightly-latest' + dafny-nightly-java: + if: github.event_name != 'schedule' || github.repository_owner == 'smithy-lang' + uses: ./.github/workflows/test_models_java_tests.yml + with: + dafny: 'nightly-latest' + dafny-nightly-net: + if: github.event_name != 'schedule' || github.repository_owner == 'smithy-lang' + uses: ./.github/workflows/test_models_net_tests.yml + with: + dafny: 'nightly-latest' diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml new file mode 100644 index 000000000..209cbff3c --- /dev/null +++ b/.github/workflows/pull.yml @@ -0,0 +1,37 @@ +# This workflow runs for every pull request +name: PR CI + +on: + pull_request: + +jobs: + pr-ci-verification: + strategy: + matrix: + dafny-version: [ + 4.1.0, + 4.3.0 + ] + uses: ./.github/workflows/test_models_dafny_verification.yml + with: + dafny: ${{ matrix.dafny-version }} + pr-ci-java: + strategy: + matrix: + dafny-version: [ + 4.1.0, + 4.3.0 + ] + uses: ./.github/workflows/test_models_java_tests.yml + with: + dafny: ${{ matrix.dafny-version }} + pr-ci-net: + strategy: + matrix: + dafny-version: [ + 4.1.0, + 4.3.0 + ] + uses: ./.github/workflows/test_models_net_tests.yml + with: + dafny: ${{ matrix.dafny-version }} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 000000000..23f5773bd --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,39 @@ +# This workflow runs for every push to main-1.x +name: Push CI + +on: + push: + branches: + - main-1.x + +jobs: + push-ci-verification: + strategy: + matrix: + dafny-version: [ + 4.1.0, + 4.3.0 + ] + uses: ./.github/workflows/test_models_dafny_verification.yml + with: + dafny: ${{ matrix.dafny-version }} + push-ci-java: + strategy: + matrix: + dafny-version: [ + 4.1.0, + 4.3.0 + ] + uses: ./.github/workflows/test_models_java_tests.yml + with: + dafny: ${{ matrix.dafny-version }} + push-ci-net: + strategy: + matrix: + dafny-version: [ + 4.1.0, + 4.3.0 + ] + uses: ./.github/workflows/test_models_net_tests.yml + with: + dafny: ${{ matrix.dafny-version }} diff --git a/.github/workflows/test_models_dafny_verification.yml b/.github/workflows/test_models_dafny_verification.yml index 683a95b18..45ef2a399 100644 --- a/.github/workflows/test_models_dafny_verification.yml +++ b/.github/workflows/test_models_dafny_verification.yml @@ -2,31 +2,15 @@ name: Library Dafny verification on: - pull_request: - push: - branches: - - main-1.x - workflow_dispatch: - # Manual trigger for this workflow, either the normal version - # or the nightly build that uses the latest Dafny prerelease - # (accordingly to the "nightly" parameter). + workflow_call: inputs: - nightly: - description: 'Run the nightly build' - required: false - type: boolean - schedule: - # Nightly build against Dafny's nightly prereleases, - # for early warning of verification issues or regressions. - # Timing chosen to be adequately after Dafny's own nightly build, - # but this might need to be tweaked: - # https://github.com/dafny-lang/dafny/blob/master/.github/workflows/deep-tests.yml#L16 - - cron: "30 16 * * *" + dafny: + description: 'The Dafny version to run' + required: true + type: string jobs: verification: - # Don't run the nightly build on forks - if: github.event_name != 'schedule' || github.repository_owner == 'smithy-lang' strategy: matrix: library: [ @@ -76,8 +60,7 @@ jobs: - name: Setup Dafny uses: dafny-lang/setup-dafny-action@v1.6.1 with: - # A && B || C is the closest thing to an if .. then ... else ... or ?: expression the GitHub Actions syntax supports. - dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || '4.1.0' }} + dafny-version: ${{ inputs.dafny }} - name: Generate Polymorph Wrapper Dafny code shell: bash diff --git a/.github/workflows/test_models_java_tests.yml b/.github/workflows/test_models_java_tests.yml index 20455d94f..b1d5cf182 100644 --- a/.github/workflows/test_models_java_tests.yml +++ b/.github/workflows/test_models_java_tests.yml @@ -2,26 +2,12 @@ name: Library Java tests on: - pull_request: - push: - branches: - - main-1.x - workflow_dispatch: - # Manual trigger for this workflow, either the normal version - # or the nightly build that uses the latest Dafny prerelease - # (accordingly to the "nightly" parameter). + workflow_call: inputs: - nightly: - description: 'Run the nightly build' - required: false - type: boolean - schedule: - # Nightly build against Dafny's nightly prereleases, - # for early warning of verification issues or regressions. - # Timing chosen to be adequately after Dafny's own nightly build, - # but this might need to be tweaked: - # https://github.com/dafny-lang/dafny/blob/master/.github/workflows/deep-tests.yml#L16 - - cron: "30 16 * * *" + dafny: + description: 'The Dafny version to run' + required: true + type: string jobs: testJava: @@ -86,10 +72,10 @@ jobs: - uses: actions/checkout@v3 - name: Setup Dafny - uses: dafny-lang/setup-dafny-action@v1.6.1 + # TODO: temporary until https://github.com/dafny-lang/setup-dafny-action/pull/19 is merged + uses: dafny-lang/setup-dafny-action@5ae5aac with: - # A && B || C is the closest thing to an if .. then ... else ... or ?: expression the GitHub Actions syntax supports. - dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || matrix.dafny-version }} + dafny-version: ${{ inputs.dafny }} - name: Setup Java uses: actions/setup-java@v3 @@ -112,9 +98,10 @@ jobs: - name: Generate Polymorph Dafny and Java code shell: bash working-directory: ./${{ matrix.library }} + # Use $DAFNY_VERSION from setup-dafny-action to handle nightlies correctly run: | make polymorph_dafny - make polymorph_java DAFNY_VERSION="--dafny-version ${{ matrix.dafny-version }}" + make polymorph_java DAFNY_VERSION="--dafny-version $DAFNY_VERSION" - name: Setup Java 8 for running tests uses: actions/setup-java@v3 diff --git a/.github/workflows/test_models_net_tests.yml b/.github/workflows/test_models_net_tests.yml index 65dca60b7..01e6e03ce 100644 --- a/.github/workflows/test_models_net_tests.yml +++ b/.github/workflows/test_models_net_tests.yml @@ -2,31 +2,15 @@ name: Library net tests on: - pull_request: - push: - branches: - - main-1.x - workflow_dispatch: - # Manual trigger for this workflow, either the normal version - # or the nightly build that uses the latest Dafny prerelease - # (accordingly to the "nightly" parameter). + workflow_call: inputs: - nightly: - description: 'Run the nightly build' - required: false - type: boolean - schedule: - # Nightly build against Dafny's nightly prereleases, - # for early warning of verification issues or regressions. - # Timing chosen to be adequately after Dafny's own nightly build, - # but this might need to be tweaked: - # https://github.com/dafny-lang/dafny/blob/master/.github/workflows/deep-tests.yml#L16 - - cron: "30 16 * * *" + dafny: + description: 'The Dafny version to run' + required: true + type: string jobs: testDotNet: - # Don't run the nightly build on forks - if: github.event_name != 'schedule' || github.repository_owner == 'smithy-lang' strategy: matrix: library: [ @@ -87,8 +71,7 @@ jobs: - name: Setup Dafny uses: dafny-lang/setup-dafny-action@v1.6.1 with: - # A && B || C is the closest thing to an if .. then ... else ... or ?: expression the GitHub Actions syntax supports. - dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || '4.1.0' }} + dafny-version: ${{ inputs.dafny }} - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} uses: actions/setup-dotnet@v3 diff --git a/.gitignore b/.gitignore index 3acc1c840..4dfaf7fad 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ /.history /.smithy.lsp.log -*/**/.idea \ No newline at end of file +*/**/.idea +/codegen/smithy-dafny-codegen/bin +/codegen/smithy-dafny-codegen-cli/bin +/smithy-dafny-conversion/bin From 538d8720f3d623cc8801aa607961ab25e805c7bd Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Tue, 31 Oct 2023 12:44:36 -0700 Subject: [PATCH 27/49] Need full commit sha --- .github/workflows/test_models_java_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_models_java_tests.yml b/.github/workflows/test_models_java_tests.yml index b1d5cf182..0039e5c99 100644 --- a/.github/workflows/test_models_java_tests.yml +++ b/.github/workflows/test_models_java_tests.yml @@ -73,7 +73,7 @@ jobs: - name: Setup Dafny # TODO: temporary until https://github.com/dafny-lang/setup-dafny-action/pull/19 is merged - uses: dafny-lang/setup-dafny-action@5ae5aac + uses: dafny-lang/setup-dafny-action@5ae5aacfdf373c46cb08f0bb852223f26cc9ecb3 with: dafny-version: ${{ inputs.dafny }} From fb2d1e4adb2d1661c12b1e990d29ca8780bef165 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Tue, 31 Oct 2023 13:05:08 -0700 Subject: [PATCH 28/49] Use latest edition in sample --- codegen/smithy-dafny-codegen/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codegen/smithy-dafny-codegen/README.md b/codegen/smithy-dafny-codegen/README.md index 467f3a0b3..642bef8e8 100644 --- a/codegen/smithy-dafny-codegen/README.md +++ b/codegen/smithy-dafny-codegen/README.md @@ -86,9 +86,10 @@ are as follows: "version": "1.0", "plugins": { "dafny-client-codegen": { - "edition": "2023", + "edition": "2023.10", "service": "smithy.example#ExampleService", "targetLanguages": ["dotnet"], + "dafnyVersion": "4.3.0", "includeDafnyFile": "[relative]/[path]/[to]/StandardLibrary/src/Index.dfy" } } From eb785e0cdf0573fa32d735191f77afbeebd0ea22 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Tue, 31 Oct 2023 14:40:45 -0700 Subject: [PATCH 29/49] Introduce proper DafnyVersion class --- .../software/amazon/polymorph/CodegenCli.java | 7 +- .../amazon/polymorph/CodegenEngine.java | 12 +- .../polymorph/smithydafny/DafnyVersion.java | 130 ++++++++++++++++++ .../generator/awssdk/v2/JavaAwsSdkV2.java | 3 +- .../generator/library/JavaLibrary.java | 5 +- .../generator/library/TestJavaLibrary.java | 3 +- .../nameresolver/AwsSdkDafnyV1.java | 3 +- .../nameresolver/AwsSdkDafnyV2.java | 3 +- .../smithyjava/nameresolver/Dafny.java | 14 +- .../DafnyClientCodegenPluginSettings.java | 13 +- .../DafnyVersionCompareToTest.java | 50 +++++++ .../smithydafny/DafnyVersionParsingTest.java | 52 +++++++ .../smithyjava/ForEachDafnyTest.java | 5 +- .../generator/awssdk/TestSetupUtils.java | 5 +- .../generator/awssdk/v2/Constants.java | 7 +- .../generator/awssdk/v2/ShimTest.java | 5 +- .../generator/awssdk/v2/ToDafnyAwsV2Test.java | 5 +- .../generator/awssdk/v2/ToNativeTest.java | 5 +- .../generator/library/ModelCodegenTest.java | 3 +- .../smithyjava/nameresolver/DafnyTest.java | 3 +- 20 files changed, 292 insertions(+), 41 deletions(-) create mode 100644 codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java create mode 100644 codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionCompareToTest.java create mode 100644 codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionParsingTest.java diff --git a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java index 6a37a25e7..a636385d7 100644 --- a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java +++ b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java @@ -4,6 +4,7 @@ package software.amazon.polymorph; import software.amazon.polymorph.CodegenEngine.TargetLanguage; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.generator.CodegenSubject.AwsSdkVersion; import org.apache.commons.cli.CommandLine; @@ -158,7 +159,7 @@ private record CliArguments( Optional outputJavaDir, Optional outputDafnyDir, Optional javaAwsSdkVersion, - Optional dafnyVersion, + Optional dafnyVersion, Optional includeDafnyFile, boolean awsSdkStyle, boolean localServiceTest @@ -212,10 +213,10 @@ static Optional parse(String[] args) throws ParseException { } } - Optional dafnyVersion = Optional.empty(); + Optional dafnyVersion = Optional.empty(); if (commandLine.hasOption("dafny-version")) { final String versionStr = commandLine.getOptionValue("dafny-version").trim().toUpperCase(); - dafnyVersion = Optional.of(versionStr); + dafnyVersion = Optional.of(DafnyVersion.parse(versionStr)); } Optional includeDafnyFile = Optional.empty(); diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/CodegenEngine.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/CodegenEngine.java index 4785710f6..cbdf075e3 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/CodegenEngine.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/CodegenEngine.java @@ -8,6 +8,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.polymorph.smithydafny.DafnyApiCodegen; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithydotnet.AwsSdkShimCodegen; import software.amazon.polymorph.smithydotnet.AwsSdkTypeConversionCodegen; import software.amazon.polymorph.smithydotnet.ServiceCodegen; @@ -21,6 +22,7 @@ import software.amazon.polymorph.smithyjava.generator.awssdk.v2.JavaAwsSdkV2; import software.amazon.polymorph.smithyjava.generator.library.JavaLibrary; import software.amazon.polymorph.smithyjava.generator.library.TestJavaLibrary; +import software.amazon.polymorph.smithyjava.nameresolver.Dafny; import software.amazon.polymorph.utils.IOUtils; import software.amazon.polymorph.utils.ModelUtils; import software.amazon.smithy.aws.traits.ServiceTrait; @@ -41,7 +43,7 @@ public class CodegenEngine { private final Path[] dependentModelPaths; private final String namespace; private final Map targetLangOutputDirs; - private final String dafnyVersion; + private final DafnyVersion dafnyVersion; // refactor this to only be required if generating Java private final AwsSdkVersion javaAwsSdkVersion; private final Optional includeDafnyFile; @@ -63,7 +65,7 @@ private CodegenEngine( final Path[] dependentModelPaths, final String namespace, final Map targetLangOutputDirs, - final String dafnyVersion, + final DafnyVersion dafnyVersion, final AwsSdkVersion javaAwsSdkVersion, final Optional includeDafnyFile, final boolean awsSdkStyle, @@ -248,7 +250,7 @@ public static class Builder { private Path[] dependentModelPaths; private String namespace; private Map targetLangOutputDirs; - private String dafnyVersion = "4.1.0"; + private DafnyVersion dafnyVersion = new DafnyVersion(4, 1, 0); private AwsSdkVersion javaAwsSdkVersion = AwsSdkVersion.V2; private Path includeDafnyFile; private boolean awsSdkStyle = false; @@ -296,7 +298,7 @@ public Builder withTargetLangOutputDirs(final Map targetLa * and compatibility with the Dafny compiler and runtime internals, * which shim code generation currently depends on. */ - public Builder withDafnyVersion(final String dafnyVersion) { + public Builder withDafnyVersion(final DafnyVersion dafnyVersion) { this.dafnyVersion = dafnyVersion; return this; } @@ -356,7 +358,7 @@ public CodegenEngine build() { targetLangOutputDirsRaw.replaceAll((_lang, path) -> path.toAbsolutePath().normalize()); final Map targetLangOutputDirs = ImmutableMap.copyOf(targetLangOutputDirsRaw); - final String dafnyVersion = Objects.requireNonNull(this.dafnyVersion); + final DafnyVersion dafnyVersion = Objects.requireNonNull(this.dafnyVersion); final AwsSdkVersion javaAwsSdkVersion = Objects.requireNonNull(this.javaAwsSdkVersion); if (targetLangOutputDirs.containsKey(TargetLanguage.DAFNY) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java new file mode 100644 index 000000000..fb3a14416 --- /dev/null +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java @@ -0,0 +1,130 @@ +package software.amazon.polymorph.smithydafny; + +import java.util.Comparator; +import java.util.Objects; + +/** + * Representation of a Dafny version number, according to SemVer 1.0 semantics. + * + * Note that Dafny pre-releases historically have used pre-release suffixes slightly wrong: + * after releasing 4.2 for example, the nightly pre-releases will have version numbers like + * "4.2.0-nightly-2023-08-04-656a114", but that should actually be interpreted as a pre-release + * for 4.2 rather than 4.3. So far that's immaterial for this code base, + * but if it becomes relevant the better solution is for Dafny pre-releases to correct this instead. + */ +public class DafnyVersion implements Comparable { + + private final int major; + private final int minor; + private final int patch; + // Will be non-null only if there was a pre-release suffix + private final String suffix; + + // Anything with a pre-release suffix should be considered less + // than a matching version without one. + private static final Comparator SUFFIX_COMPARATOR = Comparator.nullsLast(Comparator.naturalOrder()); + + public static DafnyVersion parse(String versionString) { + if (!versionString.matches("[0-9\\.A-Za-z\\-]*")) { + throw new IllegalArgumentException(); + } + int firstHyphenIndex = versionString.indexOf("-"); + String majorMinorPatch = versionString; + String suffix = null; + if (firstHyphenIndex >= 0) { + majorMinorPatch = versionString.substring(0, firstHyphenIndex); + suffix = versionString.substring(firstHyphenIndex + 1); + } + String[] splitByDots = majorMinorPatch.split("\\."); + switch (splitByDots.length) { + case 1: + return new DafnyVersion( + Integer.parseInt(splitByDots[0]), + 0, + 0, + suffix); + case 2: + return new DafnyVersion( + Integer.parseInt(splitByDots[0]), + Integer.parseInt(splitByDots[1]), + 0, + suffix); + case 3: + return new DafnyVersion( + Integer.parseInt(splitByDots[0]), + Integer.parseInt(splitByDots[1]), + Integer.parseInt(splitByDots[2]), + suffix); + default: + throw new IllegalArgumentException(); + } + } + + public DafnyVersion(int major, int minor, int patch) { + this(major, minor, patch, null); + } + + public DafnyVersion(int major, int minor, int patch, String suffix) { + this.major = requireNonNegative(major); + this.minor = requireNonNegative(minor); + this.patch = requireNonNegative(patch); + this.suffix = suffix; + } + + private int requireNonNegative(int value) { + if (value < 0) { + throw new IllegalArgumentException(); + } + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DafnyVersion that = (DafnyVersion) o; + return major == that.major + && minor == that.minor + && patch == that.patch + && Objects.equals(suffix, that.suffix); + } + + @Override + public int hashCode() { + return Objects.hash(major, minor, patch, suffix); + } + + @Override + public int compareTo(DafnyVersion other) { + int majorComparison = Integer.compare(this.major, other.major); + if (majorComparison != 0) { + return majorComparison; + } + + int minorComparison = Integer.compare(this.minor, other.minor); + if (minorComparison != 0) { + return minorComparison; + } + + int patchComparison = Integer.compare(this.patch, other.patch); + if (patchComparison != 0) { + return patchComparison; + } + + return SUFFIX_COMPARATOR.compare(this.suffix, other.suffix); + } + + @Override + public String toString() { + return "DafnyVersion{" + + "major=" + major + + ", minor=" + minor + + ", patch=" + patch + + ", suffix='" + suffix + '\'' + + '}'; + } +} diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/JavaAwsSdkV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/JavaAwsSdkV2.java index 4651bda80..99308f814 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/JavaAwsSdkV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/JavaAwsSdkV2.java @@ -8,6 +8,7 @@ import java.util.HashMap; import java.util.Map; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.MethodReference; import software.amazon.polymorph.smithyjava.generator.CodegenSubject; import software.amazon.polymorph.utils.TokenTree; @@ -47,7 +48,7 @@ private JavaAwsSdkV2( this.packageName = dafnyNameResolver.packageName(); } - public static JavaAwsSdkV2 createJavaAwsSdkV2(ServiceShape serviceShape, Model model, String dafnyVersion) { + public static JavaAwsSdkV2 createJavaAwsSdkV2(ServiceShape serviceShape, Model model, DafnyVersion dafnyVersion) { final AwsSdkDafnyV2 dafnyNameResolver = new AwsSdkDafnyV2(serviceShape, model, dafnyVersion); final AwsSdkNativeV2 nativeNameResolver = new AwsSdkNativeV2(serviceShape, model); return new JavaAwsSdkV2(serviceShape, model, dafnyNameResolver, nativeNameResolver); diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/JavaLibrary.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/JavaLibrary.java index 4b8c332d6..b3ac9a26e 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/JavaLibrary.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/JavaLibrary.java @@ -15,6 +15,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.NamespaceHelper; import software.amazon.polymorph.smithyjava.generator.CodegenSubject; import software.amazon.polymorph.smithyjava.generator.Generator; @@ -61,7 +62,7 @@ public class JavaLibrary extends CodegenSubject { public final ToDafnyLibrary toDafnyLibrary; public final ToNativeLibrary toNativeLibrary; - public JavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVersion, String dafnyVersion) { + public JavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVersion, DafnyVersion dafnyVersion) { super(model, serviceShape, initDafny(model, serviceShape, sdkVersion, dafnyVersion), initNative(model, serviceShape, sdkVersion), sdkVersion); packageName = NamespaceHelper.standardize(serviceShape.getId().getNamespace()); modelPackageName = packageName + ".model"; @@ -77,7 +78,7 @@ public JavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVers toNativeLibrary = new ToNativeLibrary(this); } - static Dafny initDafny(Model model, ServiceShape serviceShape, AwsSdkVersion awsSdkVersion, String dafnyVersion) { + static Dafny initDafny(Model model, ServiceShape serviceShape, AwsSdkVersion awsSdkVersion, DafnyVersion dafnyVersion) { String packageName = DafnyNameResolverHelpers.packageNameForNamespace(serviceShape.getId().getNamespace()); return new Dafny(packageName, model, serviceShape, awsSdkVersion, dafnyVersion); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/TestJavaLibrary.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/TestJavaLibrary.java index 34b06c7d8..afe33cd25 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/TestJavaLibrary.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/TestJavaLibrary.java @@ -9,6 +9,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.generator.library.shims.TestServiceShim; import software.amazon.polymorph.utils.TokenTree; @@ -19,7 +20,7 @@ public class TestJavaLibrary extends JavaLibrary { @SuppressWarnings("unused") private static final Logger LOGGER = LoggerFactory.getLogger(TestJavaLibrary.class); - public TestJavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVersion, String dafnyVersion) { + public TestJavaLibrary(Model model, ServiceShape serviceShape, AwsSdkVersion sdkVersion, DafnyVersion dafnyVersion) { super(model, serviceShape, sdkVersion, dafnyVersion); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV1.java index a2b3bbfc9..d71a7edbe 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV1.java @@ -4,6 +4,7 @@ import com.squareup.javapoet.ClassName; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.generator.CodegenSubject; import software.amazon.polymorph.utils.AwsSdkNameResolverHelpers; import software.amazon.polymorph.utils.DafnyNameResolverHelpers; @@ -18,7 +19,7 @@ public class AwsSdkDafnyV1 extends Dafny { - public AwsSdkDafnyV1(ServiceShape serviceShape, Model model, String dafnyVersion) { + public AwsSdkDafnyV1(ServiceShape serviceShape, Model model, DafnyVersion dafnyVersion) { super(packageNameForServiceShape(serviceShape), model, serviceShape, CodegenSubject.AwsSdkVersion.V1, dafnyVersion); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV2.java index f735a5185..72c57fe0e 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/AwsSdkDafnyV2.java @@ -9,6 +9,7 @@ import com.squareup.javapoet.TypeName; import software.amazon.polymorph.smithydafny.DafnyNameResolver; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.generator.CodegenSubject; import software.amazon.polymorph.utils.AwsSdkNameResolverHelpers; import software.amazon.polymorph.utils.DafnyNameResolverHelpers; @@ -25,7 +26,7 @@ public class AwsSdkDafnyV2 extends Dafny { - public AwsSdkDafnyV2(ServiceShape serviceShape, Model model, String dafnyVersion) { + public AwsSdkDafnyV2(ServiceShape serviceShape, Model model, DafnyVersion dafnyVersion) { super(packageNameForServiceShape(serviceShape), model, serviceShape, CodegenSubject.AwsSdkVersion.V2, dafnyVersion); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index fc4cbdb48..2af640920 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -19,6 +19,7 @@ import javax.annotation.Nullable; import software.amazon.polymorph.smithydafny.DafnyNameResolver; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.MethodReference; import software.amazon.polymorph.smithyjava.generator.CodegenSubject; import software.amazon.polymorph.smithyjava.generator.Generator; @@ -65,14 +66,14 @@ public class Dafny extends NameResolver { ); } - private final String dafnyVersion; + private final DafnyVersion dafnyVersion; public Dafny( final String packageName, final Model model, final ServiceShape serviceShape, - CodegenSubject.AwsSdkVersion awsSdkVersion, - final String dafnyVersion) { + final CodegenSubject.AwsSdkVersion awsSdkVersion, + final DafnyVersion dafnyVersion) { super( packageName, serviceShape, @@ -96,9 +97,10 @@ public static String datatypeConstructorCreate(String name, boolean isRecordType return "create_" + DafnyNameResolverHelpers.dafnyCompilesExtra_(name); } - public static boolean datatypeConstructorsNeedTypeDescriptors(String dafnyVersion) { - // TODO: proper version comparison - return dafnyVersion.compareTo("4.2") >= 0; + private static final DafnyVersion NEEDS_TYPE_DESCRIPTORS_WHEN_CONSTRUCTING_DATATYPES = new DafnyVersion(4, 2, 0); + + public static boolean datatypeConstructorsNeedTypeDescriptors(DafnyVersion dafnyVersion) { + return dafnyVersion.compareTo(NEEDS_TYPE_DESCRIPTORS_WHEN_CONSTRUCTING_DATATYPES) >= 0; } private boolean datatypeConstructorsNeedTypeDescriptors() { diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenPluginSettings.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenPluginSettings.java index 1ff8d6ea0..de57e4f24 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenPluginSettings.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/smithy/dafny/codegen/DafnyClientCodegenPluginSettings.java @@ -5,6 +5,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.polymorph.CodegenEngine; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.smithy.build.FileManifest; import software.amazon.smithy.model.node.Node; import software.amazon.smithy.model.node.ObjectNode; @@ -60,14 +61,14 @@ class DafnyClientCodegenPluginSettings { * which shim code generation currently depends on. * Required when the edition is 2023.10 or later. */ - public final String dafnyVersion; + public final DafnyVersion dafnyVersion; private DafnyClientCodegenPluginSettings( final DafnyClientCodegenEdition edition, final ShapeId serviceId, final Set targetLanguages, final Path includeDafnyFile, - final String dafnyVersion + final DafnyVersion dafnyVersion ) { this.edition = edition; this.serviceId = serviceId; @@ -119,17 +120,17 @@ static Optional fromObject(final ObjectNode no includeDafnyFileNormalized); } - final String dafnyVersion; + final String dafnyVersionString; if (edition.ordinal() >= DafnyClientCodegenEdition.EDITION_2023_10.ordinal()) { // Required from this edition on - dafnyVersion = node.expectStringMember("dafnyVersion").getValue(); + dafnyVersionString = node.expectStringMember("dafnyVersion").getValue(); } else { - dafnyVersion = node.getStringMemberOrDefault("dafnyVersion", "4.1"); + dafnyVersionString = node.getStringMemberOrDefault("dafnyVersion", "4.1"); } return Optional.of( new DafnyClientCodegenPluginSettings(edition, serviceId, targetLanguages, includeDafnyFileNormalized, - dafnyVersion)); + DafnyVersion.parse(dafnyVersionString))); } /** diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionCompareToTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionCompareToTest.java new file mode 100644 index 000000000..3f3b4193e --- /dev/null +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionCompareToTest.java @@ -0,0 +1,50 @@ +package software.amazon.polymorph.smithydafny; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class DafnyVersionCompareToTest { + + @Parameterized.Parameters(name = "{0} compareTo {1} == {2}") + public static Collection data() { + return Arrays.asList(new Object[][] { + { "4.1", "4", 1 }, + { "4.0", "4", 0 }, + { "4", "4.0.0", 0 }, + { "4.1.3", "4", 1 }, + { "3.11", "4", -1 }, + { "4.1", "4", 1 }, + { "4.1.1", "4.1.2", -1 }, + { "4.1.1", "4.1.1", 0 }, + { "4.1.2", "4.1.1", 1 }, + { "4-alpha", "4", -1 }, + { "4-alpha", "4.0", -1 }, + { "4-alpha", "4-alpha", 0 }, + { "4-alpha", "4-beta", -1 }, + }); + } + + public DafnyVersionCompareToTest(String lhs, String rhs, int expected) { + this.lhs = lhs; + this.rhs = rhs; + this.expected = expected; + } + + private final String lhs; + private final String rhs; + private final int expected; + + @Test + public void testCompareTo() { + DafnyVersion left = DafnyVersion.parse(lhs); + DafnyVersion right = DafnyVersion.parse(rhs); + assertEquals(expected, left.compareTo(right)); + } +} diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionParsingTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionParsingTest.java new file mode 100644 index 000000000..5e596e1ad --- /dev/null +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionParsingTest.java @@ -0,0 +1,52 @@ +package software.amazon.polymorph.smithydafny; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import software.amazon.polymorph.smithyjava.nameresolver.Dafny; + +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class DafnyVersionParsingTest { + + public DafnyVersionParsingTest(String versionString, DafnyVersion expected) { + this.versionString = versionString; + this.expected = expected; + } + + @Parameterized.Parameters(name = "{0} ==> {1}") + public static Collection data() { + return Arrays.asList(new Object[][] { + // Valid + { "4", new DafnyVersion(4, 0, 0) }, + { "4.1", new DafnyVersion(4, 1, 0) }, + { "4.1.4", new DafnyVersion(4, 1, 4) }, + { "4-almost", new DafnyVersion(4, 0, 0, "almost") }, + { "4.1-beta", new DafnyVersion(4, 1, 0, "beta") }, + { "4.1.4-any-day-now", new DafnyVersion(4, 1, 4, "any-day-now") }, + // Invalid + { "", null }, + { "$@%!", null }, + { "1.2.3.4", null }, + { "not.even.numbers", null } + }); + } + + private final String versionString; + private final DafnyVersion expected; + + @Test + public void testParsing() { + try { + DafnyVersion parsed = DafnyVersion.parse(versionString); + assertEquals(expected, parsed); + } catch (IllegalArgumentException e) { + assertEquals(null, expected); + } + + } +} diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java index da204c38d..37021333f 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/ForEachDafnyTest.java @@ -4,6 +4,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import software.amazon.polymorph.smithydafny.DafnyVersion; import java.util.Arrays; import java.util.Collection; @@ -14,8 +15,8 @@ public abstract class ForEachDafnyTest { @Parameterized.Parameters(name = "dafnyVersion = {0}") public static Collection dafnies() { return Arrays.asList(new Object[][] { - { "4.1" }, - { "4.3" }, + { new DafnyVersion(4, 1, 0) }, + { new DafnyVersion(4, 3, 0) }, }); } } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/TestSetupUtils.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/TestSetupUtils.java index 793d5ff52..457db6056 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/TestSetupUtils.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/TestSetupUtils.java @@ -4,6 +4,7 @@ import java.util.function.BiConsumer; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.generator.awssdk.v1.JavaAwsSdkV1; import software.amazon.polymorph.smithyjava.generator.awssdk.v2.JavaAwsSdkV2; import software.amazon.polymorph.smithyjava.generator.CodegenSubject; @@ -32,12 +33,12 @@ public static JavaAwsSdkV1 setupAwsSdkV1(Model localModel, String awsName) { localModel, namespaceForService(awsName)); return JavaAwsSdkV1.createJavaAwsSdkV1(serviceShape, localModel); } - public static JavaAwsSdkV2 setupAwsSdkV2(Model localModel, String awsName, String dafnyVersion) { + public static JavaAwsSdkV2 setupAwsSdkV2(Model localModel, String awsName, DafnyVersion dafnyVersion) { ServiceShape serviceShape = serviceFromNamespace( localModel, namespaceForService(awsName)); return JavaAwsSdkV2.createJavaAwsSdkV2(serviceShape, localModel, dafnyVersion); } - public static JavaLibrary setupLibrary(Model localModel, String namespace, String dafnyVersion) { + public static JavaLibrary setupLibrary(Model localModel, String namespace, DafnyVersion dafnyVersion) { ServiceShape serviceShape = serviceFromNamespace(localModel, namespace); return new JavaLibrary(localModel, serviceShape, CodegenSubject.AwsSdkVersion.V1, dafnyVersion); } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java index 2143d2748..d59a785d8 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 package software.amazon.polymorph.smithyjava.generator.awssdk.v2; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.nameresolver.Dafny; public class Constants { @@ -37,7 +38,7 @@ public Result DoSomething(DoSomethingRequest input) } """; - static String DoSomethingOperation(String dafnyVersion) { + static String DoSomethingOperation(DafnyVersion dafnyVersion) { return Dafny.datatypeConstructorsNeedTypeDescriptors(dafnyVersion) ? DoSomethingOperationWithTypeDescriptors : DoSomethingOperation; } @@ -72,7 +73,7 @@ public Result DoVoid(DoVoidRequest input) { } """; - static String DoVoidOperation(String dafnyVersion) { + static String DoVoidOperation(DafnyVersion dafnyVersion) { return Dafny.datatypeConstructorsNeedTypeDescriptors(dafnyVersion) ? DoVoidOperationWithTypeDescriptors : DoVoidOperation; } @@ -216,7 +217,7 @@ public String region() { } """.formatted(DoSomethingOperationWithTypeDescriptors, DoVoidOperationWithTypeDescriptors); - static String MockKmsShim(String dafnyVersion) { + static String MockKmsShim(DafnyVersion dafnyVersion) { return Dafny.datatypeConstructorsNeedTypeDescriptors(dafnyVersion) ? MockKmsShimWithTypeDescriptors : MockKmsShim; } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java index 8c714cf43..4891a5db0 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java @@ -16,6 +16,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.awssdk.TestSetupUtils; @@ -34,9 +35,9 @@ public class ShimTest extends ForEachDafnyTest { protected ShimV2 underTest; protected Model model; protected JavaAwsSdkV2 subject; - protected final String dafnyVersion; + protected final DafnyVersion dafnyVersion; - public ShimTest(String dafnyVersion) { + public ShimTest(DafnyVersion dafnyVersion) { this.dafnyVersion = dafnyVersion; model = TestSetupUtils.setupLocalModel(ModelConstants.MOCK_KMS); subject = TestSetupUtils.setupAwsSdkV2(model, "kms", dafnyVersion); diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java index cee2ae73b..47b5dda3d 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToDafnyAwsV2Test.java @@ -10,6 +10,7 @@ import java.nio.file.Path; import java.util.Map; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.awssdk.TestSetupUtils; @@ -26,9 +27,9 @@ public class ToDafnyAwsV2Test extends ForEachDafnyTest { protected final ToDafnyAwsV2 underTest; protected final Model model; - protected final String dafnyVersion; + protected final DafnyVersion dafnyVersion; - public ToDafnyAwsV2Test(String dafnyVersion) { + public ToDafnyAwsV2Test(DafnyVersion dafnyVersion) { this.dafnyVersion = dafnyVersion; model = TestSetupUtils.setupTwoLocalModel(ModelConstants.KMS_KITCHEN, ModelConstants.OTHER_NAMESPACE); underTest = new ToDafnyAwsV2(TestSetupUtils.setupAwsSdkV2(model, "kms", dafnyVersion)); diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToNativeTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToNativeTest.java index 9b1924ff3..a60c073a3 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToNativeTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ToNativeTest.java @@ -17,6 +17,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.MethodReference; import software.amazon.polymorph.smithyjava.ModelConstants; @@ -54,7 +55,7 @@ public class ToNativeTest extends ForEachDafnyTest { protected ToNativeAwsV2 underTest; protected ToNativeTestImpl underTestAbstract; protected Model model; - protected final String dafnyVersion; + protected final DafnyVersion dafnyVersion; class ToNativeTestImpl extends ToNativeAwsV2 { @@ -99,7 +100,7 @@ protected CodeBlock setWithConversionCall(MemberShape member, CodeBlock getMembe } } - public ToNativeTest(String dafnyVersion) { + public ToNativeTest(DafnyVersion dafnyVersion) { this.dafnyVersion = dafnyVersion; model = TestSetupUtils.setupTwoLocalModel(ModelConstants.KMS_KITCHEN, ModelConstants.OTHER_NAMESPACE); underTest = new ToNativeAwsV2(TestSetupUtils.setupAwsSdkV2(model, "kms", dafnyVersion)); diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/library/ModelCodegenTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/library/ModelCodegenTest.java index 900ccae81..52c9a5342 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/library/ModelCodegenTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/library/ModelCodegenTest.java @@ -7,6 +7,7 @@ import org.junit.Before; import org.junit.Test; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.awssdk.TestSetupUtils; @@ -20,7 +21,7 @@ public class ModelCodegenTest extends ForEachDafnyTest { protected ModelCodegen underTest; protected Model model; - public ModelCodegenTest(String dafnyVersion) { + public ModelCodegenTest(DafnyVersion dafnyVersion) { model = TestSetupUtils.setupLocalModel(ModelConstants.CRYPTOGRAPHY_A_STRING_OPERATION); underTest = new ModelCodegen(TestSetupUtils.setupLibrary(model, "aws.cryptography.test", dafnyVersion)); } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/nameresolver/DafnyTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/nameresolver/DafnyTest.java index eabbbf321..4606578a9 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/nameresolver/DafnyTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/nameresolver/DafnyTest.java @@ -10,6 +10,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import software.amazon.polymorph.smithydafny.DafnyVersion; import software.amazon.polymorph.smithyjava.ForEachDafnyTest; import software.amazon.polymorph.smithyjava.ModelConstants; import software.amazon.polymorph.smithyjava.generator.CodegenSubject; @@ -32,7 +33,7 @@ public class DafnyTest extends ForEachDafnyTest { Dafny underTest; protected Model model; - public DafnyTest(String dafnyVersion) { + public DafnyTest(DafnyVersion dafnyVersion) { String rawModel = """ namespace smithy.example service Example {} From 82349d6ecfad4c5ac2c8413016f57ff9330a49d9 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Tue, 31 Oct 2023 15:05:27 -0700 Subject: [PATCH 30/49] License headers --- .../software/amazon/polymorph/smithydafny/DafnyVersion.java | 2 ++ .../amazon/polymorph/smithydafny/DafnyVersionCompareToTest.java | 2 ++ .../amazon/polymorph/smithydafny/DafnyVersionParsingTest.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java index fb3a14416..dbbdbe726 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java @@ -1,3 +1,5 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 package software.amazon.polymorph.smithydafny; import java.util.Comparator; diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionCompareToTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionCompareToTest.java index 3f3b4193e..c99e7fa03 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionCompareToTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionCompareToTest.java @@ -1,3 +1,5 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 package software.amazon.polymorph.smithydafny; import org.junit.Test; diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionParsingTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionParsingTest.java index 5e596e1ad..80be8805d 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionParsingTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithydafny/DafnyVersionParsingTest.java @@ -1,3 +1,5 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 package software.amazon.polymorph.smithydafny; import org.junit.Test; From 60557cb7c7c2bf5bd65201085fae39bbfaea696d Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 12:21:41 -0700 Subject: [PATCH 31/49] Move interop methods into Dafny (StandardLibrary and abstract server modules) Confirmed it works with KMS - still have to update all other test models --- .../services/kms/internal/__default.java | 17 +-- .../StandardLibrary/src/Index.dfy | 1 + .../StandardLibrary/src/WrappersInterop.dfy | 26 ++++ .../smithydafny/DafnyApiCodegen.java | 22 +++- .../smithyjava/generator/awssdk/Shim.java | 117 ------------------ .../generator/awssdk/v1/ShimV1.java | 10 +- .../generator/awssdk/v2/ShimV2.java | 10 +- 7 files changed, 60 insertions(+), 143 deletions(-) create mode 100644 TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy delete mode 100644 codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java diff --git a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java index 375648370..467d64278 100644 --- a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java +++ b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java @@ -12,6 +12,7 @@ import software.amazon.cryptography.services.kms.internaldafny.types.Error; import software.amazon.cryptography.services.kms.internaldafny.types.IKMSClient; +import StandardLibrary_Compile.Interop_Compile.WrappersInterop; import Wrappers_Compile.Option; import Wrappers_Compile.Result; @@ -26,11 +27,11 @@ public static Result KMSClient() { String region = regionProvider.getRegion().toString(); KmsClient client = builder.build(); IKMSClient shim = new Shim(client, region); - return Shim.createSuccessOfClient(shim); + return CreateSuccessOfClient(shim); } catch (Exception e) { Error dafny_error = Error.create_KMSInternalException( - Shim.createStringSome(CharacterSequence(e.getMessage()))); - return Shim.createFailureOfError(dafny_error); + WrappersInterop.CreateStringSome(CharacterSequence(e.getMessage()))); + return CreateFailureOfError(dafny_error); } } @@ -39,11 +40,11 @@ public static Result KMSClient(final String region) { KmsClientBuilder builder = KmsClient.builder(); KmsClient client = builder.region(Region.of(region)).build(); IKMSClient shim = new Shim(client, region); - return Shim.createSuccessOfClient(shim); + return CreateSuccessOfClient(shim); } catch (Exception e) { Error dafny_error = Error.create_KMSInternalException( - Shim.createStringSome(CharacterSequence(e.getMessage()))); - return Shim.createFailureOfError(dafny_error); + WrappersInterop.CreateStringSome(CharacterSequence(e.getMessage()))); + return CreateFailureOfError(dafny_error); } } @@ -60,13 +61,13 @@ public static Wrappers_Compile.Option RegionMatch( // have no way to determine what region it is // configured with. if (shim.region() == null) { - return Shim.createBooleanNone(); + return WrappersInterop.CreateBooleanNone(); } // Otherwise we kept record of the region // when we created the client. String shimRegion = shim.region(); String regionStr = String(region); - return Shim.createBooleanSome(regionStr.equals(shimRegion)); + return WrappersInterop.CreateBooleanSome(regionStr.equals(shimRegion)); } } diff --git a/TestModels/dafny-dependencies/StandardLibrary/src/Index.dfy b/TestModels/dafny-dependencies/StandardLibrary/src/Index.dfy index 1b47b6c9f..e9c061a82 100644 --- a/TestModels/dafny-dependencies/StandardLibrary/src/Index.dfy +++ b/TestModels/dafny-dependencies/StandardLibrary/src/Index.dfy @@ -1,6 +1,7 @@ // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +include "./WrappersInterop.dfy" include "./StandardLibrary.dfy" include "./UInt.dfy" include "./UTF8.dfy" \ No newline at end of file diff --git a/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy b/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy new file mode 100644 index 000000000..e4994d81e --- /dev/null +++ b/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy @@ -0,0 +1,26 @@ +include "../../libraries/src/Wrappers.dfy" + +// TODO: document +module StandardLibrary.Interop { + + import opened Wrappers + + class WrappersInterop { + + static function method CreateStringSome(s: string): Option { + Some(s) + } + + static function method CreateStringNone(): Option { + None + } + + static function method CreateBooleanSome(b: bool): Option { + Some(b) + } + + static function method CreateBooleanNone(): Option { + None + } + } +} \ No newline at end of file diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java index 632d86eaf..2c54245da 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java @@ -2013,6 +2013,7 @@ public TokenTree generateAbstractAwsServiceClass(ServiceShape serviceShape) { if (!serviceShape.hasTrait(ServiceTrait.class)) throw new IllegalStateException("MUST be an AWS Service API"); final ServiceTrait serviceTrait = serviceShape.expectTrait(ServiceTrait.class); final String sdkId = serviceTrait.getSdkId(); + final String dafnyClientTrait = nameResolver.traitForServiceClient(serviceShape); final String configTypeName = "%sClientConfigType".formatted(sdkId); final TokenTree configType = TokenTree @@ -2026,7 +2027,7 @@ public TokenTree generateAbstractAwsServiceClass(ServiceShape serviceShape) { final TokenTree factory = TokenTree .of( "method {:extern} %sClient()".formatted(serviceTrait.getSdkId()), - "returns (res: Result<%s, Error>)".formatted(nameResolver.traitForServiceClient(serviceShape)), + "returns (res: Result<%s, Error>)".formatted(dafnyClientTrait), "ensures res.Success? ==> ", "&& fresh(res.value)", "&& fresh(res.value.%s)".formatted(nameResolver.mutableStateFunctionName()), @@ -2034,11 +2035,28 @@ public TokenTree generateAbstractAwsServiceClass(ServiceShape serviceShape) { "&& res.value.%s()".formatted(nameResolver.validStateInvariantName()) ).lineSeparated(); + final TokenTree createSuccessOfClient = TokenTree + .of( + "// Helper function for the benefit of native code to create a Success(client) without referring to Dafny internals", + "function method CreateSuccessOfClient(client: %s): Result<%s, Error> {".formatted(dafnyClientTrait, dafnyClientTrait), + " Success(client)", + "}" + ).lineSeparated(); + final TokenTree createFailureOfError = TokenTree + .of( + "// Helper function for the benefit of native code to create a Failure(error) without referring to Dafny internals", + "function method CreateFailureOfError(error: Error): Result<%s, Error> {".formatted(dafnyClientTrait), + " Failure(error)", + "}" + ).lineSeparated(); + return TokenTree .of( configType, defaultConfig, - factory + factory, + createSuccessOfClient, + createFailureOfError ) .lineSeparated(); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java deleted file mode 100644 index b72972130..000000000 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/Shim.java +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -package software.amazon.polymorph.smithyjava.generator.awssdk; - -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.TypeName; -import software.amazon.polymorph.smithyjava.generator.CodegenSubject; -import software.amazon.polymorph.smithyjava.generator.Generator; -import software.amazon.polymorph.smithyjava.nameresolver.Dafny; -import software.amazon.smithy.model.shapes.ShapeType; - -import static javax.lang.model.element.Modifier.PUBLIC; -import static javax.lang.model.element.Modifier.STATIC; - -public abstract class Shim extends Generator { - public Shim(CodegenSubject subject) { - super(subject); - } - - protected MethodSpec successOfClientConstructor() { - ClassName clientType = subject.dafnyNameResolver.classNameForInterface(subject.serviceShape); - ClassName errorType = subject.dafnyNameResolver.abstractClassForError(); - MethodSpec.Builder method = MethodSpec - .methodBuilder("createSuccessOfClient") - .addModifiers(STATIC, PUBLIC) - .addParameter(clientType, "client") - .returns(Dafny.asDafnyResult( - clientType, - errorType - )); - method.addStatement("return $L", - subject.dafnyNameResolver.createSuccess( - subject.dafnyNameResolver.typeDescriptor(subject.serviceShape.toShapeId()), - CodeBlock.of("client"))); - return method.build(); - } - - protected MethodSpec failureOfErrorConstructor() { - ClassName clientType = subject.dafnyNameResolver.classNameForInterface(subject.serviceShape); - ClassName errorType = subject.dafnyNameResolver.abstractClassForError(); - MethodSpec.Builder method = MethodSpec - .methodBuilder("createFailureOfError") - .addModifiers(STATIC, PUBLIC) - .addParameter(errorType, "error") - .returns(Dafny.asDafnyResult( - clientType, - subject.dafnyNameResolver.abstractClassForError() - )); - method.addStatement("return $L", - subject.dafnyNameResolver.createFailure( - subject.dafnyNameResolver.typeDescriptor(subject.serviceShape.toShapeId()), - CodeBlock.of("error"))); - return method.build(); - } - - protected MethodSpec stringSomeConstructor() { - TypeName stringType = subject.dafnyNameResolver.typeForCharacterSequence(); - MethodSpec.Builder method = MethodSpec - .methodBuilder("createStringSome") - .addModifiers(STATIC, PUBLIC) - .addParameter(stringType, "s") - .returns(Dafny.asDafnyOption( - stringType - )); - method.addStatement("return $L", - subject.dafnyNameResolver.createSome( - subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING), - CodeBlock.of("s"))); - return method.build(); - } - - protected MethodSpec stringNoneConstructor() { - TypeName stringType = subject.dafnyNameResolver.typeForCharacterSequence(); - MethodSpec.Builder method = MethodSpec - .methodBuilder("createStringNone") - .addModifiers(STATIC, PUBLIC) - .returns(Dafny.asDafnyOption( - stringType - )); - method.addStatement("return $L", - subject.dafnyNameResolver.createNone( - subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.STRING))); - return method.build(); - } - - protected MethodSpec booleanSomeConstructor() { - TypeName booleanType = TypeName.BOOLEAN.box(); - MethodSpec.Builder method = MethodSpec - .methodBuilder("createBooleanSome") - .addModifiers(STATIC, PUBLIC) - .addParameter(booleanType, "b") - .returns(Dafny.asDafnyOption( - booleanType - )); - method.addStatement("return $L", - subject.dafnyNameResolver.createSome( - subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.BOOLEAN), - CodeBlock.of("b"))); - return method.build(); - } - - protected MethodSpec booleanNoneConstructor() { - TypeName booleanType = TypeName.BOOLEAN.box(); - MethodSpec.Builder method = MethodSpec - .methodBuilder("createBooleanNone") - .addModifiers(STATIC, PUBLIC) - .returns(Dafny.asDafnyOption( - booleanType - )); - method.addStatement("return $L", - subject.dafnyNameResolver.createNone( - subject.dafnyNameResolver.TYPE_DESCRIPTOR_BY_SHAPE_TYPE.get(ShapeType.BOOLEAN))); - return method.build(); - } -} diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java index 041db765a..24ae28a3e 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java @@ -19,7 +19,7 @@ import javax.lang.model.element.Modifier; -import software.amazon.polymorph.smithyjava.generator.awssdk.Shim; +import software.amazon.polymorph.smithyjava.generator.Generator; import software.amazon.polymorph.utils.DafnyNameResolverHelpers; import software.amazon.polymorph.smithyjava.nameresolver.Dafny; import software.amazon.smithy.model.shapes.OperationShape; @@ -34,7 +34,7 @@ * Generates an AWS SDK Shim for the AWS SKD for Java V1 * exposing an AWS Service's operations to Dafny Generated Java. */ -public class ShimV1 extends Shim { +public class ShimV1 extends Generator { public static final String SHIM = "Shim"; // Hack to override CodegenSubject // See code comment on ../library/ModelCodegen for details. @@ -69,12 +69,6 @@ TypeSpec shim() { .addField( ClassName.get(String.class), "region", Modifier.PRIVATE, Modifier.FINAL) - .addMethod(successOfClientConstructor()) - .addMethod(failureOfErrorConstructor()) - .addMethod(stringSomeConstructor()) - .addMethod(stringNoneConstructor()) - .addMethod(booleanSomeConstructor()) - .addMethod(booleanNoneConstructor()) .addMethod(constructor()) .addMethod(impl()) .addMethod(region()) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java index d573d09c5..c13dfec57 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java @@ -19,7 +19,7 @@ import javax.lang.model.element.Modifier; -import software.amazon.polymorph.smithyjava.generator.awssdk.Shim; +import software.amazon.polymorph.smithyjava.generator.Generator; import software.amazon.polymorph.utils.DafnyNameResolverHelpers; import software.amazon.polymorph.smithyjava.nameresolver.Dafny; import software.amazon.smithy.model.shapes.OperationShape; @@ -34,7 +34,7 @@ * Generates an AWS SDK Shim for the AWS SDK for Java V2 * exposing an AWS Service's operations to Dafny Generated Java. */ -public class ShimV2 extends Shim { +public class ShimV2 extends Generator { public static final String SHIM = "Shim"; // Hack to override CodegenSubject // See code comment on ../library/ModelCodegen for details. @@ -70,12 +70,6 @@ TypeSpec shim() { .addField( ClassName.get(String.class), "region", Modifier.PRIVATE, Modifier.FINAL) - .addMethod(successOfClientConstructor()) - .addMethod(failureOfErrorConstructor()) - .addMethod(stringSomeConstructor()) - .addMethod(stringNoneConstructor()) - .addMethod(booleanSomeConstructor()) - .addMethod(booleanNoneConstructor()) .addMethod(constructor()) .addMethod(impl()) .addMethod(region()) From 7c693c9ded2e312b7c939b898770dc13a3fb9373 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 12:44:32 -0700 Subject: [PATCH 32/49] Use the same helpers for test wrappers too --- .../internaldafny/wrapped/__default.java | 2 +- .../smithydafny/DafnyApiCodegen.java | 24 ++++++++++++++++--- .../library/shims/TestServiceShim.java | 18 -------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java b/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java index 3b518ad70..c6bcb7541 100644 --- a/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java +++ b/TestModels/Resource/runtimes/java/src/test/java/simple/resources/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleResources(Simpl simple.resources.model.SimpleResourcesConfig wrappedConfig = ToNative.SimpleResourcesConfig(config); simple.resources.SimpleResources impl = SimpleResources.builder().SimpleResourcesConfig(wrappedConfig).build(); TestSimpleResources wrappedClient = TestSimpleResources.builder().impl(impl).build(); - return TestSimpleResources.createSuccessOfClient(wrappedClient); + return simple.resources.internaldafny.__default.CreateSuccessOfClient(wrappedClient); } } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java index 2c54245da..78df9feb2 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java @@ -1953,7 +1953,8 @@ public TokenTree generateAbstractLocalService(ServiceShape serviceShape) { return TokenTree .of( defaultConfig, - serviceMethod + serviceMethod, + generateResultOfClientHelperFunctions("I%sClient".formatted(localServiceTrait.getSdkId())) ) .lineSeparated(); } @@ -2055,12 +2056,29 @@ public TokenTree generateAbstractAwsServiceClass(ServiceShape serviceShape) { configType, defaultConfig, factory, - createSuccessOfClient, - createFailureOfError + generateResultOfClientHelperFunctions(dafnyClientTrait) ) .lineSeparated(); } + private static TokenTree generateResultOfClientHelperFunctions(String dafnyClientTrait) { + final TokenTree createSuccessOfClient = TokenTree + .of( + "// Helper function for the benefit of native code to create a Success(client) without referring to Dafny internals", + "function method CreateSuccessOfClient(client: %s): Result<%s, Error> {".formatted(dafnyClientTrait, dafnyClientTrait), + " Success(client)", + "}" + ).lineSeparated(); + final TokenTree createFailureOfError = TokenTree + .of( + "// Helper function for the benefit of native code to create a Failure(error) without referring to Dafny internals", + "function method CreateFailureOfError(error: Error): Result<%s, Error> {".formatted(dafnyClientTrait), + " Failure(error)", + "}" + ).lineSeparated(); + return TokenTree.of(createSuccessOfClient, createFailureOfError); + } + private static TokenTree generateLengthConstraint(final LengthTrait lengthTrait) { final String min = lengthTrait.getMin().map("%s <="::formatted).orElse(""); final String max = lengthTrait.getMax().map("<= %s"::formatted).orElse(""); diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java index 7c04a0890..b21fbe320 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java @@ -62,8 +62,6 @@ protected TypeSpec shim() { spec.addMethod(testServiceConstructor(builderSpecs)); // Add public static method for creating a builder spec.addMethod(builderSpecs.builderMethod()); - // Add public static method for creating a Success(client) - spec.addMethod(successOfTestServiceConstructor()); spec.addMethods(getOperationsForTarget().stream() .map(shape -> Operation.AsDafny.operation(shape, this.subject, this)) @@ -113,20 +111,4 @@ private MethodSpec testServiceConstructor(BuilderSpecs builderSpecs) { return method.build(); } - private MethodSpec successOfTestServiceConstructor() { - MethodSpec.Builder method = MethodSpec - .methodBuilder("createSuccessOfClient") - .addModifiers(STATIC, PUBLIC) - .addParameter(thisClassName, "client") - .returns(Dafny.asDafnyResult( - subject.dafnyNameResolver.classNameForInterface(this.targetShape), - subject.dafnyNameResolver.abstractClassForError() - )); - method.addStatement("return $L", - subject.dafnyNameResolver.createSuccess( - subject.dafnyNameResolver.typeDescriptor(targetShape.toShapeId()), - CodeBlock.of("client"))); - return method.build(); - } - } From f7c80691cf35beacf21093ba3597c21cbf800edb Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 13:17:50 -0700 Subject: [PATCH 33/49] Fix remaining TestModels --- .../constraints/internaldafny/wrapped/__default.java | 2 +- .../simple/errors/internaldafny/wrapped/__default.java | 2 +- .../resources/internaldafny/wrapped/__default.java | 2 +- .../localservice/internaldafny/wrapped/__default.java | 2 +- .../services/dynamodb/internaldafny/__default.java | 7 ++++--- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java b/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java index cbf416d20..d3f1b383a 100644 --- a/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java +++ b/TestModels/Constraints/runtimes/java/src/test/java/simple/constraints/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleConstraints(S simple.constraints.model.SimpleConstraintsConfig wrappedConfig = ToNative.SimpleConstraintsConfig(config); simple.constraints.SimpleConstraints impl = SimpleConstraints.builder().SimpleConstraintsConfig(wrappedConfig).build(); TestSimpleConstraints wrappedClient = TestSimpleConstraints.builder().impl(impl).build(); - return TestSimpleConstraints.createSuccessOfClient(wrappedClient); + return simple.constraints.internaldafny.__default.CreateSuccessOfClient(wrappedClient); } } diff --git a/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java b/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java index 3e482c594..eaa10a352 100644 --- a/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java +++ b/TestModels/Errors/runtimes/java/src/test/java/simple/errors/internaldafny/wrapped/__default.java @@ -16,6 +16,6 @@ public static Result WrappedSimpleErrors(SimpleError simple.errors.model.SimpleErrorsConfig wrappedConfig = ToNative.SimpleErrorsConfig(config); simple.errors.SimpleErrors impl = SimpleErrors.builder().SimpleErrorsConfig(wrappedConfig).build(); TestSimpleErrors wrappedClient = TestSimpleErrors.builder().impl(impl).build(); - return TestSimpleErrors.createSuccessOfClient(wrappedClient); + return simple.errors.internaldafny.__default.CreateSuccessOfClient(wrappedClient); } } diff --git a/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java b/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java index 991c6b7ec..48539bd0e 100644 --- a/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java +++ b/TestModels/Extendable/runtimes/java/src/test/java/software/simple/extendable/resources/internaldafny/wrapped/__default.java @@ -22,7 +22,7 @@ public static Result WrappedSimpleExten simple.extendable.resources.model.SimpleExtendableResourcesConfig wrappedConfig = ToNative.SimpleExtendableResourcesConfig(config); simple.extendable.resources.SimpleExtendableResources impl = SimpleExtendableResources.builder().SimpleExtendableResourcesConfig(wrappedConfig).build(); TestSimpleExtendableResources wrappedClient = TestSimpleExtendableResources.builder().impl(impl).build(); - return TestSimpleExtendableResources.createSuccessOfClient(wrappedClient); + return simple.extendable.resources.internaldafny.__default.CreateSuccessOfClient(wrappedClient); } /** diff --git a/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java b/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java index 4fc673448..83c663be5 100644 --- a/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java +++ b/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java @@ -18,7 +18,7 @@ public static Result WrappedSimpleLocalService simple.localservice.SimpleLocalService impl = SimpleLocalService.builder().SimpleLocalServiceConfig(wrappedConfig).build(); TestToNativeAndToDafnyLocalService(impl); TestSimpleLocalService wrappedClient = TestSimpleLocalService.builder().impl(impl).build(); - return TestSimpleLocalService.createSuccessOfClient(wrappedClient); + return simple.localservice.internaldafny.__default.createSuccessOfClient(wrappedClient); } // TODO: Determine how to replace this test with Dafny Source Code diff --git a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java index da91c1dba..24a44fb2c 100644 --- a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java +++ b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java @@ -4,6 +4,7 @@ import software.amazon.cryptography.services.dynamodb.internaldafny.types.IDynamoDBClient; import software.amazon.cryptography.services.dynamodb.internaldafny.types.Error; +import StandardLibrary_Compile.Interop_Compile.WrappersInterop; import Wrappers_Compile.Option; import Wrappers_Compile.Result; import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; @@ -25,11 +26,11 @@ public static Result DynamoDBClient() { .build(); IDynamoDBClient shim = new Shim(ddbClient, region.toString()); - return Shim.createSuccessOfClient(shim); + return CreateSuccessOfClient(shim); } catch (Exception e) { Error dafny_error = Error.create_InternalServerError( - Shim.createStringSome(CharacterSequence(e.getMessage()))); - return Shim.createFailureOfError(dafny_error); + WrappersInterop.CreateStringSome(CharacterSequence(e.getMessage()))); + return CreateFailureOfError(dafny_error); } } } From e27cd3e729aa1e629377eaf4aeab7c170ec579e6 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 13:21:56 -0700 Subject: [PATCH 34/49] Fix unit tests --- .../generator/awssdk/v2/Constants.java | 61 ------------------- .../generator/awssdk/v2/ShimTest.java | 2 - 2 files changed, 63 deletions(-) diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java index d59a785d8..74c15969a 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/Constants.java @@ -81,12 +81,8 @@ static String DoVoidOperation(DafnyVersion dafnyVersion) { static String MockKmsShim = """ package software.amazon.cryptography.services.kms.internaldafny; - import Wrappers_Compile.Option; import Wrappers_Compile.Result; - import dafny.DafnySequence; import dafny.Tuple0; - import java.lang.Boolean; - import java.lang.Character; import java.lang.Override; import java.lang.String; import software.amazon.awssdk.services.kms.KmsClient; @@ -108,32 +104,6 @@ public Shim(final KmsClient impl, final String region) { this.region = region; } - public static Result createSuccessOfClient( - IKeyManagementServiceClient client) { - return Result.create_Success(client); - } - - public static Result createFailureOfError(Error error) { - return Result.create_Failure(error); - } - - public static Option> createStringSome( - DafnySequence s) { - return Option.create_Some(s); - } - - public static Option> createStringNone() { - return Option.create_None(); - } - - public static Option createBooleanSome(Boolean b) { - return Option.create_Some(b); - } - - public static Option createBooleanNone() { - return Option.create_None(); - } - public KmsClient impl() { return this._impl; } @@ -150,13 +120,8 @@ public String region() { static String MockKmsShimWithTypeDescriptors = """ package software.amazon.cryptography.services.kms.internaldafny; - import Wrappers_Compile.Option; import Wrappers_Compile.Result; - import dafny.DafnySequence; import dafny.Tuple0; - import dafny.TypeDescriptor; - import java.lang.Boolean; - import java.lang.Character; import java.lang.Override; import java.lang.String; import software.amazon.awssdk.services.kms.KmsClient; @@ -178,32 +143,6 @@ public Shim(final KmsClient impl, final String region) { this.region = region; } - public static Result createSuccessOfClient( - IKeyManagementServiceClient client) { - return Result.create_Success(TypeDescriptor.reference(IKeyManagementServiceClient.class), Error._typeDescriptor(), client); - } - - public static Result createFailureOfError(Error error) { - return Result.create_Failure(TypeDescriptor.reference(IKeyManagementServiceClient.class), Error._typeDescriptor(), error); - } - - public static Option> createStringSome( - DafnySequence s) { - return Option.create_Some(DafnySequence._typeDescriptor(TypeDescriptor.CHAR), s); - } - - public static Option> createStringNone() { - return Option.create_None(DafnySequence._typeDescriptor(TypeDescriptor.CHAR)); - } - - public static Option createBooleanSome(Boolean b) { - return Option.create_Some(TypeDescriptor.BOOLEAN, b); - } - - public static Option createBooleanNone() { - return Option.create_None(TypeDescriptor.BOOLEAN); - } - public KmsClient impl() { return this._impl; } diff --git a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java index 4891a5db0..e5185f10a 100644 --- a/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java +++ b/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimTest.java @@ -123,8 +123,6 @@ public void generate() { assertEquals(expectedPath, actualPath); final String actualSource = actual.get(actualPath).toString(); final String mockKmsShim = MockKmsShim(dafnyVersion); - System.out.println(actualSource); - System.out.print(mockKmsShim); Tokenizer.tokenizeAndAssertEqual(mockKmsShim, actualSource); } } From ff32cc7dc03fd64ad32c9c89d4bbb9b7538162ff Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 13:26:10 -0700 Subject: [PATCH 35/49] Document new StandardLibrary module --- .../StandardLibrary/src/WrappersInterop.dfy | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy b/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy index e4994d81e..c0a9709ae 100644 --- a/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy +++ b/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy @@ -1,6 +1,14 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + include "../../libraries/src/Wrappers.dfy" -// TODO: document +// +// Helper functions for extern code to call in order to create common wrapper types. +// Currently necessary to abstract away from differences in TypeDescriptor usage +// in the Java backend across different versions of Dafny, +// but may be useful for other target languages in the future as well. +// module StandardLibrary.Interop { import opened Wrappers From 93f39db253d980be3b46e56b295236403a0168d1 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 14:00:00 -0700 Subject: [PATCH 36/49] Miscellaneous fixes --- .github/workflows/test_models_java_tests.yml | 2 +- .../internaldafny/wrapped/__default.java | 2 +- TestModels/SharedMakefile.mk | 4 ++-- .../software/amazon/polymorph/CodegenCli.java | 23 ++++++++++++------- .../smithydafny/DafnyApiCodegen.java | 2 +- .../generator/awssdk/v1/ShimV1.java | 1 + .../generator/awssdk/v2/ShimV2.java | 1 + 7 files changed, 22 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test_models_java_tests.yml b/.github/workflows/test_models_java_tests.yml index 0039e5c99..cf0968599 100644 --- a/.github/workflows/test_models_java_tests.yml +++ b/.github/workflows/test_models_java_tests.yml @@ -101,7 +101,7 @@ jobs: # Use $DAFNY_VERSION from setup-dafny-action to handle nightlies correctly run: | make polymorph_dafny - make polymorph_java DAFNY_VERSION="--dafny-version $DAFNY_VERSION" + make polymorph_java DAFNY_VERSION_OPTION="--dafny-version $DAFNY_VERSION" - name: Setup Java 8 for running tests uses: actions/setup-java@v3 diff --git a/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java b/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java index 83c663be5..8f85fc96a 100644 --- a/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java +++ b/TestModels/LocalService/runtimes/java/src/test/java/simple/localservice/internaldafny/wrapped/__default.java @@ -18,7 +18,7 @@ public static Result WrappedSimpleLocalService simple.localservice.SimpleLocalService impl = SimpleLocalService.builder().SimpleLocalServiceConfig(wrappedConfig).build(); TestToNativeAndToDafnyLocalService(impl); TestSimpleLocalService wrappedClient = TestSimpleLocalService.builder().impl(impl).build(); - return simple.localservice.internaldafny.__default.createSuccessOfClient(wrappedClient); + return simple.localservice.internaldafny.__default.CreateSuccessOfClient(wrappedClient); } // TODO: Determine how to replace this test with Dafny Source Code diff --git a/TestModels/SharedMakefile.mk b/TestModels/SharedMakefile.mk index d3f9fc510..d71267049 100644 --- a/TestModels/SharedMakefile.mk +++ b/TestModels/SharedMakefile.mk @@ -151,7 +151,7 @@ _polymorph: @: $(if ${CODEGEN_CLI_ROOT},,$(error You must pass the path CODEGEN_CLI_ROOT: CODEGEN_CLI_ROOT=/path/to/smithy-dafny/codegen/smithy-dafny-codegen-cli)); cd $(CODEGEN_CLI_ROOT); \ $(GRADLEW) run --args="\ - $(DAFNY_VERSION) \ + $(DAFNY_VERSION_OPTION) \ $(OUTPUT_DAFNY) \ $(OUTPUT_DOTNET) \ $(OUTPUT_JAVA) \ @@ -165,7 +165,7 @@ _polymorph_wrapped: @: $(if ${CODEGEN_CLI_ROOT},,$(error You must pass the path CODEGEN_CLI_ROOT: CODEGEN_CLI_ROOT=/path/to/smithy-dafny/codegen/smithy-dafny-codegen-cli)); cd $(CODEGEN_CLI_ROOT); \ $(GRADLEW) run --args="\ - $(DAFNY_VERSION) \ + $(DAFNY_VERSION_OPTION) \ $(OUTPUT_DAFNY_WRAPPED) \ $(OUTPUT_DOTNET_WRAPPED) \ $(OUTPUT_JAVA_WRAPPED) \ diff --git a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java index a636385d7..549f426ef 100644 --- a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java +++ b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java @@ -74,9 +74,9 @@ public static void main(String[] args) { .withNamespace(cliArguments.namespace) .withTargetLangOutputDirs(outputDirs) .withAwsSdkStyle(cliArguments.awsSdkStyle) - .withLocalServiceTest(cliArguments.localServiceTest); + .withLocalServiceTest(cliArguments.localServiceTest) + .withDafnyVersion(cliArguments.dafnyVersion); cliArguments.javaAwsSdkVersion.ifPresent(engineBuilder::withJavaAwsSdkVersion); - cliArguments.dafnyVersion.ifPresent(engineBuilder::withDafnyVersion); cliArguments.includeDafnyFile.ifPresent(engineBuilder::withIncludeDafnyFile); final CodegenEngine engine = engineBuilder.build(); engine.run(); @@ -123,7 +123,7 @@ private static Options getCliOptions() { .build()) .addOption(Option.builder() .longOpt("dafny-version") - .desc(" Dafny version to use. Defaults to 4.1.0") + .desc("Dafny version to generate code for") .hasArg() .build()) .addOption(Option.builder() @@ -159,7 +159,7 @@ private record CliArguments( Optional outputJavaDir, Optional outputDafnyDir, Optional javaAwsSdkVersion, - Optional dafnyVersion, + DafnyVersion dafnyVersion, Optional includeDafnyFile, boolean awsSdkStyle, boolean localServiceTest @@ -213,10 +213,17 @@ static Optional parse(String[] args) throws ParseException { } } - Optional dafnyVersion = Optional.empty(); - if (commandLine.hasOption("dafny-version")) { - final String versionStr = commandLine.getOptionValue("dafny-version").trim().toUpperCase(); - dafnyVersion = Optional.of(DafnyVersion.parse(versionStr)); + DafnyVersion dafnyVersion; + String versionStr = commandLine.getOptionValue("dafny-version"); + if (versionStr == null) { + LOGGER.error("--dafny-version option is required"); + return Optional.empty(); + } + try { + dafnyVersion = DafnyVersion.parse(versionStr.trim()); + } catch (IllegalArgumentException ex) { + LOGGER.error("Could not parse --dafny-version: {}", versionStr); + throw ex; } Optional includeDafnyFile = Optional.empty(); diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java index 78df9feb2..98eedb151 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java @@ -1954,7 +1954,7 @@ public TokenTree generateAbstractLocalService(ServiceShape serviceShape) { .of( defaultConfig, serviceMethod, - generateResultOfClientHelperFunctions("I%sClient".formatted(localServiceTrait.getSdkId())) + generateResultOfClientHelperFunctions("%sClient".formatted(localServiceTrait.getSdkId())) ) .lineSeparated(); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java index 24ae28a3e..bd80be583 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v1/ShimV1.java @@ -30,6 +30,7 @@ import static software.amazon.polymorph.smithyjava.nameresolver.Constants.DAFNY_TUPLE0_CLASS_NAME; import static software.amazon.polymorph.smithyjava.nameresolver.Constants.SMITHY_API_UNIT; +//TODO: Create abstract class for V1 & V2 to extend /** * Generates an AWS SDK Shim for the AWS SKD for Java V1 * exposing an AWS Service's operations to Dafny Generated Java. diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java index c13dfec57..577ab5a9b 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/awssdk/v2/ShimV2.java @@ -30,6 +30,7 @@ import static software.amazon.polymorph.smithyjava.nameresolver.Constants.DAFNY_TUPLE0_CLASS_NAME; import static software.amazon.polymorph.smithyjava.nameresolver.Constants.SMITHY_API_UNIT; +//TODO: Create abstract class for V1 & V2 to extend /** * Generates an AWS SDK Shim for the AWS SDK for Java V2 * exposing an AWS Service's operations to Dafny Generated Java. From 6ca9e79dc851ab06f725a5afd3fb32a418c95132 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 14:47:49 -0700 Subject: [PATCH 37/49] =?UTF-8?q?Make=20sure=20CLi=20actually=20fails=20wi?= =?UTF-8?q?thout=20=E2=80=94dafny-version,=20add=20it=20in=20CI=20everywhe?= =?UTF-8?q?re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test_models_dafny_verification.yml | 2 +- .github/workflows/test_models_java_tests.yml | 2 +- .github/workflows/test_models_net_tests.yml | 4 ++-- .../src/main/java/software/amazon/polymorph/CodegenCli.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test_models_dafny_verification.yml b/.github/workflows/test_models_dafny_verification.yml index 45ef2a399..0b24f9037 100644 --- a/.github/workflows/test_models_dafny_verification.yml +++ b/.github/workflows/test_models_dafny_verification.yml @@ -66,7 +66,7 @@ jobs: shell: bash working-directory: ./${{ matrix.library }} run: | - make polymorph_dafny + make polymorph_dafny DAFNY_VERSION_OPTION="--dafny-version $DAFNY_VERSION" - name: Verify ${{ matrix.library }} Dafny code shell: bash diff --git a/.github/workflows/test_models_java_tests.yml b/.github/workflows/test_models_java_tests.yml index cf0968599..ed3b8095c 100644 --- a/.github/workflows/test_models_java_tests.yml +++ b/.github/workflows/test_models_java_tests.yml @@ -100,7 +100,7 @@ jobs: working-directory: ./${{ matrix.library }} # Use $DAFNY_VERSION from setup-dafny-action to handle nightlies correctly run: | - make polymorph_dafny + make polymorph_dafny DAFNY_VERSION_OPTION="--dafny-version $DAFNY_VERSION" make polymorph_java DAFNY_VERSION_OPTION="--dafny-version $DAFNY_VERSION" - name: Setup Java 8 for running tests diff --git a/.github/workflows/test_models_net_tests.yml b/.github/workflows/test_models_net_tests.yml index 01e6e03ce..fa639816f 100644 --- a/.github/workflows/test_models_net_tests.yml +++ b/.github/workflows/test_models_net_tests.yml @@ -99,8 +99,8 @@ jobs: shell: bash working-directory: ./${{ matrix.library }} run: | - make polymorph_dafny - make polymorph_net + make polymorph_dafny DAFNY_VERSION_OPTION="--dafny-version $DAFNY_VERSION" + make polymorph_net DAFNY_VERSION_OPTION="--dafny-version $DAFNY_VERSION" - name: Compile ${{ matrix.library }} implementation shell: bash diff --git a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java index 549f426ef..87f9d7ed6 100644 --- a/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java +++ b/codegen/smithy-dafny-codegen-cli/src/main/java/software/amazon/polymorph/CodegenCli.java @@ -217,7 +217,7 @@ static Optional parse(String[] args) throws ParseException { String versionStr = commandLine.getOptionValue("dafny-version"); if (versionStr == null) { LOGGER.error("--dafny-version option is required"); - return Optional.empty(); + System.exit(-1); } try { dafnyVersion = DafnyVersion.parse(versionStr.trim()); From 6c3ac1a52b6f4ad3a1b064883b8774032746a7cf Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 14:57:29 -0700 Subject: [PATCH 38/49] Upgrade setup-dafny-action to 1.7.0 --- .github/workflows/test_models_dafny_verification.yml | 2 +- .github/workflows/test_models_java_tests.yml | 3 +-- .github/workflows/test_models_net_tests.yml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_models_dafny_verification.yml b/.github/workflows/test_models_dafny_verification.yml index 0b24f9037..ffa9aebd8 100644 --- a/.github/workflows/test_models_dafny_verification.yml +++ b/.github/workflows/test_models_dafny_verification.yml @@ -58,7 +58,7 @@ jobs: - uses: actions/checkout@v2 - name: Setup Dafny - uses: dafny-lang/setup-dafny-action@v1.6.1 + uses: dafny-lang/setup-dafny-action@v1.7.0 with: dafny-version: ${{ inputs.dafny }} diff --git a/.github/workflows/test_models_java_tests.yml b/.github/workflows/test_models_java_tests.yml index ed3b8095c..b98c593a3 100644 --- a/.github/workflows/test_models_java_tests.yml +++ b/.github/workflows/test_models_java_tests.yml @@ -72,8 +72,7 @@ jobs: - uses: actions/checkout@v3 - name: Setup Dafny - # TODO: temporary until https://github.com/dafny-lang/setup-dafny-action/pull/19 is merged - uses: dafny-lang/setup-dafny-action@5ae5aacfdf373c46cb08f0bb852223f26cc9ecb3 + uses: dafny-lang/setup-dafny-action@v1.7.0 with: dafny-version: ${{ inputs.dafny }} diff --git a/.github/workflows/test_models_net_tests.yml b/.github/workflows/test_models_net_tests.yml index fa639816f..d6fa46e77 100644 --- a/.github/workflows/test_models_net_tests.yml +++ b/.github/workflows/test_models_net_tests.yml @@ -69,7 +69,7 @@ jobs: - uses: actions/checkout@v3 - name: Setup Dafny - uses: dafny-lang/setup-dafny-action@v1.6.1 + uses: dafny-lang/setup-dafny-action@v1.7.0 with: dafny-version: ${{ inputs.dafny }} From 31595e55212105080e5969912532317f247a85d2 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 15:13:30 -0700 Subject: [PATCH 39/49] Fix import statements for WrappersInterop --- .../cryptography/services/dynamodb/internaldafny/__default.java | 2 +- .../amazon/cryptography/services/kms/internal/__default.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java index 24a44fb2c..2640a177f 100644 --- a/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java +++ b/TestModels/aws-sdks/ddb/runtimes/java/src/main/java/software/amazon/cryptography/services/dynamodb/internaldafny/__default.java @@ -4,7 +4,7 @@ import software.amazon.cryptography.services.dynamodb.internaldafny.types.IDynamoDBClient; import software.amazon.cryptography.services.dynamodb.internaldafny.types.Error; -import StandardLibrary_Compile.Interop_Compile.WrappersInterop; +import StandardLibrary_mInterop_Compile.WrappersInterop; import Wrappers_Compile.Option; import Wrappers_Compile.Result; import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; diff --git a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java index 467d64278..60c2c0047 100644 --- a/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java +++ b/TestModels/aws-sdks/kms/runtimes/java/src/main/java/software/amazon/cryptography/services/kms/internal/__default.java @@ -12,7 +12,7 @@ import software.amazon.cryptography.services.kms.internaldafny.types.Error; import software.amazon.cryptography.services.kms.internaldafny.types.IKMSClient; -import StandardLibrary_Compile.Interop_Compile.WrappersInterop; +import StandardLibrary_mInterop_Compile.WrappersInterop; import Wrappers_Compile.Option; import Wrappers_Compile.Result; From 93052065d60f59cb3decce07193a9de5d8719c9b Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 15:22:59 -0700 Subject: [PATCH 40/49] Getting tired of only getting partial CI results --- .github/workflows/test_models_dafny_verification.yml | 1 + .github/workflows/test_models_java_tests.yml | 1 + .github/workflows/test_models_net_tests.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/test_models_dafny_verification.yml b/.github/workflows/test_models_dafny_verification.yml index ffa9aebd8..629b99d5c 100644 --- a/.github/workflows/test_models_dafny_verification.yml +++ b/.github/workflows/test_models_dafny_verification.yml @@ -12,6 +12,7 @@ on: jobs: verification: strategy: + fail-fast: false matrix: library: [ TestModels/dafny-dependencies/StandardLibrary, # This stores current Polymorph dependencies that all TestModels depend on diff --git a/.github/workflows/test_models_java_tests.yml b/.github/workflows/test_models_java_tests.yml index b98c593a3..9bbac33c5 100644 --- a/.github/workflows/test_models_java_tests.yml +++ b/.github/workflows/test_models_java_tests.yml @@ -14,6 +14,7 @@ jobs: # Don't run the nightly build on forks if: github.event_name != 'schedule' || github.repository_owner == 'smithy-lang' strategy: + fail-fast: false matrix: dafny-version: [ 4.1.0, diff --git a/.github/workflows/test_models_net_tests.yml b/.github/workflows/test_models_net_tests.yml index d6fa46e77..cc18675e5 100644 --- a/.github/workflows/test_models_net_tests.yml +++ b/.github/workflows/test_models_net_tests.yml @@ -12,6 +12,7 @@ on: jobs: testDotNet: strategy: + fail-fast: false matrix: library: [ TestModels/dafny-dependencies/StandardLibrary, # This stores current Polymorph dependencies that all TestModels depend on From f20738b41b3e25f338056ad9893efd8d63eb2b64 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 15:49:02 -0700 Subject: [PATCH 41/49] Using service client interface instead of concrete class in abstract module --- .github/workflows/pull.yml | 3 +++ .github/workflows/push.yml | 3 +++ TestModels/Constraints/src/Index.dfy | 2 +- TestModels/Errors/src/Index.dfy | 2 +- TestModels/Extendable/src/Index.dfy | 2 +- TestModels/LocalService/src/Index.dfy | 2 +- TestModels/Resource/src/Index.dfy | 2 +- .../amazon/polymorph/smithydafny/DafnyApiCodegen.java | 6 +++--- .../smithyjava/generator/library/shims/ServiceShim.java | 2 +- 9 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index 209cbff3c..a0e4609ea 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -7,6 +7,7 @@ on: jobs: pr-ci-verification: strategy: + fail-fast: false matrix: dafny-version: [ 4.1.0, @@ -17,6 +18,7 @@ jobs: dafny: ${{ matrix.dafny-version }} pr-ci-java: strategy: + fail-fast: false matrix: dafny-version: [ 4.1.0, @@ -27,6 +29,7 @@ jobs: dafny: ${{ matrix.dafny-version }} pr-ci-net: strategy: + fail-fast: false matrix: dafny-version: [ 4.1.0, diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 23f5773bd..587305f73 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -9,6 +9,7 @@ on: jobs: push-ci-verification: strategy: + fail-fast: false matrix: dafny-version: [ 4.1.0, @@ -19,6 +20,7 @@ jobs: dafny: ${{ matrix.dafny-version }} push-ci-java: strategy: + fail-fast: false matrix: dafny-version: [ 4.1.0, @@ -29,6 +31,7 @@ jobs: dafny: ${{ matrix.dafny-version }} push-ci-net: strategy: + fail-fast: false matrix: dafny-version: [ 4.1.0, diff --git a/TestModels/Constraints/src/Index.dfy b/TestModels/Constraints/src/Index.dfy index f8979e553..c1967d888 100644 --- a/TestModels/Constraints/src/Index.dfy +++ b/TestModels/Constraints/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.constraints.internaldafny" } SimpleConstraints refines A } method SimpleConstraints(config: SimpleConstraintsConfig) - returns (res: Result) + returns (res: Result) { var client := new SimpleConstraintsClient(Operations.Config); return Success(client); diff --git a/TestModels/Errors/src/Index.dfy b/TestModels/Errors/src/Index.dfy index 4588871b9..b39ad4b7b 100644 --- a/TestModels/Errors/src/Index.dfy +++ b/TestModels/Errors/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.errors.internaldafny" } SimpleErrors refines AbstractSim } method SimpleErrors(config: SimpleErrorsConfig) - returns (res: Result) + returns (res: Result) { var client := new SimpleErrorsClient(Operations.Config); return Success(client); diff --git a/TestModels/Extendable/src/Index.dfy b/TestModels/Extendable/src/Index.dfy index d3ccc91d8..5ab67455a 100644 --- a/TestModels/Extendable/src/Index.dfy +++ b/TestModels/Extendable/src/Index.dfy @@ -20,7 +20,7 @@ module // so the implementation MUST have it. config: SimpleExtendableResourcesConfig ) returns ( - res: Result + res: Result ) { var internalConfig := Operations.Config(); diff --git a/TestModels/LocalService/src/Index.dfy b/TestModels/LocalService/src/Index.dfy index 9a566b871..9d59225fd 100644 --- a/TestModels/LocalService/src/Index.dfy +++ b/TestModels/LocalService/src/Index.dfy @@ -18,7 +18,7 @@ module method SimpleLocalService( config: SimpleLocalServiceConfig ) returns ( - res: Result + res: Result ) { var client := new SimpleLocalServiceClient(Operations.Config); diff --git a/TestModels/Resource/src/Index.dfy b/TestModels/Resource/src/Index.dfy index 6df0f8d08..ab1be9fec 100644 --- a/TestModels/Resource/src/Index.dfy +++ b/TestModels/Resource/src/Index.dfy @@ -20,7 +20,7 @@ module method SimpleResources( config: SimpleResourcesConfig ) returns ( - res: Result + res: Result ) { var internalConfig: Operations.InternalConfig := Operations.Config( diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java index 98eedb151..2516984b8 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java @@ -1859,6 +1859,7 @@ private TokenTree modifiesClauseForPathToReference( public TokenTree generateAbstractLocalService(ServiceShape serviceShape) { if (!serviceShape.hasTrait(LocalServiceTrait.class)) throw new IllegalStateException("MUST be an LocalService"); final LocalServiceTrait localServiceTrait = serviceShape.expectTrait(LocalServiceTrait.class); + final String dafnyClientTrait = "I%sClient".formatted(localServiceTrait.getSdkId()); final String configTypeName = nameResolver.baseTypeForShape(localServiceTrait.getConfigId()); final String defaultFunctionMethodName = "Default%s".formatted(localServiceTrait.getConfigId().getName()); @@ -1883,8 +1884,7 @@ public TokenTree generateAbstractLocalService(ServiceShape serviceShape) { ), // Yes, Error is hard coded // this can work because we need to be able Errors from other modules... - "returns (res: Result<%sClient, Error>)\n" - .formatted(localServiceTrait.getSdkId()) + "returns (res: Result<%s, Error>)\n".formatted(dafnyClientTrait) ).lineSeparated(); // Add `requires` clauses @@ -1954,7 +1954,7 @@ public TokenTree generateAbstractLocalService(ServiceShape serviceShape) { .of( defaultConfig, serviceMethod, - generateResultOfClientHelperFunctions("%sClient".formatted(localServiceTrait.getSdkId())) + generateResultOfClientHelperFunctions(dafnyClientTrait) ) .lineSeparated(); } diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/ServiceShim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/ServiceShim.java index 5dcbc4738..96ef98e26 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/ServiceShim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/ServiceShim.java @@ -125,7 +125,7 @@ private MethodSpec serviceConstructor(BuilderSpecs builderSpecs) { method.addStatement(dafnyDeclareAndConvert(trait.getConfigId())); // Invoke client creation // i.e.: Result result = software.amazon.cryptography.primitives.internaldafny.__default.AtomicPrimitives(dafnyValue); - TypeName success = subject.dafnyNameResolver.classNameForConcreteServiceClient(subject.serviceShape); + TypeName success = subject.dafnyNameResolver.classNameForInterface(subject.serviceShape); TypeName failure = subject.dafnyNameResolver.abstractClassForError(); TypeName result = Dafny.asDafnyResult(success, failure); method.addStatement("$T $L = $T.$L($L)", From 3d3e52f561ebd175fea2b2ed1c4b8765e6ddca0a Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 16:04:41 -0700 Subject: [PATCH 42/49] Should be traitForServiceClient after all --- TestModels/SimpleTypes/SimpleBlob/src/Index.dfy | 2 +- TestModels/SimpleTypes/SimpleBoolean/src/Index.dfy | 2 +- TestModels/SimpleTypes/SimpleDouble/src/Index.dfy | 2 +- TestModels/SimpleTypes/SimpleEnum/src/Index.dfy | 2 +- TestModels/SimpleTypes/SimpleInteger/src/Index.dfy | 2 +- TestModels/SimpleTypes/SimpleLong/src/Index.dfy | 2 +- TestModels/SimpleTypes/SimpleString/src/Index.dfy | 2 +- TestModels/Union/src/Index.dfy | 2 +- .../software/amazon/polymorph/smithydafny/DafnyApiCodegen.java | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/TestModels/SimpleTypes/SimpleBlob/src/Index.dfy b/TestModels/SimpleTypes/SimpleBlob/src/Index.dfy index ec82dd2e4..5baa61e60 100644 --- a/TestModels/SimpleTypes/SimpleBlob/src/Index.dfy +++ b/TestModels/SimpleTypes/SimpleBlob/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.types.blob.internaldafny" } SimpleBlob refines AbstractS } method SimpleBlob(config: SimpleBlobConfig) - returns (res: Result) { + returns (res: Result) { var client := new SimpleBlobClient(Operations.Config); return Success(client); } diff --git a/TestModels/SimpleTypes/SimpleBoolean/src/Index.dfy b/TestModels/SimpleTypes/SimpleBoolean/src/Index.dfy index 0c068e575..3284fd21f 100644 --- a/TestModels/SimpleTypes/SimpleBoolean/src/Index.dfy +++ b/TestModels/SimpleTypes/SimpleBoolean/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.types.boolean.internaldafny" } SimpleBoolean refines Abs } method SimpleBoolean(config: SimpleBooleanConfig) - returns (res: Result) { + returns (res: Result) { var client := new SimpleBooleanClient(Operations.Config); return Success(client); } diff --git a/TestModels/SimpleTypes/SimpleDouble/src/Index.dfy b/TestModels/SimpleTypes/SimpleDouble/src/Index.dfy index b7a48b6b6..98b617c6d 100644 --- a/TestModels/SimpleTypes/SimpleDouble/src/Index.dfy +++ b/TestModels/SimpleTypes/SimpleDouble/src/Index.dfy @@ -12,7 +12,7 @@ module {:extern "simple.types.smithydouble.internaldafny" } SimpleDouble refines } method SimpleDouble(config: SimpleDoubleConfig) - returns (res: Result) { + returns (res: Result) { var client := new SimpleDoubleClient(Operations.Config); return Success(client); } diff --git a/TestModels/SimpleTypes/SimpleEnum/src/Index.dfy b/TestModels/SimpleTypes/SimpleEnum/src/Index.dfy index ae668b750..ef894dbeb 100644 --- a/TestModels/SimpleTypes/SimpleEnum/src/Index.dfy +++ b/TestModels/SimpleTypes/SimpleEnum/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.types.smithyenum.internaldafny" } SimpleEnum refines Abs } method SimpleEnum(config: SimpleEnumConfig) - returns (res: Result) { + returns (res: Result) { var client := new SimpleEnumClient(Operations.Config); return Success(client); } diff --git a/TestModels/SimpleTypes/SimpleInteger/src/Index.dfy b/TestModels/SimpleTypes/SimpleInteger/src/Index.dfy index 3dd7ea75f..f092c0e6f 100644 --- a/TestModels/SimpleTypes/SimpleInteger/src/Index.dfy +++ b/TestModels/SimpleTypes/SimpleInteger/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.types.integer.internaldafny" } SimpleInteger refines Abs } method SimpleInteger(config: SimpleIntegerConfig) - returns (res: Result) { + returns (res: Result) { var client := new SimpleIntegerClient(Operations.Config); return Success(client); } diff --git a/TestModels/SimpleTypes/SimpleLong/src/Index.dfy b/TestModels/SimpleTypes/SimpleLong/src/Index.dfy index 0680c3a1e..44ed0d0ee 100644 --- a/TestModels/SimpleTypes/SimpleLong/src/Index.dfy +++ b/TestModels/SimpleTypes/SimpleLong/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.types.smithylong.internaldafny" } SimpleLong refines Abs } method SimpleLong(config: SimpleLongConfig) - returns (res: Result) { + returns (res: Result) { var client := new SimpleLongClient(Operations.Config); return Success(client); } diff --git a/TestModels/SimpleTypes/SimpleString/src/Index.dfy b/TestModels/SimpleTypes/SimpleString/src/Index.dfy index d0d265219..e0fed14bb 100644 --- a/TestModels/SimpleTypes/SimpleString/src/Index.dfy +++ b/TestModels/SimpleTypes/SimpleString/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.types.smithystring.internaldafny" } SimpleString refines } method SimpleString(config: SimpleStringConfig) - returns (res: Result) { + returns (res: Result) { var client := new SimpleStringClient(Operations.Config); return Success(client); } diff --git a/TestModels/Union/src/Index.dfy b/TestModels/Union/src/Index.dfy index 37ae46b2d..ce6371516 100644 --- a/TestModels/Union/src/Index.dfy +++ b/TestModels/Union/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.union.internaldafny" } SimpleUnion refines AbstractSimpl } method SimpleUnion(config: SimpleUnionConfig) - returns (res: Result) + returns (res: Result) { var client := new SimpleUnionClient(Operations.Config); return Success(client); diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java index 2516984b8..77ccce8f2 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java @@ -1859,7 +1859,7 @@ private TokenTree modifiesClauseForPathToReference( public TokenTree generateAbstractLocalService(ServiceShape serviceShape) { if (!serviceShape.hasTrait(LocalServiceTrait.class)) throw new IllegalStateException("MUST be an LocalService"); final LocalServiceTrait localServiceTrait = serviceShape.expectTrait(LocalServiceTrait.class); - final String dafnyClientTrait = "I%sClient".formatted(localServiceTrait.getSdkId()); + final String dafnyClientTrait = nameResolver.traitForServiceClient(serviceShape); final String configTypeName = nameResolver.baseTypeForShape(localServiceTrait.getConfigId()); final String defaultFunctionMethodName = "Default%s".formatted(localServiceTrait.getConfigId().getName()); From 28adebbf0c46aab46974a297f20201fe51b49ede Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 16:16:24 -0700 Subject: [PATCH 43/49] Fix remaining models --- TestModels/Aggregate/src/Index.dfy | 2 +- TestModels/Constructor/src/Index.dfy | 2 +- TestModels/Dependencies/src/Index.dfy | 2 +- TestModels/Extern/src/Index.dfy | 2 +- TestModels/Refinement/src/Index.dfy | 2 +- TestModels/Union/src/Index.dfy | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/TestModels/Aggregate/src/Index.dfy b/TestModels/Aggregate/src/Index.dfy index dcc2cda02..5e845b0df 100644 --- a/TestModels/Aggregate/src/Index.dfy +++ b/TestModels/Aggregate/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.aggregate.internaldafny"} SimpleAggregate refines Abstra } method SimpleAggregate(config: SimpleAggregateConfig) - returns (res: Result) { + returns (res: Result) { var client := new SimpleAggregateClient(Operations.Config); return Success(client); } diff --git a/TestModels/Constructor/src/Index.dfy b/TestModels/Constructor/src/Index.dfy index 93aed973c..c7bc34faf 100644 --- a/TestModels/Constructor/src/Index.dfy +++ b/TestModels/Constructor/src/Index.dfy @@ -16,7 +16,7 @@ module {:extern "simple.constructor.internaldafny" } SimpleConstructor refines A } method SimpleConstructor(config: SimpleConstructorConfig) - returns (res: Result) + returns (res: Result) { var configToAssign := Operations.Config( blobValue := config.blobValue.UnwrapOr([0]), diff --git a/TestModels/Dependencies/src/Index.dfy b/TestModels/Dependencies/src/Index.dfy index 5f4ee12b5..3320e9820 100644 --- a/TestModels/Dependencies/src/Index.dfy +++ b/TestModels/Dependencies/src/Index.dfy @@ -25,7 +25,7 @@ module {:extern "simple.dependencies.internaldafny" } SimpleDependencies refines } method SimpleDependencies(config: SimpleDependenciesConfig) - returns (res: Result) + returns (res: Result) { expect config.simpleResourcesConfig.Some?; expect config.specialString.Some?; diff --git a/TestModels/Extern/src/Index.dfy b/TestModels/Extern/src/Index.dfy index cc8c5b101..845fc23cf 100644 --- a/TestModels/Extern/src/Index.dfy +++ b/TestModels/Extern/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.dafnyextern.internaldafny" } SimpleExtern refines Abstra } method SimpleExtern(config: SimpleExternConfig) - returns (res: Result) + returns (res: Result) { var client := new SimpleExternClient(Operations.Config); return Success(client); diff --git a/TestModels/Refinement/src/Index.dfy b/TestModels/Refinement/src/Index.dfy index 51b23ccc7..06205012a 100644 --- a/TestModels/Refinement/src/Index.dfy +++ b/TestModels/Refinement/src/Index.dfy @@ -12,7 +12,7 @@ module {:extern "simple.refinement.internaldafny"} SimpleRefinement refines Abst method SimpleRefinement( config: SimpleRefinementConfig ) returns ( - res: Result + res: Result ) { var client := new SimpleRefinementClient(Operations.Config); return Success(client); diff --git a/TestModels/Union/src/Index.dfy b/TestModels/Union/src/Index.dfy index ce6371516..ba859b1c5 100644 --- a/TestModels/Union/src/Index.dfy +++ b/TestModels/Union/src/Index.dfy @@ -10,7 +10,7 @@ module {:extern "simple.union.internaldafny" } SimpleUnion refines AbstractSimpl } method SimpleUnion(config: SimpleUnionConfig) - returns (res: Result) + returns (res: Result) { var client := new SimpleUnionClient(Operations.Config); return Success(client); From 183b0fa2a636a306746179866ef99d019901cadb Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 16:26:52 -0700 Subject: [PATCH 44/49] Fix Dependencies --- TestModels/Dependencies/src/SimpleDependenciesImpl.dfy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestModels/Dependencies/src/SimpleDependenciesImpl.dfy b/TestModels/Dependencies/src/SimpleDependenciesImpl.dfy index 6a0a6cabd..fc04b7ce9 100644 --- a/TestModels/Dependencies/src/SimpleDependenciesImpl.dfy +++ b/TestModels/Dependencies/src/SimpleDependenciesImpl.dfy @@ -85,7 +85,7 @@ module SimpleDependenciesImpl refines AbstractSimpleDependenciesOperations { var simpleResourcesConfig := config.simpleResourcesConfig; - var client: SimpleResources.SimpleResourcesClient :- expect SimpleResources.SimpleResources( + var client: SimpleResources.ISimpleResourcesClient :- expect SimpleResources.SimpleResources( simpleResourcesConfig ); From 937bda6eef42782be7589b552a9af607ffda571e Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Thu, 2 Nov 2023 16:44:11 -0700 Subject: [PATCH 45/49] I said, FIX DEPENDENCIES --- TestModels/Dependencies/src/SimpleDependenciesImpl.dfy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestModels/Dependencies/src/SimpleDependenciesImpl.dfy b/TestModels/Dependencies/src/SimpleDependenciesImpl.dfy index fc04b7ce9..e04099ef1 100644 --- a/TestModels/Dependencies/src/SimpleDependenciesImpl.dfy +++ b/TestModels/Dependencies/src/SimpleDependenciesImpl.dfy @@ -85,7 +85,7 @@ module SimpleDependenciesImpl refines AbstractSimpleDependenciesOperations { var simpleResourcesConfig := config.simpleResourcesConfig; - var client: SimpleResources.ISimpleResourcesClient :- expect SimpleResources.SimpleResources( + var client: SimpleResourcesTypes.ISimpleResourcesClient :- expect SimpleResources.SimpleResources( simpleResourcesConfig ); From b0527eaf00f8f3b950626073664b96365a2c5419 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Tue, 21 Nov 2023 15:34:58 -0800 Subject: [PATCH 46/49] Skip Extendable model on 4.3 --- .github/workflows/test_models_dafny_verification.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/test_models_dafny_verification.yml b/.github/workflows/test_models_dafny_verification.yml index 629b99d5c..436bc306f 100644 --- a/.github/workflows/test_models_dafny_verification.yml +++ b/.github/workflows/test_models_dafny_verification.yml @@ -14,6 +14,8 @@ jobs: strategy: fail-fast: false matrix: + dafny: + - ${{ inputs.dafny }} library: [ TestModels/dafny-dependencies/StandardLibrary, # This stores current Polymorph dependencies that all TestModels depend on TestModels/Aggregate, @@ -47,6 +49,11 @@ jobs: TestModels/aws-sdks/sqs-via-cli, ] os: [ ubuntu-latest ] + exclude: + # This model tickles a tricky Dafny verification regression to be fixed in 4.4 + # https://github.com/dafny-lang/dafny/pull/4800 + - dafny: 4.3.0 + library: TestModels/Extendable runs-on: ${{ matrix.os }} env: DOTNET_CLI_TELEMETRY_OPTOUT: 1 From 6eed66695932fa4dc1c8cdfb0351d513a3b6b487 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Wed, 22 Nov 2023 09:39:21 -0800 Subject: [PATCH 47/49] Remove dead code, more comments on the helper methods --- .../StandardLibrary/src/WrappersInterop.dfy | 20 +++++++++++++++--- .../smithydafny/DafnyApiCodegen.java | 21 ++++++------------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy b/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy index c0a9709ae..84e91c4a2 100644 --- a/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy +++ b/TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy @@ -5,9 +5,23 @@ include "../../libraries/src/Wrappers.dfy" // // Helper functions for extern code to call in order to create common wrapper types. -// Currently necessary to abstract away from differences in TypeDescriptor usage -// in the Java backend across different versions of Dafny, -// but may be useful for other target languages in the future as well. +// +// This is currently necessary to abstract away from differences in TypeDescriptor usage +// in the Java backend across different versions of Dafny: +// after Dafny 4.2 methods like Option.create_Some() +// also require explicit TypeDescriptor arguments. +// If we declare a `CreateSome(t: T)` function, +// the compiled version may or may not need a type descriptor, +// which means test models would need to have different Java code for different Dafny versions. +// But if we define a non-generic version for a specific type, +// Dafny will emit the right type descriptor instances inside the compiled method, +// so the calling signature is the same across Dafny versions. +// +// These may be useful for other target languages in the future as well, +// to similarly abstract away from Dafny compilation internal details. +// +// See also DafnyApiCodegen.generateResultOfClientHelperFunctions(), +// which solves the same problem by emitting similar helper methods for each client type. // module StandardLibrary.Interop { diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java index 77ccce8f2..d8afb4859 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java @@ -2036,21 +2036,6 @@ public TokenTree generateAbstractAwsServiceClass(ServiceShape serviceShape) { "&& res.value.%s()".formatted(nameResolver.validStateInvariantName()) ).lineSeparated(); - final TokenTree createSuccessOfClient = TokenTree - .of( - "// Helper function for the benefit of native code to create a Success(client) without referring to Dafny internals", - "function method CreateSuccessOfClient(client: %s): Result<%s, Error> {".formatted(dafnyClientTrait, dafnyClientTrait), - " Success(client)", - "}" - ).lineSeparated(); - final TokenTree createFailureOfError = TokenTree - .of( - "// Helper function for the benefit of native code to create a Failure(error) without referring to Dafny internals", - "function method CreateFailureOfError(error: Error): Result<%s, Error> {".formatted(dafnyClientTrait), - " Failure(error)", - "}" - ).lineSeparated(); - return TokenTree .of( configType, @@ -2061,6 +2046,12 @@ public TokenTree generateAbstractAwsServiceClass(ServiceShape serviceShape) { .lineSeparated(); } + /** + * Generates Dafny methods that don't need to accept TypeDescriptors in some versions of Dafny, + * so that test models can have a single copy of Java code across multiple versions of Dafny. + * + * See also TestModels/dafny-dependencies/StandardLibrary/src/WrappersInterop.dfy. + */ private static TokenTree generateResultOfClientHelperFunctions(String dafnyClientTrait) { final TokenTree createSuccessOfClient = TokenTree .of( From 0db5dec93d356c75f42f979cf03d9a539016708a Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 27 Nov 2023 14:20:00 -0800 Subject: [PATCH 48/49] Apply suggestions from code review Co-authored-by: Tony Knapp <5892063+texastony@users.noreply.github.com> --- .../amazon/polymorph/smithyjava/nameresolver/Dafny.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index 2af640920..061f2d4fe 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -97,6 +97,7 @@ public static String datatypeConstructorCreate(String name, boolean isRecordType return "create_" + DafnyNameResolverHelpers.dafnyCompilesExtra_(name); } + // Dafnys greater than or equal to this will need Type Descriptors for constructing datatypes private static final DafnyVersion NEEDS_TYPE_DESCRIPTORS_WHEN_CONSTRUCTING_DATATYPES = new DafnyVersion(4, 2, 0); public static boolean datatypeConstructorsNeedTypeDescriptors(DafnyVersion dafnyVersion) { @@ -397,7 +398,7 @@ TypeName typeForString(StringShape shape) { return typeForCharacterSequence(); } - public TypeName typeForCharacterSequence() { + TypeName typeForCharacterSequence() { return ParameterizedTypeName.get( Constants.DAFNY_SEQUENCE_CLASS_NAME, WildcardTypeName.subtypeOf(Character.class) From 855d3297344aeb89aecd5fa373182c8747b68380 Mon Sep 17 00:00:00 2001 From: Robin Salkeld Date: Mon, 27 Nov 2023 15:00:01 -0800 Subject: [PATCH 49/49] PR feedback --- .github/workflows/pull.yml | 27 ++++++++++--------- .github/workflows/push.yml | 27 ++++++++++--------- .../library/shims/TestServiceShim.java | 3 --- .../smithyjava/nameresolver/Dafny.java | 27 +++++++++++++++++-- 4 files changed, 55 insertions(+), 29 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index a0e4609ea..9eb93e9f5 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -5,36 +5,39 @@ on: pull_request: jobs: + pr-populate-dafny-versions: + runs-on: ubuntu-latest + steps: + - name: Populate Dafny versions list + id: populate-dafny-versions-list + run: echo "dafny-versions-list=['4.1.0', '4.3.0']" >> $GITHUB_OUTPUT + outputs: + dafny-version-list: ${{ steps.populate-dafny-versions-list.outputs.dafny-versions-list }} + pr-ci-verification: + needs: pr-populate-dafny-versions strategy: fail-fast: false matrix: - dafny-version: [ - 4.1.0, - 4.3.0 - ] + dafny-version: ${{ fromJson(needs.pr-populate-dafny-versions.outputs.dafny-version-list) }} uses: ./.github/workflows/test_models_dafny_verification.yml with: dafny: ${{ matrix.dafny-version }} pr-ci-java: + needs: pr-populate-dafny-versions strategy: fail-fast: false matrix: - dafny-version: [ - 4.1.0, - 4.3.0 - ] + dafny-version: ${{ fromJson(needs.pr-populate-dafny-versions.outputs.dafny-version-list) }} uses: ./.github/workflows/test_models_java_tests.yml with: dafny: ${{ matrix.dafny-version }} pr-ci-net: + needs: pr-populate-dafny-versions strategy: fail-fast: false matrix: - dafny-version: [ - 4.1.0, - 4.3.0 - ] + dafny-version: ${{ fromJson(needs.pr-populate-dafny-versions.outputs.dafny-version-list) }} uses: ./.github/workflows/test_models_net_tests.yml with: dafny: ${{ matrix.dafny-version }} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 587305f73..40021d927 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -7,36 +7,39 @@ on: - main-1.x jobs: + pr-populate-dafny-versions: + runs-on: ubuntu-latest + steps: + - name: Populate Dafny versions list + id: populate-dafny-versions-list + run: echo "dafny-versions-list=['4.1.0', '4.3.0']" >> $GITHUB_OUTPUT + outputs: + dafny-version-list: ${{ steps.populate-dafny-versions-list.outputs.dafny-versions-list }} + push-ci-verification: + needs: pr-populate-dafny-versions strategy: fail-fast: false matrix: - dafny-version: [ - 4.1.0, - 4.3.0 - ] + dafny-version: ${{ fromJson(needs.pr-populate-dafny-versions.outputs.dafny-version-list) }} uses: ./.github/workflows/test_models_dafny_verification.yml with: dafny: ${{ matrix.dafny-version }} push-ci-java: + needs: pr-populate-dafny-versions strategy: fail-fast: false matrix: - dafny-version: [ - 4.1.0, - 4.3.0 - ] + dafny-version: ${{ fromJson(needs.pr-populate-dafny-versions.outputs.dafny-version-list) }} uses: ./.github/workflows/test_models_java_tests.yml with: dafny: ${{ matrix.dafny-version }} push-ci-net: + needs: pr-populate-dafny-versions strategy: fail-fast: false matrix: - dafny-version: [ - 4.1.0, - 4.3.0 - ] + dafny-version: ${{ fromJson(needs.pr-populate-dafny-versions.outputs.dafny-version-list) }} uses: ./.github/workflows/test_models_net_tests.yml with: dafny: ${{ matrix.dafny-version }} diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java index b21fbe320..ef5d82595 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/generator/library/shims/TestServiceShim.java @@ -3,7 +3,6 @@ package software.amazon.polymorph.smithyjava.generator.library.shims; import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; @@ -19,12 +18,10 @@ import software.amazon.polymorph.smithyjava.BuilderSpecs; import software.amazon.polymorph.smithyjava.generator.library.JavaLibrary; import software.amazon.polymorph.smithyjava.modeled.Operation; -import software.amazon.polymorph.smithyjava.nameresolver.Dafny; import software.amazon.smithy.model.shapes.ServiceShape; import static javax.lang.model.element.Modifier.PROTECTED; import static javax.lang.model.element.Modifier.PUBLIC; -import static javax.lang.model.element.Modifier.STATIC; public class TestServiceShim extends ServiceShim { /** The Service Shape this Shim Tests. */ diff --git a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java index 061f2d4fe..550047a9a 100644 --- a/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java +++ b/codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java @@ -100,6 +100,9 @@ public static String datatypeConstructorCreate(String name, boolean isRecordType // Dafnys greater than or equal to this will need Type Descriptors for constructing datatypes private static final DafnyVersion NEEDS_TYPE_DESCRIPTORS_WHEN_CONSTRUCTING_DATATYPES = new DafnyVersion(4, 2, 0); + /** + * @return Whether the given Dafny version requires type descriptor values when instantiating datatype constructors. + */ public static boolean datatypeConstructorsNeedTypeDescriptors(DafnyVersion dafnyVersion) { return dafnyVersion.compareTo(NEEDS_TYPE_DESCRIPTORS_WHEN_CONSTRUCTING_DATATYPES) >= 0; } @@ -108,6 +111,11 @@ private boolean datatypeConstructorsNeedTypeDescriptors() { return datatypeConstructorsNeedTypeDescriptors(dafnyVersion); } + /** + * Code to create an instance of the None constructor of Wrappers.Option. + * @param typeDescriptor the code to create a TypeDescriptor for the type T, + * which is needed if datatypeConstructorsNeedTypeDescriptors() + */ public CodeBlock createNone(CodeBlock typeDescriptor) { if (datatypeConstructorsNeedTypeDescriptors()) { return CodeBlock.of( @@ -121,6 +129,11 @@ public CodeBlock createNone(CodeBlock typeDescriptor) { } } + /** + * Code to create an instance of the Some(value: T) constructor of Wrappers.Option. + * @param typeDescriptor the code to create a TypeDescriptor for the type T, + * which is needed if datatypeConstructorsNeedTypeDescriptors() + */ public CodeBlock createSome(CodeBlock typeDescriptor, CodeBlock value) { if (datatypeConstructorsNeedTypeDescriptors()) { return CodeBlock.of( @@ -136,6 +149,11 @@ public CodeBlock createSome(CodeBlock typeDescriptor, CodeBlock value) { } } + /** + * Code to create an instance of the Success(value: T) constructor of Wrappers.Result. + * @param valueTypeDescriptor the code to create a TypeDescriptor for the type T, + * which is needed if datatypeConstructorsNeedTypeDescriptors() + */ public CodeBlock createSuccess(CodeBlock valueTypeDescriptor, CodeBlock value) { if (datatypeConstructorsNeedTypeDescriptors()) { return CodeBlock.of( @@ -151,12 +169,17 @@ public CodeBlock createSuccess(CodeBlock valueTypeDescriptor, CodeBlock value) { } } - public CodeBlock createFailure(CodeBlock typeDescriptor, CodeBlock error) { + /** + * Code to create an instance of the Failure(error: Error) constructor of Wrappers.Result. + * @param valueTypeDescriptor the code to create a TypeDescriptor for the type T, + * which is needed if datatypeConstructorsNeedTypeDescriptors() + */ + public CodeBlock createFailure(CodeBlock valueTypeDescriptor, CodeBlock error) { if (datatypeConstructorsNeedTypeDescriptors()) { return CodeBlock.of( "$T.create_Failure($L, Error._typeDescriptor(), $L)", Constants.DAFNY_RESULT_CLASS_NAME, - typeDescriptor, + valueTypeDescriptor, error); } else { return CodeBlock.of(