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
This commit is contained in:
Gerolf Seitz 2019-12-06 16:10:38 +01:00 committed by mergify[bot]
parent b7fdf2236c
commit 658365e5eb
8 changed files with 28 additions and 18 deletions

View File

@ -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)): _*

View File

@ -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()

View File

@ -45,6 +45,6 @@ private[inner] object RecordMethods {
}
Vector(constructor) ++ conversionMethods ++
ObjectMethods(className, fields.map(_.javaName))
ObjectMethods(className, typeParameters, fields.map(_.javaName))
}
}

View File

@ -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()
}

View File

@ -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()
}
}

View File

@ -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))
}
}

View File

@ -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])): _*)
}
}
}

View File

@ -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"