make packagePrefixes implicit in Java codegen (#15642)

* remove the package-prefix-free overload

* switch fullyQualifiedName, the basis, to a newtyped implicit

* remove unused packagePrefixes

* remove fullyQualifiedName indirection
This commit is contained in:
Stephen Compall 2022-11-22 10:15:13 -05:00 committed by GitHub
parent 51c3865701
commit 38079ea422
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 213 additions and 289 deletions

View File

@ -7,7 +7,12 @@ import java.nio.file.{Files, Path}
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.{Executors, ThreadFactory}
import com.daml.lf.archive.DarParser
import com.daml.lf.codegen.backend.java.inner.{ClassForType, DecoderClass, fullyQualifiedName}
import com.daml.lf.codegen.backend.java.inner.{
ClassForType,
DecoderClass,
fullyQualifiedName,
PackagePrefixes,
}
import com.daml.lf.codegen.conf.{Conf, PackageReference}
import com.daml.lf.codegen.dependencygraph.DependencyGraph
import com.daml.lf.data.Ref.{Identifier, PackageId}
@ -75,13 +80,14 @@ private final class CodeGenRunner(
}
private def createTypeDefinitionClasses(module: ModuleWithContext): Iterable[JavaFile] = {
import scope.packagePrefixes
MDC.put("packageId", module.packageId)
MDC.put("packageIdShort", module.packageId.take(7))
MDC.put("moduleName", module.name)
val javaFiles =
for {
typeWithContext <- module.typesLineages
javaFile <- ClassForType(typeWithContext, scope.packagePrefixes, scope.toBeGenerated)
javaFile <- ClassForType(typeWithContext, scope.toBeGenerated)
} yield javaFile
MDC.remove("packageId")
MDC.remove("packageIdShort")
@ -95,15 +101,14 @@ object CodeGenRunner extends StrictLogging {
private[codegen] final class Scope(
val signatures: Seq[PackageSignature],
val packagePrefixes: Map[PackageId, String],
serializableTypes: Vector[(Identifier, TypeDecl)],
) {
)(implicit val packagePrefixes: PackagePrefixes) {
val toBeGenerated: Set[Identifier] = serializableTypes.view.map(_._1).toSet
val templateClassNames: Vector[ClassName] = serializableTypes.collect {
case id -> (_: TypeDecl.Template) =>
ClassName.bestGuess(fullyQualifiedName(id, packagePrefixes))
ClassName.bestGuess(fullyQualifiedName(id))
}
}
@ -173,17 +178,18 @@ object CodeGenRunner extends StrictLogging {
val resolvedSignatures = resolveRetroInterfaces(signatures)
val resolvedPrefixes =
resolvePackagePrefixes(
packagePrefixes,
modulePrefixes,
resolvedSignatures,
generatedModuleIds,
implicit val resolvedPrefixes: PackagePrefixes =
PackagePrefixes(
resolvePackagePrefixes(
packagePrefixes,
modulePrefixes,
resolvedSignatures,
generatedModuleIds,
)
)
new CodeGenRunner.Scope(
resolvedSignatures,
resolvedPrefixes,
transitiveClosure.serializableTypes,
)
}

View File

@ -5,7 +5,7 @@ package com.daml.lf.codegen.backend.java.inner
import com.daml.lf.codegen.TypeWithContext
import com.daml.lf.codegen.backend.java.JavaEscaper
import com.daml.lf.data.Ref.{PackageId, Identifier}
import com.daml.lf.data.Ref.Identifier
import com.daml.lf.typesig.{Enum, DefDataType, PackageSignature, Record, Variant}
import PackageSignature.TypeDecl
import TypeDecl.{Normal, Template}
@ -16,20 +16,19 @@ object ClassForType extends StrictLogging {
def apply(
typeWithContext: TypeWithContext,
packagePrefixes: Map[PackageId, String],
toBeGenerated: Identifier => Boolean,
): List[JavaFile] = {
)(implicit packagePrefixes: PackagePrefixes): List[JavaFile] = {
def recurOnTypeLineages: List[JavaFile] =
typeWithContext.typesLineages
.flatMap(ClassForType(_, packagePrefixes, toBeGenerated))
.flatMap(ClassForType(_, toBeGenerated))
.toList
def generateForType(lfInterfaceType: TypeDecl): List[JavaFile] = {
val classNameString = fullyQualifiedName(typeWithContext.identifier, packagePrefixes)
val classNameString = fullyQualifiedName(typeWithContext.identifier)
val className = ClassName.bestGuess(classNameString)
generateInterfaceTypes(typeWithContext, packagePrefixes) ++
generateSerializableTypes(typeWithContext, className, packagePrefixes, lfInterfaceType)
generateInterfaceTypes(typeWithContext) ++
generateSerializableTypes(typeWithContext, className, lfInterfaceType)
}
Option
@ -40,14 +39,12 @@ object ClassForType extends StrictLogging {
}
private def generateInterfaceTypes(
typeWithContext: TypeWithContext,
packagePrefixes: Map[PackageId, String],
): List[JavaFile] =
typeWithContext: TypeWithContext
)(implicit packagePrefixes: PackagePrefixes): List[JavaFile] =
for {
(interfaceName, interface) <- typeWithContext.interface.interfaces.toList
classNameString = fullyQualifiedName(
Identifier(typeWithContext.interface.packageId, interfaceName),
packagePrefixes,
Identifier(typeWithContext.interface.packageId, interfaceName)
)
className = ClassName.bestGuess(classNameString)
interfaceViewTypeName = ClassName.bestGuess(
@ -56,8 +53,7 @@ object ClassForType extends StrictLogging {
throw new IllegalArgumentException(
s"View Type is required for interface $interfaceName"
)
),
packagePrefixes,
)
)
)
packageName = className.packageName()
@ -67,7 +63,6 @@ object ClassForType extends StrictLogging {
className,
interfaceViewTypeName,
interface,
packagePrefixes,
typeWithContext.interface.typeDecls,
typeWithContext.interface.packageId,
interfaceName,
@ -77,9 +72,8 @@ object ClassForType extends StrictLogging {
private def generateSerializableTypes(
typeWithContext: TypeWithContext,
className: ClassName,
packagePrefixes: Map[PackageId, String],
lfInterfaceType: TypeDecl,
): List[JavaFile] = {
)(implicit packagePrefixes: PackagePrefixes): List[JavaFile] = {
val packageName = className.packageName()
lfInterfaceType match {
case Normal(DefDataType(typeVars, record: Record.FWT)) =>
@ -89,7 +83,6 @@ object ClassForType extends StrictLogging {
className,
typeVars.map(JavaEscaper.escapeString),
record,
packagePrefixes,
)
javaFiles(packageName, recordClass)
case Normal(DefDataType(typeVars, variant: Variant.FWT)) =>
@ -103,7 +96,6 @@ object ClassForType extends StrictLogging {
escapedTypeVars,
variant,
typeWithContext,
packagePrefixes,
)
javaFile(packageName, variantSpec) :: javaFiles(subPackage, constructorSpecs)
case Normal(DefDataType(_, enum: Enum)) =>
@ -115,7 +107,6 @@ object ClassForType extends StrictLogging {
record,
template,
typeWithContext,
packagePrefixes,
)
javaFiles(packageName, typeSpec)
}

View File

@ -29,10 +29,10 @@ private[inner] object ClassGenUtils {
val getArguments = CodeBlock.of("event.getArguments()")
val getAgreementText = CodeBlock.of("event.getAgreementText()")
def getContractKey(t: Type, packagePrefixes: Map[PackageId, String]) =
def getContractKey(t: Type)(implicit packagePrefixes: PackagePrefixes) =
CodeBlock.of(
"event.getContractKey().map(e -> $L)",
FromValueGenerator.extractor(t, "e", CodeBlock.of("e"), newNameGenerator, packagePrefixes),
FromValueGenerator.extractor(t, "e", CodeBlock.of("e"), newNameGenerator),
)
val getSignatories = CodeBlock.of("event.getSignatories()")
@ -79,14 +79,15 @@ private[inner] object ClassGenUtils {
choiceName: ChoiceName,
choice: TemplateChoice[Type],
fields: Fields,
packagePrefixes: Map[PackageId, String],
)(alter: MethodSpec.Builder => MethodSpec.Builder): MethodSpec = {
)(alter: MethodSpec.Builder => MethodSpec.Builder)(implicit
packagePrefixes: PackagePrefixes
): MethodSpec = {
val methodName = s"$name${choiceName.capitalize}"
val choiceBuilder = MethodSpec
.methodBuilder(methodName)
.addModifiers(Modifier.PUBLIC)
.returns(returns)
val javaType = toJavaTypeName(choice.param, packagePrefixes)
val javaType = toJavaTypeName(choice.param)
for (FieldInfo(_, _, javaName, javaType) <- fields) {
choiceBuilder.addParameter(javaType, javaName)
}

View File

@ -5,7 +5,6 @@ package com.daml.lf.codegen.backend.java.inner
import com.daml.ledger.javaapi
import ClassGenUtils.{companionFieldName, optional, optionalString, setOfStrings}
import com.daml.lf.data.Ref.PackageId
import com.daml.lf.typesig.Type
import com.squareup.javapoet._
import scalaz.syntax.std.option._
@ -15,11 +14,9 @@ import javax.lang.model.element.Modifier
object ContractClass {
def builder(
templateClassName: ClassName,
key: Option[Type],
packagePrefixes: Map[PackageId, String],
) = Builder.create(templateClassName, key, packagePrefixes)
def builder(templateClassName: ClassName, key: Option[Type])(implicit
packagePrefixes: PackagePrefixes
) = Builder.create(templateClassName, key)
case class Builder private (
classBuilder: TypeSpec.Builder,
@ -28,7 +25,6 @@ object ContractClass {
contractIdClassName: ClassName,
contractKeyClassName: Option[TypeName],
key: Option[Type],
packagePrefixes: Map[PackageId, String],
) {
def addGenerateFromMethods(): Builder = {
classBuilder
@ -120,14 +116,12 @@ object ContractClass {
)
}
def create(
templateClassName: ClassName,
key: Option[Type],
packagePrefixes: Map[PackageId, String],
def create(templateClassName: ClassName, key: Option[Type])(implicit
packagePrefixes: PackagePrefixes
) = {
val classBuilder =
TypeSpec.classBuilder("Contract").addModifiers(Modifier.STATIC, Modifier.PUBLIC)
val contractKeyClassName = key.map(toJavaTypeName(_, packagePrefixes))
val contractKeyClassName = key.map(toJavaTypeName(_))
import scala.language.existentials
val (contractSuperclass, keyTparams) = contractKeyClassName.cata(
@ -180,7 +174,6 @@ object ContractClass {
contractIdClassName,
contractKeyClassName,
key,
packagePrefixes,
)
}
}

View File

@ -28,12 +28,10 @@ object ContractIdClass {
templateClassName: ClassName,
choices: Map[ChoiceName, TemplateChoice[typesig.Type]],
kind: For,
packagePrefixes: Map[PackageId, String],
) = Builder.create(
templateClassName,
choices,
kind,
packagePrefixes,
)
case class Builder private (
@ -41,25 +39,22 @@ object ContractIdClass {
contractIdClassName: ClassName,
idClassBuilder: TypeSpec.Builder,
choices: Map[ChoiceName, TemplateChoice[typesig.Type]],
packagePrefixes: Map[PackageId, String],
) {
def build(): TypeSpec = idClassBuilder.build()
def addConversionForImplementedInterfaces(
implementedInterfaces: Seq[Ref.TypeConName],
packagePrefixes: Map[PackageId, String],
def addConversionForImplementedInterfaces(implementedInterfaces: Seq[Ref.TypeConName])(implicit
packagePrefixes: PackagePrefixes
): Builder = {
idClassBuilder.addMethods(
generateToInterfaceMethods(
"ContractId",
"this.contractId",
implementedInterfaces,
packagePrefixes,
).asJava
)
implementedInterfaces.foreach { interfaceName =>
val name =
ClassName.bestGuess(fullyQualifiedName(interfaceName, packagePrefixes))
ClassName.bestGuess(fullyQualifiedName(interfaceName))
val interfaceContractIdName = name nestedClass "ContractId"
val tplContractIdClassName = templateClassName.nestedClass("ContractId")
idClassBuilder.addMethod(
@ -100,7 +95,8 @@ object ContractIdClass {
choices: Map[ChoiceName, TemplateChoice.FWT],
typeDeclarations: Map[QualifiedName, TypeDecl],
packageId: PackageId,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
) = {
val exercisesClass = TypeSpec
.interfaceBuilder(exercisesInterface)
@ -114,7 +110,6 @@ object ContractIdClass {
exercisesClass addMethod Builder.generateExerciseMethod(
choiceName,
choice,
packagePrefixes,
)
for (
record <- choice.param.fold(
@ -127,8 +122,7 @@ object ContractIdClass {
val splatted = Builder.generateFlattenedExerciseMethod(
choiceName,
choice,
getFieldsWithTypes(record.fields, packagePrefixes),
packagePrefixes,
getFieldsWithTypes(record.fields),
)
exercisesClass.addMethod(splatted)
}
@ -140,10 +134,11 @@ object ContractIdClass {
nestedReturn: String,
selfArgs: String,
implementedInterfaces: Seq[Ref.TypeConName],
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
) =
implementedInterfaces.map { interfaceName =>
val name = ClassName.bestGuess(fullyQualifiedName(interfaceName, packagePrefixes))
val name = ClassName.bestGuess(fullyQualifiedName(interfaceName))
val interfaceContractIdName = name nestedClass nestedReturn
MethodSpec
.methodBuilder("toInterface")
@ -160,28 +155,29 @@ object ContractIdClass {
choiceName: ChoiceName,
choice: TemplateChoice[Type],
fields: Fields,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): MethodSpec =
ClassGenUtils.generateFlattenedCreateOrExerciseMethod(
"exercise",
parameterizedUpdateType(toJavaTypeName(choice.returnType, packagePrefixes)),
parameterizedUpdateType(toJavaTypeName(choice.returnType)),
choiceName,
choice,
fields,
packagePrefixes,
)(_.addModifiers(Modifier.DEFAULT))
private[ContractIdClass] def generateExerciseMethod(
choiceName: ChoiceName,
choice: TemplateChoice[Type],
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): MethodSpec = {
val methodName = s"exercise${choiceName.capitalize}"
val exerciseChoiceBuilder = MethodSpec
.methodBuilder(methodName)
.addModifiers(Modifier.DEFAULT, Modifier.PUBLIC)
.returns(parameterizedUpdateType(toJavaTypeName(choice.returnType, packagePrefixes)))
val javaType = toJavaTypeName(choice.param, packagePrefixes)
.returns(parameterizedUpdateType(toJavaTypeName(choice.returnType)))
val javaType = toJavaTypeName(choice.param)
exerciseChoiceBuilder.addParameter(javaType, "arg")
exerciseChoiceBuilder.addStatement(
"return makeExerciseCmd($L, arg)",
@ -246,7 +242,6 @@ object ContractIdClass {
templateClassName: ClassName,
choices: Map[ChoiceName, TemplateChoice[typesig.Type]],
kind: For,
packagePrefixes: Map[PackageId, String],
): Builder = {
val idClassBuilder =
@ -271,7 +266,7 @@ object ContractIdClass {
idClassBuilder
.addMethod(constructor)
.addMethod(generateGetCompanion(templateClassName, kind))
Builder(templateClassName, contractIdClassName, idClassBuilder, choices, packagePrefixes)
Builder(templateClassName, contractIdClassName, idClassBuilder, choices)
}
}
}

View File

@ -11,7 +11,6 @@ import com.daml.ledger.javaapi.data.codegen.{
}
import com.daml.lf.codegen.backend.java.JavaEscaper
import com.daml.lf.data.ImmArray.ImmArraySeq
import com.daml.lf.data.Ref.PackageId
import com.daml.lf.typesig._
import com.squareup.javapoet._
import com.typesafe.scalalogging.StrictLogging
@ -80,9 +79,8 @@ private[inner] object FromValueGenerator extends StrictLogging {
typeParameters: IndexedSeq[String],
methodName: String,
recordValueExtractor: (String, String) => CodeBlock,
packagePrefixes: Map[PackageId, String],
isPublic: Boolean = true,
): MethodSpec = {
)(implicit packagePrefixes: PackagePrefixes): MethodSpec = {
logger.debug(s"Generating value decoder method $methodName")
val converterParams = FromValueExtractorParameters
@ -102,7 +100,7 @@ private[inner] object FromValueGenerator extends StrictLogging {
fields.iterator.zip(accessors).foreach { case (FieldInfo(_, damlType, javaName, _), accessor) =>
fromValueCode.addStatement(
generateFieldExtractor(damlType, javaName, accessor, packagePrefixes)
generateFieldExtractor(damlType, javaName, accessor)
)
}
@ -164,17 +162,14 @@ private[inner] object FromValueGenerator extends StrictLogging {
.build()
}
def generateFieldExtractor(
fieldType: Type,
field: String,
accessor: CodeBlock,
packagePrefixes: Map[PackageId, String],
def generateFieldExtractor(fieldType: Type, field: String, accessor: CodeBlock)(implicit
packagePrefixes: PackagePrefixes
): CodeBlock =
CodeBlock.of(
"$T $L =$W$L",
toJavaTypeName(fieldType, packagePrefixes),
toJavaTypeName(fieldType),
field,
extractor(fieldType, field, accessor, newNameGenerator, packagePrefixes),
extractor(fieldType, field, accessor, newNameGenerator),
)
private[this] val extractors =
@ -252,19 +247,17 @@ private[inner] object FromValueGenerator extends StrictLogging {
field: String,
accessor: CodeBlock,
args: Iterator[String],
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): CodeBlock =
extractorRec(damlType, field, args, packagePrefixes) extract accessor
extractorRec(damlType, field, args) extract accessor
private[this] def extractorRec(
damlType: Type,
field: String,
args: Iterator[String],
packagePrefixes: Map[PackageId, String],
private[this] def extractorRec(damlType: Type, field: String, args: Iterator[String])(implicit
packagePrefixes: PackagePrefixes
): Extractor = {
lazy val apiType = toAPITypeName(damlType)
lazy val javaType = toJavaTypeName(damlType, packagePrefixes)
lazy val javaType = toJavaTypeName(damlType)
logger.debug(s"Generating composite extractor for $field of type $javaType")
import Extractor._
@ -272,7 +265,7 @@ private[inner] object FromValueGenerator extends StrictLogging {
// shorten recursive calls
// we always want a ValueDecoder when recurring
def go(recDamlType: Type): CodeBlock =
extractorRec(recDamlType, field, args, packagePrefixes) asDecoder args
extractorRec(recDamlType, field, args) asDecoder args
def oneTypeArgPrim(primFun: String, param: Type): Extractor =
Decoder(
@ -342,17 +335,17 @@ private[inner] object FromValueGenerator extends StrictLogging {
case TypeCon(_, typeParameters) =>
val (targs, valueDecoders) = typeParameters.map {
case targ @ TypeVar(tvName) =>
toJavaTypeName(targ, packagePrefixes) -> CodeBlock.of(
toJavaTypeName(targ) -> CodeBlock.of(
"fromValue$L",
JavaEscaper.escapeString(tvName),
)
case targ @ TypeCon(_, ImmArraySeq()) =>
toJavaTypeName(targ, packagePrefixes) -> CodeBlock.of(
toJavaTypeName(targ) -> CodeBlock.of(
"$T.valueDecoder()",
toJavaTypeName(targ, packagePrefixes),
toJavaTypeName(targ),
)
case targ =>
toJavaTypeName(targ, packagePrefixes) -> go(targ)
toJavaTypeName(targ) -> go(targ)
}.unzip
val targsCode = CodeBlock.join(targs.map(CodeBlock.of("$L", _)).asJava, ",$W")

View File

@ -22,11 +22,10 @@ object InterfaceClass extends StrictLogging {
interfaceName: ClassName,
interfaceViewTypeName: ClassName,
interface: DefInterface.FWT,
packagePrefixes: Map[PackageId, String],
typeDeclarations: Map[QualifiedName, typesig.PackageSignature.TypeDecl],
packageId: PackageId,
interfaceId: QualifiedName,
): TypeSpec =
)(implicit packagePrefixes: PackagePrefixes): TypeSpec =
TrackLineage.of("interface", interfaceName.simpleName()) {
logger.info("Start")
val interfaceType = TypeSpec
@ -37,7 +36,6 @@ object InterfaceClass extends StrictLogging {
TemplateClass
.generateChoicesMetadata(
interfaceName,
packagePrefixes,
interface.choices,
)
.asJava
@ -50,7 +48,6 @@ object InterfaceClass extends StrictLogging {
interfaceName,
interface.choices,
ContractIdClass.For.Interface,
packagePrefixes,
)
.build()
)
@ -59,19 +56,17 @@ object InterfaceClass extends StrictLogging {
interface.choices,
typeDeclarations,
packageId,
packagePrefixes,
)
)
.addType(
TemplateClass.generateCreateAndClass(
interfaceName,
-\/(ContractIdClass.For.Interface),
packagePrefixes,
)
)
.addType(
TemplateClass
.generateByKeyClass(interfaceName, -\/(ContractIdClass.For.Interface), packagePrefixes)
.generateByKeyClass(interfaceName, -\/(ContractIdClass.For.Interface))
)
.addType(
generateInterfaceCompanionClass(

View File

@ -19,11 +19,12 @@ private[inner] object RecordClass extends StrictLogging {
className: ClassName,
typeParameters: IndexedSeq[String],
record: Record.FWT,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): TypeSpec = {
TrackLineage.of("record", className.simpleName()) {
logger.info("Start")
val fields = getFieldsWithTypes(record.fields, packagePrefixes)
val fields = getFieldsWithTypes(record.fields)
val recordType = TypeSpec
.classBuilder(className)
.addModifiers(Modifier.PUBLIC)
@ -38,7 +39,7 @@ private[inner] object RecordClass extends StrictLogging {
.addTypeVariables(typeParameters.map(TypeVariableName.get).asJava)
.addFields(RecordFields(fields).asJava)
.addField(createPackageIdField(packageId))
.addMethods(RecordMethods(fields, className, typeParameters, packagePrefixes).asJava)
.addMethods(RecordMethods(fields, className, typeParameters).asJava)
.build()
logger.debug("End")
recordType

View File

@ -5,16 +5,12 @@ package com.daml.lf.codegen.backend.java.inner
import com.daml.ledger.javaapi
import com.daml.lf.codegen.backend.java.ObjectMethods
import com.daml.lf.data.Ref.PackageId
import com.squareup.javapoet._
private[inner] object RecordMethods {
def apply(
fields: Fields,
className: ClassName,
typeParameters: IndexedSeq[String],
packagePrefixes: Map[PackageId, String],
def apply(fields: Fields, className: ClassName, typeParameters: IndexedSeq[String])(implicit
packagePrefixes: PackagePrefixes
): Vector[MethodSpec] = {
val constructor = ConstructorGenerator.generateConstructor(fields)
@ -38,12 +34,10 @@ private[inner] object RecordMethods {
inVar,
)
.build(),
packagePrefixes,
)
val toValue = ToValueGenerator.generateToValueForRecordLike(
params,
fields,
packagePrefixes,
ClassName.get(classOf[javaapi.data.DamlRecord]),
name => CodeBlock.of("return new $T($L)", classOf[javaapi.data.DamlRecord], name),
)

View File

@ -27,15 +27,16 @@ private[inner] object TemplateClass extends StrictLogging {
record: Record.FWT,
template: DefTemplate.FWT,
typeWithContext: TypeWithContext,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): TypeSpec =
TrackLineage.of("template", typeWithContext.name) {
logger.info("Start")
val fields = getFieldsWithTypes(record.fields, packagePrefixes)
val fields = getFieldsWithTypes(record.fields)
val staticCreateMethod = generateStaticCreateMethod(fields, className)
val templateChoices = template.tChoices.directChoices
val companion = new Companion(className, template.key, packagePrefixes)
val companion = new Companion(className, template.key)
val templateType = TypeSpec
.classBuilder(className)
.addModifiers(Modifier.FINAL, Modifier.PUBLIC)
@ -48,7 +49,6 @@ private[inner] object TemplateClass extends StrictLogging {
template.key,
typeWithContext.interface.typeDecls,
typeWithContext.packageId,
packagePrefixes,
)
)
.addMethods(
@ -56,7 +56,6 @@ private[inner] object TemplateClass extends StrictLogging {
templateChoices,
typeWithContext.interface.typeDecls,
typeWithContext.packageId,
packagePrefixes,
)
)
.addMethod(staticCreateMethod)
@ -66,15 +65,14 @@ private[inner] object TemplateClass extends StrictLogging {
className,
templateChoices,
ContractIdClass.For.Template,
packagePrefixes,
)
.addConversionForImplementedInterfaces(template.implementedInterfaces, packagePrefixes)
.addConversionForImplementedInterfaces(template.implementedInterfaces)
.addContractIdConversionCompanionForwarder()
.build()
)
.addType(
ContractClass
.builder(className, template.key, packagePrefixes)
.builder(className, template.key)
.addGenerateFromMethods()
.build()
)
@ -83,29 +81,27 @@ private[inner] object TemplateClass extends StrictLogging {
templateChoices,
typeWithContext.interface.typeDecls,
typeWithContext.packageId,
packagePrefixes,
)
)
.addMethod(generateCreateAndMethod())
.addType(
generateCreateAndClass(className, \/-(template.implementedInterfaces), packagePrefixes)
generateCreateAndClass(className, \/-(template.implementedInterfaces))
)
.addFields(
generateChoicesMetadata(
className: ClassName,
packagePrefixes,
templateChoices,
).asJava
)
.addField(companion.generateField(templateChoices.keySet))
.addMethod(companion.generateGetter())
.addFields(RecordFields(fields).asJava)
.addMethods(TemplateMethods(fields, className, packagePrefixes).asJava)
generateByKeyMethod(template.key, packagePrefixes) foreach { byKeyMethod =>
.addMethods(TemplateMethods(fields, className).asJava)
generateByKeyMethod(template.key) foreach { byKeyMethod =>
templateType
.addMethod(byKeyMethod)
.addType(
generateByKeyClass(className, \/-(template.implementedInterfaces), packagePrefixes)
generateByKeyClass(className, \/-(template.implementedInterfaces))
)
}
logger.debug("End")
@ -168,19 +164,18 @@ private[inner] object TemplateClass extends StrictLogging {
private val byKeyClassName = "ByKey"
private[this] def generateByKeyMethod(
maybeKey: Option[Type],
packagePrefixes: Map[PackageId, String],
private[this] def generateByKeyMethod(maybeKey: Option[Type])(implicit
packagePrefixes: PackagePrefixes
) =
maybeKey map { key =>
MethodSpec
.methodBuilder("byKey")
.returns(ClassName bestGuess byKeyClassName)
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addParameter(toJavaTypeName(key, packagePrefixes), "key")
.addParameter(toJavaTypeName(key), "key")
.addStatement(
"return new ByKey($L)",
generateToValueConverter(key, CodeBlock.of("key"), newNameGenerator, packagePrefixes),
generateToValueConverter(key, CodeBlock.of("key"), newNameGenerator),
)
.addJavadoc(
"""Set up an {@link $T};$Winvoke an {@code exercise} method on the result of
@ -196,7 +191,8 @@ private[inner] object TemplateClass extends StrictLogging {
private[inner] def generateByKeyClass(
markerName: ClassName,
implementedInterfaces: ContractIdClass.For.Interface.type \/ Seq[Ref.TypeConName],
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
) = {
import scala.language.existentials
val (superclass, companionArg) = implementedInterfaces.fold(
@ -234,7 +230,6 @@ private[inner] object TemplateClass extends StrictLogging {
byKeyClassName,
s"$companionFieldName, this.contractKey",
implemented,
packagePrefixes,
),
)
.asJava
@ -248,7 +243,8 @@ private[inner] object TemplateClass extends StrictLogging {
maybeKey: Option[Type],
typeDeclarations: Map[QualifiedName, PackageSignature.TypeDecl],
packageId: PackageId,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
) =
maybeKey.fold(java.util.Collections.emptyList[MethodSpec]()) { key =>
val methods = for ((choiceName, choice) <- choices.toList) yield {
@ -256,7 +252,6 @@ private[inner] object TemplateClass extends StrictLogging {
choiceName,
choice,
key,
packagePrefixes,
)
val flattened =
for (
@ -273,8 +268,7 @@ private[inner] object TemplateClass extends StrictLogging {
choiceName,
choice,
key,
getFieldsWithTypes(record.fields, packagePrefixes),
packagePrefixes,
getFieldsWithTypes(record.fields),
)
}
raw :: flattened.toList
@ -287,7 +281,8 @@ private[inner] object TemplateClass extends StrictLogging {
choiceName: ChoiceName,
choice: TemplateChoice[Type],
key: Type,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): MethodSpec =
MethodSpec
.methodBuilder(s"exerciseByKey${choiceName.capitalize}")
@ -297,7 +292,7 @@ private[inner] object TemplateClass extends StrictLogging {
updateClassName,
parameterizedTypeName(
exercisedClassName,
toJavaTypeName(choice.returnType, packagePrefixes),
toJavaTypeName(choice.returnType),
),
)
)
@ -305,8 +300,8 @@ private[inner] object TemplateClass extends StrictLogging {
howToFix = s"use {@code byKey(key).exercise${choiceName.capitalize}} instead",
sinceDaml = "2.3.0",
)
.addParameter(toJavaTypeName(key, packagePrefixes), "key")
.addParameter(toJavaTypeName(choice.param, packagePrefixes), "arg")
.addParameter(toJavaTypeName(key), "key")
.addParameter(toJavaTypeName(choice.param), "arg")
.addStatement(
"return byKey(key).exercise$L(arg)",
choiceName.capitalize,
@ -319,7 +314,8 @@ private[inner] object TemplateClass extends StrictLogging {
choice: TemplateChoice[Type],
key: Type,
fields: Fields,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): MethodSpec = {
val methodName = s"exerciseByKey${choiceName.capitalize}"
val exerciseByKeyBuilder = MethodSpec
@ -330,11 +326,11 @@ private[inner] object TemplateClass extends StrictLogging {
updateClassName,
parameterizedTypeName(
exercisedClassName,
toJavaTypeName(choice.returnType, packagePrefixes),
toJavaTypeName(choice.returnType),
),
)
)
.addParameter(toJavaTypeName(key, packagePrefixes), "key")
.addParameter(toJavaTypeName(key), "key")
for (FieldInfo(_, _, javaName, javaType) <- fields) {
exerciseByKeyBuilder.addParameter(javaType, javaName)
}
@ -363,7 +359,8 @@ private[inner] object TemplateClass extends StrictLogging {
private[inner] def generateCreateAndClass(
markerName: ClassName,
implementedInterfaces: ContractIdClass.For.Interface.type \/ Seq[Ref.TypeConName],
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
) = {
import scala.language.existentials
val (superclass, companionArg) = implementedInterfaces.fold(
@ -401,7 +398,6 @@ private[inner] object TemplateClass extends StrictLogging {
createAndClassName,
s"$companionFieldName, this.createArguments",
implemented,
packagePrefixes,
),
)
.asJava
@ -414,14 +410,14 @@ private[inner] object TemplateClass extends StrictLogging {
choices: Map[ChoiceName, TemplateChoice[typesig.Type]],
typeDeclarations: Map[QualifiedName, PackageSignature.TypeDecl],
packageId: PackageId,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
) = {
val methods = for ((choiceName, choice) <- choices) yield {
val createAndExerciseChoiceMethod =
generateDeprecatedCreateAndExerciseMethod(
choiceName,
choice,
packagePrefixes,
)
val splatted =
for (
@ -436,8 +432,7 @@ private[inner] object TemplateClass extends StrictLogging {
generateDeprecatedFlattenedCreateAndExerciseMethod(
choiceName,
choice,
getFieldsWithTypes(record.fields, packagePrefixes),
packagePrefixes,
getFieldsWithTypes(record.fields),
)
}
createAndExerciseChoiceMethod :: splatted.toList
@ -449,10 +444,11 @@ private[inner] object TemplateClass extends StrictLogging {
private def generateDeprecatedCreateAndExerciseMethod(
choiceName: ChoiceName,
choice: TemplateChoice[Type],
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): MethodSpec = {
val methodName = s"createAndExercise${choiceName.capitalize}"
val javaType = toJavaTypeName(choice.param, packagePrefixes)
val javaType = toJavaTypeName(choice.param)
MethodSpec
.methodBuilder(methodName)
.addModifiers(Modifier.PUBLIC)
@ -465,7 +461,7 @@ private[inner] object TemplateClass extends StrictLogging {
updateClassName,
parameterizedTypeName(
exercisedClassName,
toJavaTypeName(choice.returnType, packagePrefixes),
toJavaTypeName(choice.returnType),
),
)
)
@ -482,7 +478,8 @@ private[inner] object TemplateClass extends StrictLogging {
choiceName: ChoiceName,
choice: TemplateChoice[Type],
fields: Fields,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): MethodSpec =
ClassGenUtils.generateFlattenedCreateOrExerciseMethod(
"createAndExercise",
@ -490,13 +487,12 @@ private[inner] object TemplateClass extends StrictLogging {
updateClassName,
parameterizedTypeName(
exercisedClassName,
toJavaTypeName(choice.returnType, packagePrefixes),
toJavaTypeName(choice.returnType),
),
),
choiceName,
choice,
fields,
packagePrefixes,
)(
_.makeDeprecated(
howToFix = s"use {@code createAnd().exercise${choiceName.capitalize}} instead",
@ -513,9 +509,8 @@ private[inner] object TemplateClass extends StrictLogging {
def generateChoicesMetadata(
templateClassName: ClassName,
packagePrefixes: Map[PackageId, String],
templateChoices: Map[ChoiceName, TemplateChoice.FWT],
): Seq[FieldSpec] = {
)(implicit packagePrefixes: PackagePrefixes): Seq[FieldSpec] = {
templateChoices.map { case (choiceName, choice) =>
val fieldClass = classOf[Choice[_, _, _]]
FieldSpec
@ -523,8 +518,8 @@ private[inner] object TemplateClass extends StrictLogging {
ParameterizedTypeName.get(
ClassName get fieldClass,
templateClassName,
toJavaTypeName(choice.param, packagePrefixes),
toJavaTypeName(choice.returnType, packagePrefixes),
toJavaTypeName(choice.param),
toJavaTypeName(choice.returnType),
),
toChoiceNameField(choiceName),
Modifier.STATIC,
@ -539,31 +534,26 @@ private[inner] object TemplateClass extends StrictLogging {
choice.param,
CodeBlock.of("value$$"),
Iterator.empty,
packagePrefixes,
),
FromValueGenerator.extractor(
choice.param,
"value$",
CodeBlock.of("$L", "value$"),
newNameGenerator,
packagePrefixes,
),
FromValueGenerator.extractor(
choice.returnType,
"value$",
CodeBlock.of("$L", "value$"),
newNameGenerator,
packagePrefixes,
),
)
.build()
}.toSeq
}
private final class Companion(
templateClassName: ClassName,
maybeKey: Option[Type],
packagePrefixes: Map[PackageId, String],
private final class Companion(templateClassName: ClassName, maybeKey: Option[Type])(implicit
packagePrefixes: PackagePrefixes
) {
import scala.language.existentials
import javaapi.data.codegen.ContractCompanion
@ -572,11 +562,11 @@ private[inner] object TemplateClass extends StrictLogging {
keyType =>
(
classOf[ContractCompanion.WithKey[_, _, _, _]],
Seq(toJavaTypeName(keyType, packagePrefixes)),
Seq(toJavaTypeName(keyType)),
",$We -> $L",
Seq(
FromValueGenerator
.extractor(keyType, "e", CodeBlock.of("e"), newNameGenerator, packagePrefixes)
.extractor(keyType, "e", CodeBlock.of("e"), newNameGenerator)
),
),
(classOf[ContractCompanion.WithoutKey[_, _, _]], Seq.empty, "", Seq.empty),

View File

@ -6,17 +6,14 @@ package com.daml.lf.codegen.backend.java.inner
import com.daml.ledger.javaapi
import com.daml.ledger.javaapi.data.ContractFilter
import com.daml.lf.codegen.backend.java.ObjectMethods
import com.daml.lf.data.Ref.PackageId
import com.squareup.javapoet._
import javax.lang.model.element.Modifier
private[inner] object TemplateMethods {
def apply(
fields: Fields,
className: ClassName,
packagePrefixes: Map[PackageId, String],
def apply(fields: Fields, className: ClassName)(implicit
packagePrefixes: PackagePrefixes
): Vector[MethodSpec] = {
val constructor = ConstructorGenerator.generateConstructor(fields)
val conversionMethods = distinctTypeVars(fields, IndexedSeq.empty[String]).flatMap { params =>
@ -31,7 +28,6 @@ private[inner] object TemplateMethods {
val toValue = ToValueGenerator.generateToValueForRecordLike(
params,
fields,
packagePrefixes,
ClassName.get(classOf[javaapi.data.DamlRecord]),
name => CodeBlock.of("return new $T($L)", classOf[javaapi.data.DamlRecord], name),
)
@ -49,7 +45,6 @@ private[inner] object TemplateMethods {
inVar,
)
.build(),
packagePrefixes,
isPublic = false,
)
List(deprecatedFromValue, valueDecoder, toValue, privateGetValueDecoder)

View File

@ -6,7 +6,6 @@ package com.daml.lf.codegen.backend.java.inner
import com.daml.ledger.javaapi
import com.daml.lf.codegen.backend.java.{JavaEscaper, Types}
import com.daml.lf.data.ImmArray.ImmArraySeq
import com.daml.lf.data.Ref.PackageId
import com.daml.lf.typesig._
import com.squareup.javapoet._
import javax.lang.model.element.Modifier
@ -32,10 +31,9 @@ object ToValueGenerator {
def generateToValueForRecordLike(
typeParams: IndexedSeq[String],
fields: Fields,
packagePrefixes: Map[PackageId, String],
returnType: TypeName,
returnStatement: String => CodeBlock,
): MethodSpec = {
)(implicit packagePrefixes: PackagePrefixes): MethodSpec = {
val arrayOfFields =
ParameterizedTypeName.get(
classOf[java.util.ArrayList[_]],
@ -65,7 +63,6 @@ object ToValueGenerator {
damlType,
CodeBlock.of("this.$L", javaName),
newNameGenerator,
packagePrefixes,
),
)
}
@ -73,11 +70,8 @@ object ToValueGenerator {
toValueMethod.build()
}
def generateToValueConverter(
damlType: Type,
accessor: CodeBlock,
args: Iterator[String],
packagePrefixes: Map[PackageId, String],
def generateToValueConverter(damlType: Type, accessor: CodeBlock, args: Iterator[String])(implicit
packagePrefixes: PackagePrefixes
): CodeBlock = {
damlType match {
case TypeVar(tvName) =>
@ -96,7 +90,7 @@ object ToValueGenerator {
val extractor = CodeBlock.of(
"$L -> $L",
arg,
generateToValueConverter(param, CodeBlock.of("$L", arg), args, packagePrefixes),
generateToValueConverter(param, CodeBlock.of("$L", arg), args),
)
CodeBlock.of(
"$L.stream().collect($T.toDamlList($L))",
@ -108,7 +102,7 @@ object ToValueGenerator {
case TypePrim(PrimTypeOptional, ImmArraySeq(param)) =>
val arg = args.next()
val wrapped =
generateToValueConverter(param, CodeBlock.of("$L", arg), args, packagePrefixes)
generateToValueConverter(param, CodeBlock.of("$L", arg), args)
val extractor = CodeBlock.of("$L -> $L", arg, wrapped)
CodeBlock.of(
"$T.of($L.map($L))",
@ -122,7 +116,7 @@ object ToValueGenerator {
val extractor = CodeBlock.of(
"$L -> $L",
arg,
generateToValueConverter(param, CodeBlock.of("$L.getValue()", arg), args, packagePrefixes),
generateToValueConverter(param, CodeBlock.of("$L.getValue()", arg), args),
)
CodeBlock.of(
"$L.entrySet()$Z.stream()$Z.collect($T.toDamlTextMap($T::getKey, $L))$W",
@ -137,7 +131,7 @@ object ToValueGenerator {
val keyExtractor = CodeBlock.of(
"$L -> $L",
arg,
generateToValueConverter(keyType, CodeBlock.of("$L.getKey()", arg), args, packagePrefixes),
generateToValueConverter(keyType, CodeBlock.of("$L.getKey()", arg), args),
)
val valueExtractor = CodeBlock.of(
"$L -> $L",
@ -146,7 +140,6 @@ object ToValueGenerator {
valueType,
CodeBlock.of("$L.getValue()", arg),
args,
packagePrefixes,
),
)
CodeBlock.of(
@ -163,7 +156,7 @@ object ToValueGenerator {
case TypeCon(_, typeParameters) =>
val extractorParams = typeParameters.map { ta =>
val arg = args.next()
val wrapped = generateToValueConverter(ta, CodeBlock.of("$L", arg), args, packagePrefixes)
val wrapped = generateToValueConverter(ta, CodeBlock.of("$L", arg), args)
val extractor = CodeBlock.of("$L -> $L", arg, wrapped)
extractor
}

View File

@ -6,7 +6,6 @@ package com.daml.lf.codegen.backend.java.inner
import com.daml.ledger.javaapi
import com.daml.lf.codegen.TypeWithContext
import com.daml.lf.codegen.backend.java.JavaEscaper
import com.daml.lf.data.Ref.PackageId
import com.daml.lf.typesig._
import PackageSignature.TypeDecl.Normal
import com.daml.ledger.javaapi.data.codegen.ValueDecoder
@ -25,11 +24,10 @@ private[inner] object VariantClass extends StrictLogging {
typeArguments: IndexedSeq[String],
variant: Variant.FWT,
typeWithContext: TypeWithContext,
packagePrefixes: Map[PackageId, String],
): (TypeSpec, List[TypeSpec]) =
)(implicit packagePrefixes: PackagePrefixes): (TypeSpec, List[TypeSpec]) =
TrackLineage.of("variant", typeWithContext.name) {
logger.info("Start")
val constructorInfo = getFieldsWithTypes(variant.fields, packagePrefixes)
val constructorInfo = getFieldsWithTypes(variant.fields)
val variantType = TypeSpec
.classBuilder(variantClassName)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
@ -53,7 +51,6 @@ private[inner] object VariantClass extends StrictLogging {
typeArguments,
variant,
typeWithContext,
packagePrefixes,
subPackage,
).asJava
)
@ -63,7 +60,6 @@ private[inner] object VariantClass extends StrictLogging {
typeArguments,
variant,
typeWithContext,
packagePrefixes,
variantClassName,
)
logger.debug("End")
@ -283,15 +279,14 @@ private[inner] object VariantClass extends StrictLogging {
typeArgs: IndexedSeq[String],
variant: Variant.FWT,
typeWithContext: TypeWithContext,
packagePrefixes: Map[PackageId, String],
variantClassName: ClassName,
): List[TypeSpec] = {
)(implicit packagePrefixes: PackagePrefixes): List[TypeSpec] = {
logger.debug("Generating inner classes")
val innerClasses = new collection.mutable.ArrayBuffer[TypeSpec]
val variantRecords = new collection.mutable.HashSet[String]()
val fullVariantClassName = variantClassName.parameterized(typeArgs)
for (fieldInfo <- getFieldsWithTypes(variant.fields, packagePrefixes)) {
for (fieldInfo <- getFieldsWithTypes(variant.fields)) {
val FieldInfo(damlName, damlType, javaName, _) = fieldInfo
damlType match {
case TypeCon(TypeConName(id), _) if isVariantRecord(typeWithContext, damlName, id) =>
@ -306,7 +301,6 @@ private[inner] object VariantClass extends StrictLogging {
damlName,
javaName,
damlType,
packagePrefixes,
)
}
}
@ -323,10 +317,9 @@ private[inner] object VariantClass extends StrictLogging {
.generate(
typeWithContext.interface.packageId,
typeVars.map(JavaEscaper.escapeString),
getFieldsWithTypes(record.fields, packagePrefixes),
getFieldsWithTypes(record.fields),
child.name,
fullVariantClassName,
packagePrefixes,
)
case t =>
val c = s"${typeWithContext.name}.${child.name}"

View File

@ -24,13 +24,14 @@ object VariantConstructorClass extends StrictLogging {
constructorName: String,
javaName: String,
body: Type,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): TypeSpec = {
TrackLineage.of("variant constructor", constructorName) {
logger.info("Start")
val className = ClassName.bestGuess(javaName).parameterized(typeArgs)
val javaType = toJavaTypeName(body, packagePrefixes)
val javaType = toJavaTypeName(body)
val variantFieldName = lowerCaseFieldName(body match {
case TypeVar(typeArg) =>
JavaEscaper.escapeString(typeArg)
@ -45,15 +46,15 @@ object VariantConstructorClass extends StrictLogging {
val conversionMethods = distinctTypeVars(body, typeArgs) match {
case IndexedSeq(params) =>
List(
toValue(constructorName, params, body, variantFieldName, packagePrefixes),
toValue(constructorName, params, body, variantFieldName),
deprecatedFromValue(params, params, variant, className),
)
case IndexedSeq(usedParams, allParams) =>
// usedParams is always subset of allParams
List(
toValue(constructorName, usedParams, body, variantFieldName, packagePrefixes),
toValue(constructorName, usedParams, body, variantFieldName),
deprecatedFromValue(usedParams, allParams, variant, className),
toValue(constructorName, allParams, body, variantFieldName, packagePrefixes),
toValue(constructorName, allParams, body, variantFieldName),
deprecatedFromValue(allParams, allParams, variant, className),
)
}
@ -81,7 +82,8 @@ object VariantConstructorClass extends StrictLogging {
typeArgs: IndexedSeq[String],
body: Type,
fieldName: String,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
) = {
val extractorParameters = ToValueExtractorParameters.generate(typeArgs)
@ -99,7 +101,6 @@ object VariantConstructorClass extends StrictLogging {
body,
CodeBlock.of("this.$L", fieldName),
newNameGenerator,
packagePrefixes,
),
)
.build()

View File

@ -18,7 +18,8 @@ private[inner] object VariantRecordClass extends StrictLogging {
fields: Fields,
name: String,
superclass: TypeName,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): TypeSpec =
TrackLineage.of("variant-record", name) {
logger.info("Start")
@ -36,7 +37,6 @@ private[inner] object VariantRecordClass extends StrictLogging {
superclass,
className.parameterized(typeParameters),
typeParameters,
packagePrefixes,
).asJava
)
.build()

View File

@ -6,7 +6,6 @@ package com.daml.lf.codegen.backend.java.inner
import com.daml.ledger.javaapi
import com.daml.ledger.javaapi.data.codegen.{PrimitiveValueDecoders, ValueDecoder}
import com.daml.lf.codegen.backend.java.ObjectMethods
import com.daml.lf.data.Ref.PackageId
import com.squareup.javapoet._
import com.typesafe.scalalogging.StrictLogging
@ -21,22 +20,23 @@ private[inner] object VariantRecordMethods extends StrictLogging {
variantClassName: TypeName,
className: TypeName,
typeParameters: IndexedSeq[String],
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
): Vector[MethodSpec] = {
val constructor = ConstructorGenerator.generateConstructor(fields)
val conversionMethods = distinctTypeVars(fields, typeParameters) match {
case IndexedSeq(params) =>
List(
toValue(constructorName, params, fields, packagePrefixes),
toValue(constructorName, params, fields),
generateDeprecatedFromValue(params, params, variantClassName, className),
)
case IndexedSeq(usedParams, allParams) =>
// usedParams is always subset of allParams
List(
toValue(constructorName, usedParams, fields, packagePrefixes),
toValue(constructorName, usedParams, fields),
generateDeprecatedFromValue(usedParams, allParams, variantClassName, className),
toValue(constructorName, allParams, fields, packagePrefixes),
toValue(constructorName, allParams, fields),
generateDeprecatedFromValue(allParams, allParams, variantClassName, className),
)
}
@ -45,15 +45,11 @@ private[inner] object VariantRecordMethods extends StrictLogging {
ObjectMethods(className.rawType, typeParameters, fields.map(_.javaName))
}
private def toValue(
constructorName: String,
params: IndexedSeq[String],
fields: Fields,
packagePrefixes: Map[PackageId, String],
private def toValue(constructorName: String, params: IndexedSeq[String], fields: Fields)(implicit
packagePrefixes: PackagePrefixes
) = ToValueGenerator.generateToValueForRecordLike(
params,
fields,
packagePrefixes,
TypeName.get(classOf[javaapi.data.Variant]),
name =>
CodeBlock.of(

View File

@ -4,7 +4,6 @@
package com.daml.lf.codegen.backend.java.inner
import com.daml.lf.typesig.{Type, Variant}
import com.daml.lf.data.Ref.PackageId
import com.daml.lf.codegen.backend.java.JavaEscaper
import com.daml.lf.codegen.TypeWithContext
import com.daml.lf.typesig._
@ -20,11 +19,10 @@ object VariantValueDecodersMethods {
typeArgs: IndexedSeq[String],
variant: Variant.FWT,
typeWithContext: TypeWithContext,
packagePrefixes: Map[PackageId, String],
subPackage: String,
): Vector[MethodSpec] = {
)(implicit packagePrefixes: PackagePrefixes): Vector[MethodSpec] = {
val (variantRecords, methodSpecs) =
getFieldsWithTypes(variant.fields, packagePrefixes).partitionMap { fieldInfo =>
getFieldsWithTypes(variant.fields).partitionMap { fieldInfo =>
val FieldInfo(damlName, damlType, javaName, _) = fieldInfo
damlType match {
case TypeCon(TypeConName(id), _) if isVariantRecord(typeWithContext, damlName, id) =>
@ -34,7 +32,7 @@ object VariantValueDecodersMethods {
val className =
ClassName.bestGuess(s"$subPackage.$javaName").parameterized(typeArgs)
Right(
variantConDecoderMethod(damlName, typeArgs, className, damlType, packagePrefixes)
variantConDecoderMethod(damlName, typeArgs, className, damlType)
)
}
}
@ -53,12 +51,11 @@ object VariantValueDecodersMethods {
ClassName.bestGuess(s"$subPackage.${child.name}").parameterized(typeParameters)
FromValueGenerator.generateValueDecoderForRecordLike(
getFieldsWithTypes(record.fields, packagePrefixes),
getFieldsWithTypes(record.fields),
className,
typeArgs,
s"valueDecoder${child.name}",
FromValueGenerator.variantCheck(child.name, _, _),
packagePrefixes,
)
case t =>
val c = s"${typeWithContext.name}.${child.name}"
@ -75,7 +72,8 @@ object VariantValueDecodersMethods {
typeParameters: IndexedSeq[String],
className: TypeName,
fieldType: Type,
packagePrefixes: Map[PackageId, String],
)(implicit
packagePrefixes: PackagePrefixes
) = {
val converterParams =
FromValueExtractorParameters.generate(typeParameters).valueDecoderParameterSpecs
@ -89,7 +87,6 @@ object VariantValueDecodersMethods {
fieldType,
"body",
CodeBlock.of("variantValue$$"),
packagePrefixes,
)
)
.addStatement("return new $T(body)", className)

View File

@ -12,12 +12,15 @@ import com.daml.lf.data.ImmArray.ImmArraySeq
import com.daml.lf.data.Ref.{Identifier, PackageId, QualifiedName}
import com.daml.lf.typesig._
import com.squareup.javapoet._
import scalaz.@@
import javax.lang.model.element.Modifier
import scala.jdk.CollectionConverters._
package inner {
case class FieldInfo(damlName: String, damlType: Type, javaName: String, javaType: TypeName)
sealed trait PackagePrefixesTag
}
package object inner {
@ -29,34 +32,31 @@ package object inner {
type Fields = IndexedSeq[FieldInfo]
private[inner] def getFieldsWithTypes(
fields: IndexedSeq[FieldWithType],
packagePrefixes: Map[PackageId, String],
private[inner] def getFieldsWithTypes(fields: IndexedSeq[FieldWithType])(implicit
packagePrefixes: PackagePrefixes
): Fields =
fields.map(getFieldWithType(_, packagePrefixes))
fields.map(getFieldWithType(_))
private[inner] def getFieldWithType(
fwt: FieldWithType,
packagePrefixes: Map[PackageId, String],
private[inner] def getFieldWithType(fwt: FieldWithType)(implicit
packagePrefixes: PackagePrefixes
): FieldInfo =
FieldInfo(
fwt._1,
fwt._2,
JavaEscaper.escapeString(fwt._1),
toJavaTypeName(fwt._2, packagePrefixes),
toJavaTypeName(fwt._2),
)
private[inner] def toJavaTypeName(
damlType: Type,
packagePrefixes: Map[PackageId, String],
): TypeName =
damlType: Type
)(implicit packagePrefixes: PackagePrefixes): TypeName =
damlType match {
case TypeCon(TypeConName(ident), Seq()) =>
ClassName.bestGuess(fullyQualifiedName(ident, packagePrefixes)).box()
ClassName.bestGuess(fullyQualifiedName(ident)).box()
case TypeCon(TypeConName(ident), typeParameters) =>
ParameterizedTypeName.get(
ClassName.bestGuess(fullyQualifiedName(ident, packagePrefixes)),
typeParameters.map(toJavaTypeName(_, packagePrefixes)): _*
ClassName.bestGuess(fullyQualifiedName(ident)),
typeParameters.map(toJavaTypeName(_)): _*
)
case TypePrim(PrimTypeBool, _) => ClassName.get(classOf[java.lang.Boolean])
case TypePrim(PrimTypeInt64, _) => ClassName.get(classOf[java.lang.Long])
@ -66,7 +66,7 @@ package object inner {
case TypePrim(PrimTypeTimestamp, _) => ClassName.get(classOf[java.time.Instant])
case TypePrim(PrimTypeParty, _) => ClassName.get(classOf[java.lang.String])
case TypePrim(PrimTypeContractId, ImmArraySeq(templateType)) =>
toJavaTypeName(templateType, packagePrefixes) match {
toJavaTypeName(templateType) match {
case templateClass: ClassName => templateClass.nestedClass("ContractId")
case typeVariableName: TypeVariableName =>
ParameterizedTypeName.get(ClassName.get(classOf[ContractId[_]]), typeVariableName)
@ -76,26 +76,26 @@ package object inner {
ParameterizedTypeName
.get(
ClassName.get(classOf[java.util.List[_]]),
typeParameters.map(toJavaTypeName(_, packagePrefixes)): _*
typeParameters.map(toJavaTypeName(_)): _*
)
case TypePrim(PrimTypeOptional, typeParameters) =>
ParameterizedTypeName
.get(
ClassName.get(classOf[java.util.Optional[_]]),
typeParameters.map(toJavaTypeName(_, packagePrefixes)): _*
typeParameters.map(toJavaTypeName(_)): _*
)
case TypePrim(PrimTypeTextMap, typeParameters) =>
ParameterizedTypeName
.get(
ClassName.get(classOf[java.util.Map[String, _]]),
ClassName.get(classOf[java.lang.String]) +:
typeParameters.map(toJavaTypeName(_, packagePrefixes)): _*
typeParameters.map(toJavaTypeName(_)): _*
)
case TypePrim(PrimTypeGenMap, typeParameters) =>
ParameterizedTypeName
.get(
ClassName.get(classOf[java.util.Map[_, _]]),
typeParameters.map(toJavaTypeName(_, packagePrefixes)): _*
typeParameters.map(toJavaTypeName(_)): _*
)
case TypePrim(PrimTypeUnit, _) => ClassName.get(classOf[javaapi.data.Unit])
case TypeVar(name) => TypeVariableName.get(JavaEscaper.escapeString(name))
@ -127,20 +127,13 @@ package object inner {
sys.error("Assumption error: toAPITypeName should not be called for type constructors!")
}
type PackagePrefixes = Map[PackageId, String] @@ PackagePrefixesTag
private[codegen] val PackagePrefixes = scalaz.Tag.of[PackagePrefixesTag]
def fullyQualifiedName(
identifier: Identifier,
packagePrefixes: Map[PackageId, String],
): String =
fullyQualifiedName(identifier.qualifiedName, Some(identifier.packageId, packagePrefixes))
def fullyQualifiedName(qualifiedName: QualifiedName): String =
fullyQualifiedName(qualifiedName, None)
private def fullyQualifiedName(
qualifiedName: QualifiedName,
packageIdAndPackagePrefixesOpt: Option[(PackageId, Map[PackageId, String])],
): String = {
val QualifiedName(module, name) = qualifiedName
identifier: Identifier
)(implicit packagePrefixes: PackagePrefixes): String = {
val Identifier(packageId, QualifiedName(module, name)) = identifier
// consider all but the last name segment to be part of the java package name
val packageSegments = module.segments.slowAppend(name.segments).toSeq.dropRight(1)
@ -148,11 +141,7 @@ package object inner {
val className = name.segments.toSeq.takeRight(1)
val packageName = packageSegments.map(_.toLowerCase)
val packagePrefix = packageIdAndPackagePrefixesOpt
.flatMap { case (packageId, packagePrefixes) =>
packagePrefixes.get(packageId)
}
.getOrElse("")
val packagePrefix = PackagePrefixes.unwrap(packagePrefixes).getOrElse(packageId, "")
(Vector(packagePrefix) ++ packageName ++ className)
.filter(_.nonEmpty)

View File

@ -61,8 +61,9 @@ final class CodeGenRunnerTests extends AnyFlatSpec with Matchers {
val scope = CodeGenRunner.configureCodeGenScope(Map(testDar -> Some("PREFIX")), Map.empty)
assert(scope.signatures.map(_.packageId).length === dar.all.length)
assert(scope.packagePrefixes.size === dar.all.length)
assert(scope.packagePrefixes.values.forall(_ === "PREFIX"))
val prefixes = backend.java.inner.PackagePrefixes unwrap scope.packagePrefixes
assert(prefixes.size === dar.all.length)
assert(prefixes.values.forall(_ === "PREFIX"))
assert(scope.toBeGenerated === Set.empty)
}

View File

@ -18,16 +18,17 @@ final class RecordFieldsSpec extends AnyFlatSpec with Matchers {
behavior of "RecordFields"
private[this] implicit val packagePrefixes: PackagePrefixes = PackagePrefixes(Map.empty)
it should "not generate any parameter from an empty record" in {
RecordFields(getFieldsWithTypes(ImmArraySeq(), Map())) shouldBe empty
RecordFields(getFieldsWithTypes(ImmArraySeq())) shouldBe empty
}
it should "throw exception when the parameter name is empty" in {
an[IllegalArgumentException] shouldBe thrownBy(
RecordFields(
getFieldsWithTypes(
ImmArraySeq(Ref.Name.assertFromString("") -> TypePrim(PrimTypeBool, ImmArraySeq.empty)),
Map(),
ImmArraySeq(Ref.Name.assertFromString("") -> TypePrim(PrimTypeBool, ImmArraySeq.empty))
)
)
)
@ -39,8 +40,7 @@ final class RecordFieldsSpec extends AnyFlatSpec with Matchers {
getFieldsWithTypes(
ImmArraySeq(
Ref.Name.assertFromString("bool") -> TypePrim(PrimTypeBool, ImmArraySeq.empty)
),
Map(),
)
)
)
@ -67,8 +67,7 @@ final class RecordFieldsSpec extends AnyFlatSpec with Matchers {
getFieldsWithTypes(
ImmArraySeq(
Ref.Name.assertFromString("field") -> TypeCon(TypeConName(ident), ImmArraySeq.empty)
),
Map(),
)
)
)

View File

@ -137,15 +137,16 @@ final class RecordLikeMethodsSpec
}
private val name = ClassName.bestGuess("Test")
private val methods = RecordMethods(
getFieldsWithTypes(
ImmArraySeq(Ref.Name.assertFromString("bool") -> TypePrim(PrimTypeBool, ImmArraySeq.empty)),
Map(),
),
name,
IndexedSeq.empty,
Map(),
)
private val methods = {
implicit val packagePrefixes: PackagePrefixes = PackagePrefixes(Map.empty)
RecordMethods(
getFieldsWithTypes(
ImmArraySeq(Ref.Name.assertFromString("bool") -> TypePrim(PrimTypeBool, ImmArraySeq.empty))
),
name,
IndexedSeq.empty,
)
}
private val Vector(constructor, deprecatedFromValue, valueDecoder, toValue) = methods.take(4)
}