From 658365e5eb41f1487566dccd5d2ffe5cd6715684 Mon Sep 17 00:00:00 2001 From: Gerolf Seitz Date: Fri, 6 Dec 2019 16:10:38 +0100 Subject: [PATCH] Java codegen fixes (#3762) * Fix compiler warnings in generated enums * Fix warnings in generated equals method for parameterized types. * Remove warning in equals for records without fields. CHANGELOG_BEGIN - [Java Bindings] Removed warnings in code emitted by the Java Codegen. CHANGELOG_END * fix compilation error in tests --- .../lf/codegen/backend/java/ObjectMethods.scala | 14 ++++++++------ .../lf/codegen/backend/java/inner/EnumClass.scala | 15 +++++++++------ .../backend/java/inner/RecordMethods.scala | 2 +- .../backend/java/inner/TemplateClass.scala | 2 +- .../java/inner/VariantConstructorClass.scala | 2 +- .../backend/java/inner/VariantRecordMethods.scala | 2 +- .../lf/codegen/backend/java/inner/package.scala | 7 ++++++- .../codegen/backend/java/ObjectMethodsSpec.scala | 2 +- 8 files changed, 28 insertions(+), 18 deletions(-) diff --git a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/ObjectMethods.scala b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/ObjectMethods.scala index 4db879fd235..6aad8ef7aee 100644 --- a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/ObjectMethods.scala +++ b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/ObjectMethods.scala @@ -6,25 +6,27 @@ package com.digitalasset.daml.lf.codegen.backend.java import com.squareup.javapoet.{ClassName, MethodSpec, TypeName} import com.typesafe.scalalogging.StrictLogging import javax.lang.model.element.Modifier +import com.digitalasset.daml.lf.codegen.backend.java.inner.ClassNameExtensions private[codegen] object ObjectMethods extends StrictLogging { - def apply(className: ClassName, fieldNames: IndexedSeq[String]): Vector[MethodSpec] = + def apply(className: ClassName, typeParameters: IndexedSeq[String], fieldNames: IndexedSeq[String]): Vector[MethodSpec] = Vector( - generateEquals(className, fieldNames), + generateEquals(className.asWildcardType(typeParameters), fieldNames), generateHashCode(fieldNames), generateToString(className, fieldNames, None)) def apply( className: ClassName, + typeParameters: IndexedSeq[String], fieldNames: IndexedSeq[String], enclosingClassName: ClassName): Vector[MethodSpec] = Vector( - generateEquals(className, fieldNames), + generateEquals(className.asWildcardType(typeParameters), fieldNames), generateHashCode(fieldNames), generateToString(className, fieldNames, Some(enclosingClassName))) - private def initEqualsBuilder(className: ClassName): MethodSpec.Builder = + private def initEqualsBuilder(className: TypeName): MethodSpec.Builder = MethodSpec .methodBuilder("equals") .addModifiers(Modifier.PUBLIC) @@ -40,13 +42,13 @@ private[codegen] object ObjectMethods extends StrictLogging { .beginControlFlow("if (!(object instanceof $T))", className) .addStatement("return false") .endControlFlow() - .addStatement("$T other = ($T) object", className, className) - private def generateEquals(className: ClassName, fieldNames: IndexedSeq[String]): MethodSpec = + private def generateEquals(className: TypeName, fieldNames: IndexedSeq[String]): MethodSpec = if (fieldNames.isEmpty) { initEqualsBuilder(className).addStatement("return true").build() } else { initEqualsBuilder(className) + .addStatement("$T other = ($T) object", className, className) .addStatement( s"return ${List.fill(fieldNames.size)("this.$L.equals(other.$L)").mkString(" && ")}", fieldNames.flatMap(fieldName => IndexedSeq(fieldName, fieldName)): _* diff --git a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/EnumClass.scala b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/EnumClass.scala index fafb6a18ec4..cb21d01a6fe 100644 --- a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/EnumClass.scala +++ b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/EnumClass.scala @@ -24,7 +24,7 @@ private[inner] object EnumClass extends StrictLogging { val enumType = TypeSpec.enumBuilder(className).addModifiers(Modifier.PUBLIC) enum.constructors.foreach(c => enumType.addEnumConstant(c.toUpperCase())) enumType.addField(generateValuesArray(enum)) - enumType.addMethod(generateEnumsMapBuilder(enum)) + enumType.addMethod(generateEnumsMapBuilder(className, enum)) enumType.addField(generateEnumsMap(className)) enumType.addMethod(generateFromValue(className, enum)) enumType.addMethod(generateToValue(className)) @@ -43,21 +43,24 @@ private[inner] object EnumClass extends StrictLogging { fieldSpec.build() } + private def mapType(className: ClassName) = ParameterizedTypeName.get(ClassName.get(classOf[java.util.Map[Any, Any]]), ClassName.get(classOf[String]), className) + private def hashMapType(className: ClassName) = ParameterizedTypeName.get(ClassName.get(classOf[java.util.HashMap[Any, Any]]), ClassName.get(classOf[String]), className) + private def generateEnumsMap(className: ClassName): FieldSpec = FieldSpec - .builder(classOf[java.util.Map[Any, Any]], "__enums$") + .builder(mapType(className), "__enums$") .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) .initializer("$T.__buildEnumsMap$$()", className) .build() - private def generateEnumsMapBuilder(enum: iface.Enum): MethodSpec = { + private def generateEnumsMapBuilder(className: ClassName, enum: iface.Enum): MethodSpec = { val builder = MethodSpec.methodBuilder("__buildEnumsMap$") builder.addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) - builder.returns(classOf[java.util.Map[Any, Any]]) + builder.returns(mapType(className)) builder.addStatement( "$T m = new $T()", - classOf[java.util.Map[Any, Any]], - classOf[java.util.HashMap[Any, Any]]) + mapType(className), + hashMapType(className)) enum.constructors.foreach(c => builder.addStatement(s"""m.put("$c", ${c.toUpperCase()})""")) builder.addStatement("return m") builder.build() diff --git a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/RecordMethods.scala b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/RecordMethods.scala index 40a341eb340..9885ffcadba 100644 --- a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/RecordMethods.scala +++ b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/RecordMethods.scala @@ -45,6 +45,6 @@ private[inner] object RecordMethods { } Vector(constructor) ++ conversionMethods ++ - ObjectMethods(className, fields.map(_.javaName)) + ObjectMethods(className, typeParameters, fields.map(_.javaName)) } } diff --git a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/TemplateClass.scala b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/TemplateClass.scala index 72ce65243e7..59cd793a35f 100644 --- a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/TemplateClass.scala +++ b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/TemplateClass.scala @@ -157,7 +157,7 @@ private[inner] object TemplateClass extends StrictLogging { key, packagePrefixes )) - .addMethods(ObjectMethods(contractClassName, fields, templateClassName).asJava) + .addMethods(ObjectMethods(contractClassName, IndexedSeq.empty, fields, templateClassName).asJava) .build() } diff --git a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/VariantConstructorClass.scala b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/VariantConstructorClass.scala index 815bca9c4e7..3d832b13cb3 100644 --- a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/VariantConstructorClass.scala +++ b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/VariantConstructorClass.scala @@ -51,7 +51,7 @@ object VariantConstructorClass extends StrictLogging { .addMethod(ConstructorGenerator.generateConstructor( IndexedSeq(FieldInfo("body", body, variantFieldName, javaType)))) .addMethods(conversionMethods.asJava) - .addMethods(ObjectMethods(className.rawType, Vector(variantFieldName)).asJava) + .addMethods(ObjectMethods(className.rawType, typeArgs, Vector(variantFieldName)).asJava) .build() } } diff --git a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/VariantRecordMethods.scala b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/VariantRecordMethods.scala index f2e7e9c722b..f4e60c0fb38 100644 --- a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/VariantRecordMethods.scala +++ b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/VariantRecordMethods.scala @@ -43,7 +43,7 @@ private[inner] object VariantRecordMethods extends StrictLogging { } Vector(constructor) ++ conversionMethods ++ - ObjectMethods(className.rawType, fields.map(_.javaName)) + ObjectMethods(className.rawType, typeParameters, fields.map(_.javaName)) } } diff --git a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/package.scala b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/package.scala index 3ab62068781..4463e4c6a7b 100644 --- a/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/package.scala +++ b/language-support/java/codegen/src/main/scala/com/digitalasset/daml/lf/codegen/backend/java/inner/package.scala @@ -7,7 +7,7 @@ import java.util import com.daml.ledger.javaapi import com.daml.ledger.javaapi.data.codegen.ContractId -import com.daml.ledger.javaapi.data.{DamlGenMap, DamlList, DamlTextMap, DamlOptional} +import com.daml.ledger.javaapi.data.{DamlGenMap, DamlList, DamlOptional, DamlTextMap} import com.digitalasset.daml.lf.data.ImmArray.ImmArraySeq import com.digitalasset.daml.lf.data.Ref.{Identifier, PackageId, QualifiedName} import com.digitalasset.daml.lf.iface._ @@ -195,6 +195,11 @@ package object inner { if (typeParams.isEmpty) name else ParameterizedTypeName.get(name, typeParams.map(TypeVariableName.get): _*) } + + def asWildcardType(typeParams: IndexedSeq[String]): TypeName = { + if (typeParams.isEmpty) name + else ParameterizedTypeName.get(name, typeParams.map(_ => WildcardTypeName.subtypeOf(classOf[Object])): _*) + } } } diff --git a/language-support/java/codegen/src/test/scala/com/digitalasset/daml/lf/codegen/backend/java/ObjectMethodsSpec.scala b/language-support/java/codegen/src/test/scala/com/digitalasset/daml/lf/codegen/backend/java/ObjectMethodsSpec.scala index ffe3cfd8f2a..3ff517cb836 100644 --- a/language-support/java/codegen/src/test/scala/com/digitalasset/daml/lf/codegen/backend/java/ObjectMethodsSpec.scala +++ b/language-support/java/codegen/src/test/scala/com/digitalasset/daml/lf/codegen/backend/java/ObjectMethodsSpec.scala @@ -12,7 +12,7 @@ import org.scalatest.{FlatSpec, Matchers} final class ObjectMethodsSpec extends FlatSpec with Matchers { val Vector(equalsSpec, hashCodeSpec, toStringSpec) = - ObjectMethods(ClassName.bestGuess("Test"), IndexedSeq.empty) + ObjectMethods(ClassName.bestGuess("Test"), IndexedSeq.empty, IndexedSeq.empty) behavior of "ObjectMethods.equals"