mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-19 08:48:21 +03:00
Enrich Templates and Interface codegen defs with PackageName and PackageVersion (#19381)
* Enrich Templates and Interface codegen defs with PackageName and PackageVersion * Make PackageVersion comparable * Apply suggestions from code review Co-authored-by: Raphael Speyer <raphael.speyer@digitalasset.com> * Fix after review suggestions --------- Co-authored-by: Raphael Speyer <raphael.speyer@digitalasset.com>
This commit is contained in:
parent
551f7a2072
commit
8980c32b7a
@ -0,0 +1,64 @@
|
||||
package com.daml.ledger.javaapi.data;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PackageVersion implements Comparable<PackageVersion> {
|
||||
private final int[] segments;
|
||||
|
||||
/**
|
||||
* Creates a PackageVersion from the provided segments.
|
||||
* <p>
|
||||
* This method is meant only for internal API usage.
|
||||
* It is marked unsafe as it does not validate the input
|
||||
* according to the accepted ledger format of PackageVersion.
|
||||
*/
|
||||
public PackageVersion(int[] segments) {
|
||||
this.segments = segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the provided String value into a PackageVersion.
|
||||
* <p>
|
||||
* This method is meant only for internal API usage.
|
||||
* It is marked unsafe as it does not validate the input
|
||||
* according to the accepted ledger format of PackageVersion.
|
||||
*/
|
||||
public static PackageVersion unsafeFromString(@NonNull String version) {
|
||||
String[] parts = version.split("\\.");
|
||||
int[] segments = new int[parts.length];
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
segments[i] = Integer.parseInt(parts[i]);
|
||||
if (segments[i] < 0) {
|
||||
throw new IllegalArgumentException("Invalid version. No negative segments allowed: " + version);
|
||||
}
|
||||
}
|
||||
return new PackageVersion(segments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(PackageVersion other) {
|
||||
return Arrays.compare(this.segments, other.segments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PackageVersion that = (PackageVersion) o;
|
||||
return Arrays.equals(segments, that.segments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(segments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.stream(segments).mapToObj(Integer::toString)
|
||||
.collect(Collectors.joining("."));
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.daml.ledger.javaapi.data
|
||||
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
import scala.util.Random
|
||||
|
||||
class PackageVersionSpec extends AnyFlatSpec with Matchers {
|
||||
|
||||
"PackageVersion" should "be parsed correctly from String" in {
|
||||
val packageVersion = PackageVersion.unsafeFromString("1.22.333")
|
||||
packageVersion.toString shouldBe "1.22.333"
|
||||
packageVersion shouldBe new PackageVersion(Array(1, 22, 333))
|
||||
}
|
||||
|
||||
"PackageVersion" should "not allow negative or non-integers" in {
|
||||
an[IllegalArgumentException] should be thrownBy PackageVersion.unsafeFromString("0.-1")
|
||||
an[IllegalArgumentException] should be thrownBy PackageVersion.unsafeFromString("0.beef")
|
||||
}
|
||||
|
||||
"PackageVersion" should "be ordered correctly" in {
|
||||
|
||||
val expectedOrderedPackageVersions = Seq(
|
||||
// Lowest possible package version
|
||||
PackageVersion.unsafeFromString("0"),
|
||||
PackageVersion.unsafeFromString("0.1"),
|
||||
PackageVersion.unsafeFromString("0.11"),
|
||||
PackageVersion.unsafeFromString("1.0"),
|
||||
PackageVersion.unsafeFromString("2"),
|
||||
PackageVersion.unsafeFromString("10"),
|
||||
PackageVersion.unsafeFromString(s"${Int.MaxValue}"),
|
||||
PackageVersion.unsafeFromString(s"${Int.MaxValue}.3"),
|
||||
PackageVersion.unsafeFromString(s"${Int.MaxValue}." * 23 + "99"),
|
||||
)
|
||||
|
||||
Random
|
||||
.shuffle(expectedOrderedPackageVersions)
|
||||
.sorted should contain theSameElementsInOrderAs expectedOrderedPackageVersions
|
||||
}
|
||||
}
|
@ -239,8 +239,10 @@ scala_source_jar(
|
||||
],
|
||||
exclude = test_exclusions.get(ver, []),
|
||||
),
|
||||
enable_interfaces = ver == "2.dev",
|
||||
project_name = "integration-tests-model",
|
||||
target = ver,
|
||||
version = "1.2.3",
|
||||
)
|
||||
for ver in COMPILER_LF_VERSIONS
|
||||
]
|
||||
|
@ -68,5 +68,5 @@ def dar_to_java(**kwargs):
|
||||
break
|
||||
|
||||
test_exclusions = {
|
||||
"2.1": ["src/it/daml/Tests/ContractKeys.daml"],
|
||||
"2.1": ["src/it/daml/Tests/ContractKeys.daml", "src/it/daml/Tests/SimpleInterface.daml"],
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
-- Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
-- SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
|
||||
module Tests.SimpleInterface where
|
||||
|
||||
data SomeViewType = SomeViewType { field: Text }
|
||||
|
||||
interface SimpleInterface where
|
||||
viewtype SomeViewType
|
@ -7,5 +7,10 @@ import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({AllGenericTests.class, ContractKeysTest.class, TextMapTest.class})
|
||||
@Suite.SuiteClasses({
|
||||
AllGenericTests.class,
|
||||
ContractKeysTest.class,
|
||||
TextMapTest.class,
|
||||
InterfacePackageNameAndVersionTest.class
|
||||
})
|
||||
public class AllTests {}
|
||||
|
@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import com.daml.ledger.javaapi.data.PackageVersion;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.platform.runner.JUnitPlatform;
|
||||
import org.junit.runner.RunWith;
|
||||
import tests.simpleinterface.SimpleInterface;
|
||||
|
||||
// TODO: Merge with PackageNameAndVersionTest.java once interfaces are marked stable
|
||||
@RunWith(JUnitPlatform.class)
|
||||
public class InterfacePackageNameAndVersionTest {
|
||||
@Test
|
||||
void packageName() {
|
||||
assertEquals(SimpleInterface.PACKAGE_NAME, "integration-tests-model");
|
||||
}
|
||||
|
||||
@Test
|
||||
void packageVersion() {
|
||||
assertEquals(SimpleInterface.PACKAGE_VERSION, PackageVersion.unsafeFromString("1.2.3"));
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import org.junit.runners.Suite;
|
||||
DecoderTest.class,
|
||||
GenMapTest.class,
|
||||
ListTest.class,
|
||||
PackageNameAndVersionTest.class,
|
||||
NumericTest.class,
|
||||
OptionalTest.class,
|
||||
ParametrizedContractIdTest.class,
|
||||
|
@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import com.daml.ledger.javaapi.data.PackageVersion;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.platform.runner.JUnitPlatform;
|
||||
import org.junit.runner.RunWith;
|
||||
import tests.template1.SimpleTemplate;
|
||||
|
||||
@RunWith(JUnitPlatform.class)
|
||||
public class PackageNameAndVersionTest {
|
||||
@Test
|
||||
void packageName() {
|
||||
assertEquals(SimpleTemplate.PACKAGE_NAME, "integration-tests-model");
|
||||
}
|
||||
|
||||
@Test
|
||||
void packageVersion() {
|
||||
assertEquals(SimpleTemplate.PACKAGE_VERSION, PackageVersion.unsafeFromString("1.2.3"));
|
||||
}
|
||||
}
|
@ -66,6 +66,7 @@ object ClassForType extends StrictLogging {
|
||||
typeWithContext.auxiliarySignatures,
|
||||
typeWithContext.interface.packageId,
|
||||
interfaceName,
|
||||
typeWithContext.interface.metadata,
|
||||
)
|
||||
} yield javaFile(packageName, interfaceClass)
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
package com.daml.lf.codegen.backend.java.inner
|
||||
|
||||
import com.daml.lf.data.Ref
|
||||
import Ref.{ChoiceName, PackageId}
|
||||
import Ref.{ChoiceName, PackageId, PackageName, PackageVersion}
|
||||
import com.daml.lf.typesig.{DefDataType, Record, TypeCon}
|
||||
import com.daml.lf.typesig.PackageSignature.TypeDecl
|
||||
|
||||
@ -50,6 +50,8 @@ private[inner] object ClassGenUtils {
|
||||
}
|
||||
|
||||
val templateIdFieldName = "TEMPLATE_ID"
|
||||
val packageNameFieldName = "PACKAGE_NAME"
|
||||
val packageVersionFieldName = "PACKAGE_VERSION"
|
||||
val companionFieldName = "COMPANION"
|
||||
val archiveChoiceName = ChoiceName assertFromString "Archive"
|
||||
|
||||
@ -71,6 +73,44 @@ private[inner] object ClassGenUtils {
|
||||
)
|
||||
.build()
|
||||
|
||||
def generatePackageNameField(packageName: PackageName) =
|
||||
FieldSpec
|
||||
.builder(
|
||||
ClassName.get(classOf[String]),
|
||||
packageNameFieldName,
|
||||
Modifier.STATIC,
|
||||
Modifier.FINAL,
|
||||
Modifier.PUBLIC,
|
||||
)
|
||||
.initializer("$S", packageName)
|
||||
.build()
|
||||
|
||||
def generatePackageVersionField(packageVersion: PackageVersion) = {
|
||||
val packageVersionSegmentIntArrLiteral =
|
||||
packageVersion.segments.toArray.mkString("{", ", ", "}")
|
||||
val intArrayTypeName = ArrayTypeName.of(classOf[Int])
|
||||
FieldSpec
|
||||
.builder(
|
||||
ClassName.get(classOf[javaapi.data.PackageVersion]),
|
||||
packageVersionFieldName,
|
||||
Modifier.STATIC,
|
||||
Modifier.FINAL,
|
||||
Modifier.PUBLIC,
|
||||
)
|
||||
.initializer(
|
||||
CodeBlock
|
||||
.builder()
|
||||
.add(
|
||||
"new $T(new $T $L)",
|
||||
ClassName.get(classOf[javaapi.data.PackageVersion]),
|
||||
intArrayTypeName,
|
||||
packageVersionSegmentIntArrLiteral,
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
def generateFlattenedCreateOrExerciseMethod(
|
||||
name: String,
|
||||
returns: TypeName,
|
||||
|
@ -8,8 +8,7 @@ import com.daml.ledger.javaapi.data.codegen.{Contract, InterfaceCompanion}
|
||||
import com.daml.lf.codegen.NodeWithContext.AuxiliarySignatures
|
||||
import com.daml.lf.codegen.backend.java.inner.TemplateClass.toChoiceNameField
|
||||
import com.daml.lf.data.Ref.{ChoiceName, PackageId, QualifiedName}
|
||||
import com.daml.lf.typesig
|
||||
import typesig.DefInterface
|
||||
import com.daml.lf.typesig.{DefInterface, PackageMetadata}
|
||||
import com.squareup.javapoet._
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import scalaz.-\/
|
||||
@ -26,6 +25,7 @@ object InterfaceClass extends StrictLogging {
|
||||
typeDeclarations: AuxiliarySignatures,
|
||||
packageId: PackageId,
|
||||
interfaceId: QualifiedName,
|
||||
packageMetadata: PackageMetadata,
|
||||
)(implicit packagePrefixes: PackagePrefixes): TypeSpec =
|
||||
TrackLineage.of("interface", interfaceName.simpleName()) {
|
||||
logger.info("Start")
|
||||
@ -33,6 +33,8 @@ object InterfaceClass extends StrictLogging {
|
||||
.classBuilder(interfaceName)
|
||||
.addModifiers(Modifier.FINAL, Modifier.PUBLIC)
|
||||
.addField(generateTemplateIdField(packageId, interfaceId))
|
||||
.addField(ClassGenUtils.generatePackageNameField(packageMetadata.name))
|
||||
.addField(ClassGenUtils.generatePackageVersionField(packageMetadata.version))
|
||||
.addFields(
|
||||
TemplateClass
|
||||
.generateChoicesMetadata(
|
||||
|
@ -4,7 +4,7 @@
|
||||
package com.daml.lf.codegen.backend.java.inner
|
||||
|
||||
import com.daml.ledger.javaapi
|
||||
import ClassGenUtils.{companionFieldName, templateIdFieldName, generateGetCompanion}
|
||||
import ClassGenUtils.{companionFieldName, generateGetCompanion, templateIdFieldName}
|
||||
import com.daml.lf.codegen.TypeWithContext
|
||||
import com.daml.lf.data.Ref
|
||||
import Ref.ChoiceName
|
||||
@ -46,6 +46,8 @@ private[inner] object TemplateClass extends StrictLogging {
|
||||
.addModifiers(Modifier.FINAL, Modifier.PUBLIC)
|
||||
.superclass(classOf[javaapi.data.Template])
|
||||
.addField(generateTemplateIdField(typeWithContext))
|
||||
.addField(generatePackageNameField(typeWithContext))
|
||||
.addField(generatePackageVersionField(typeWithContext))
|
||||
.addMethod(generateCreateMethod(className))
|
||||
.addMethods(
|
||||
generateDeprecatedStaticExerciseByKeyMethods(
|
||||
@ -504,6 +506,12 @@ private[inner] object TemplateClass extends StrictLogging {
|
||||
typeWithContext.name,
|
||||
)
|
||||
|
||||
private def generatePackageVersionField(typeWithContext: TypeWithContext) =
|
||||
ClassGenUtils.generatePackageVersionField(typeWithContext.interface.metadata.version)
|
||||
|
||||
private def generatePackageNameField(typeWithContext: TypeWithContext) =
|
||||
ClassGenUtils.generatePackageNameField(typeWithContext.interface.metadata.name)
|
||||
|
||||
def generateChoicesMetadata(
|
||||
templateClassName: ClassName,
|
||||
templateChoices: Map[ChoiceName, TemplateChoice.FWT],
|
||||
|
Loading…
Reference in New Issue
Block a user