minimal Scala codegen interface support (#13858)

* add inherited choices for Scala codegen, test output exercises

CHANGELOG_BEGIN
- [scala codegen] Choices inherited from interfaces may be exercised
  directly from those templates via ``createAnd``, contract ID, or
  exercise-by-key.  Exercise by interface-contract-ID and
  interface-contract-ID types in signatures are not supported.
  See `issue #13858 <https://github.com/digital-asset/daml/pull/13858>`__.
CHANGELOG_END
This commit is contained in:
Stephen Compall 2022-05-12 08:03:00 -04:00 committed by GitHub
parent 59498586a5
commit 30e9b87279
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 6 deletions

View File

@ -17,16 +17,19 @@ load(
"lf_version_configuration",
)
# TODO(#13296) change to "latest" when interfaces released
tested_lf_config = "dev"
daml_compile(
name = "MyMain",
srcs = ["src/main/daml/MyMain.daml"],
target = lf_version_configuration.get("latest"),
target = lf_version_configuration.get(tested_lf_config),
)
daml_compile(
name = "MySecondMain",
srcs = ["src/main/daml/MySecondMain.daml"],
target = lf_version_configuration.get("latest"),
target = lf_version_configuration.get(tested_lf_config),
)
dar_to_scala(
@ -34,7 +37,7 @@ dar_to_scala(
srcs = [
":MyMain.dar",
":MySecondMain.dar",
"//daml-lf/encoder:testing-dar-latest",
"//daml-lf/encoder:testing-dar-%s" % tested_lf_config,
],
package_prefix = "com.daml.sample",
srcjar_out = "MyMain.srcjar",

View File

@ -590,3 +590,24 @@ template JustMapUser
aMap: JustMap Int Int
where
signatory party
interface InterfaceToMix where
getOwner: Party
choice InheritedOnly: () with
controller getOwner this
do return ()
{- TODO(#13349) uncomment when overloaded choices compile
choice OverloadedInTemplate: () with
controller getOwner this
do return ()
-}
template InterfaceMixer with
party: Party
where
signatory party
choice OverloadedInTemplate: () with
controller party
do return ()
implements InterfaceToMix where
getOwner = party

View File

@ -3,7 +3,9 @@
package com.daml.codegen
import com.daml.sample.MyMain.{Increment, KeyedNumber, SimpleListExample}
import com.daml.sample.MyMain
import MyMain.{KeyedNumber, Increment, SimpleListExample}
import com.daml.ledger.api.refinements.ApiTypes
import com.daml.ledger.api.v1.{commands => rpccmd}
import com.daml.ledger.client.binding.{Primitive => P}
@ -33,6 +35,42 @@ class GeneratedCommandsUT extends AnyWordSpec with Matchers with Inside {
}
}
"exercise" should {
import com.daml.ledger.client.binding.Value.encode
val imId: P.ContractId[MyMain.InterfaceMixer] = P.ContractId("fakeimid")
val DirectTemplateId = ApiTypes.TemplateId unwrap MyMain.InterfaceMixer.id
"invoke directly-defined choices" in {
inside(imId.exerciseOverloadedInTemplate(alice).command.command) {
case rpccmd.Command.Command.Exercise(
rpccmd.ExerciseCommand(
Some(DirectTemplateId),
cid,
"OverloadedInTemplate",
Some(choiceArg),
)
) =>
cid should ===(imId)
choiceArg should ===(encode(MyMain.OverloadedInTemplate()))
}
}
"invoke interface-inherited choices, directly from template" in {
inside(imId.exerciseInheritedOnly(alice).command.command) {
case rpccmd.Command.Command.Exercise(
rpccmd.ExerciseCommand(
Some(DirectTemplateId), // TODO(#13349, #13668) must be interface ID
cid,
"InheritedOnly",
Some(choiceArg),
)
) =>
cid should ===(imId)
choiceArg should ===(encode(MyMain.InheritedOnly()))
}
}
}
"key" should {
"make an exercise-by-key command" in {
inside((KeyedNumber.key(alice).exerciseIncrement(alice, 42)).command.command) {

View File

@ -74,7 +74,7 @@ object CodeGen {
roots: Seq[String],
): ValidationNel[String, Unit] =
decodeInterfaces(files).map { interfaces: NonEmptyList[EnvironmentInterface] =>
val combined = interfaces.suml1
val combined = interfaces.suml1.resolveChoices
val interface = combined.copy(
typeDecls = Util.filterTemplatesBy(roots.map(_.r))(combined.typeDecls)
)
@ -134,7 +134,7 @@ object CodeGen {
val typeDeclarationsToGenerate =
DependencyGraph.transitiveClosure(
serializableTypes = util.iface.typeDecls,
interfaces = Map.empty, // TODO(#13349)
interfaces = util.iface.astInterfaces,
)
// Each record/variant has Scala code generated for it individually, unless their names are related
@ -164,6 +164,7 @@ object CodeGen {
// 1. collect records, search variants and splat/filter
val (unassociatedRecords, splattedVariants, enums) = splatVariants(definitions)
// TODO(#13349) include interfaces as well
// 2. put templates/types into single Namespace.fromHierarchy
val treeified: Namespace[String, Option[lf.HierarchicalOutput.TemplateOrDatatype]] =
Namespace.fromHierarchy {