Generate json encoders for choice args/results (#18834)

* Generate json encoders for choice args/results
This commit is contained in:
Alex Matson 2024-03-26 12:31:42 -04:00 committed by GitHub
parent 9fa944a38b
commit 78e02aed89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 44 additions and 6 deletions

View File

@ -85,7 +85,7 @@ object DecoderClass {
private val decodersField = FieldSpec private val decodersField = FieldSpec
.builder(contractDecoderType, "contractDecoder") .builder(contractDecoderType, "contractDecoder")
.addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.build() .build()
def generateStaticInitializer(templateNames: Iterable[ClassName]): CodeBlock = { def generateStaticInitializer(templateNames: Iterable[ClassName]): CodeBlock = {

View File

@ -524,7 +524,7 @@ private[inner] object TemplateClass extends StrictLogging {
Modifier.PUBLIC, Modifier.PUBLIC,
) )
.initializer( .initializer(
"$Z$T.create($>$S, value$$ -> $L,$Wvalue$$ ->$W$L,$Wvalue$$ ->$W$L,$W$L,$W$L)$<", "$Z$T.create($>$S, value$$ -> $L,$Wvalue$$ ->$W$L,$Wvalue$$ ->$W$L,$W$L,$W$L,$W$L,$W$L)$<",
fieldClass, fieldClass,
choiceName, choiceName,
generateToValueConverter( generateToValueConverter(
@ -546,6 +546,8 @@ private[inner] object TemplateClass extends StrictLogging {
), ),
FromJsonGenerator.jsonDecoderForType(choice.param), FromJsonGenerator.jsonDecoderForType(choice.param),
FromJsonGenerator.jsonDecoderForType(choice.returnType), FromJsonGenerator.jsonDecoderForType(choice.returnType),
ToJsonGenerator.encoderOf(choice.param),
ToJsonGenerator.encoderOf(choice.returnType),
) )
.build() .build()
}.toSeq }.toSeq

View File

@ -244,7 +244,7 @@ private[inner] object ToJsonGenerator {
.returns(fieldClass) .returns(fieldClass)
.build() .build()
private def encoderOf( private[inner] def encoderOf(
damlType: Type, damlType: Type,
nesting: Int = 0, // Used to avoid clashing argument identifiers in nested encoder definitions nesting: Int = 0, // Used to avoid clashing argument identifiers in nested encoder definitions
)(implicit packagePrefixes: PackagePrefixes): CodeBlock = { )(implicit packagePrefixes: PackagePrefixes): CodeBlock = {

View File

@ -3,12 +3,24 @@
module Bar where module Bar where
data Result = Result
with
result : Int
deriving (Eq, Show)
template Bar template Bar
with with
owner : Party owner : Party
where where
signatory owner signatory owner
choice AddOne : Result
with
value : Int
controller owner
do
return Result with result = value + 1
data ParameterizedContractId a = ParameterizedContractId data ParameterizedContractId a = ParameterizedContractId
with with
parameterizedContractId: ContractId a parameterizedContractId: ContractId a
@ -20,4 +32,3 @@ template Haha
owner : Party owner : Party
where where
signatory owner signatory owner

View File

@ -5,9 +5,12 @@ package com.daml.lf.codegen.backend.java
import com.daml.ledger.javaapi.data.Unit import com.daml.ledger.javaapi.data.Unit
import com.daml.ledger.javaapi.data.codegen.Choice import com.daml.ledger.javaapi.data.codegen.Choice
import com.daml.ledger.javaapi.data.codegen.json.JsonLfReader
import org.scalatest.matchers.should.Matchers import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec import org.scalatest.wordspec.AnyWordSpec
import ut.bar.Bar import ut.bar.Bar
import ut.bar.AddOne
import ut.bar.Result
import ut.da.internal.template.Archive import ut.da.internal.template.Archive
import scala.jdk.CollectionConverters._ import scala.jdk.CollectionConverters._
@ -23,8 +26,30 @@ final class ChoiceFieldsSpec extends AnyWordSpec with Matchers {
val choices = Bar.COMPANION.choices val choices = Bar.COMPANION.choices
val names = choices.keySet() val names = choices.keySet()
choices.size() shouldBe 1 choices.size() shouldBe 2
names shouldBe Set("Archive").asJava names shouldBe Set("Archive", "AddOne").asJava
}
"encode and decode choice arguments in json" in {
val choice: Choice[Bar, AddOne, Result] = Bar.CHOICE_AddOne
val dummyArg = new AddOne(4)
val encodedArg = choice.argJsonEncoder(dummyArg).intoString()
"{\"value\": \"4\"}" shouldBe encodedArg
val decodedArg = choice.argJsonDecoder.decode(new JsonLfReader(encodedArg))
dummyArg shouldBe decodedArg
}
"encode and decode choice results in json" in {
val choice: Choice[Bar, AddOne, Result] = Bar.CHOICE_AddOne
val dummyResult = new Result(5)
val encodedResult = choice.resultJsonEncoder(dummyResult).intoString()
"{\"result\": \"5\"}" shouldBe encodedResult
val decodedResult = choice.resultJsonDecoder.decode(new JsonLfReader(encodedResult))
dummyResult shouldBe decodedResult
} }
} }
} }