From 4ffa162a304d6dc8cd7444206a17a6a0b38f2c77 Mon Sep 17 00:00:00 2001 From: David Schlosnagle Date: Wed, 20 Jul 2022 09:17:55 -0400 Subject: [PATCH] Equals compares collections last --- .../conjure/java/types/MethodSpecs.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/MethodSpecs.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/MethodSpecs.java index 5bac5e53f..a70a57a1a 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/MethodSpecs.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/MethodSpecs.java @@ -19,6 +19,7 @@ import static com.palantir.logsafe.Preconditions.checkState; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.palantir.conjure.java.util.JavaNameSanitizer; import com.palantir.conjure.spec.FieldName; @@ -27,6 +28,7 @@ import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import java.time.OffsetDateTime; @@ -38,6 +40,8 @@ public final class MethodSpecs { + private static final ImmutableSet COLLECTION_TYPES = + ImmutableSet.of("java.util.List", "java.util.Set", "java.util.Map"); private static final String MEMOIZED_HASH_CODE = "memoizedHashCode"; public static MethodSpec createEquals(TypeName thisClass) { @@ -70,8 +74,10 @@ public static MethodSpec createEqualTo( CodeBlock equalsTo = fields.isEmpty() ? CodeBlock.of("$L", true) - : CodeBlocks.of( - fields.stream().map(MethodSpecs::createEqualsStatement).collect(joining(CodeBlock.of(" && ")))); + : CodeBlocks.of(fields.stream() + .sorted(MethodSpecs::collectionsLastForEquals) + .map(MethodSpecs::createEqualsStatement) + .collect(joining(CodeBlock.of(" && ")))); return MethodSpec.methodBuilder("equalTo") .addModifiers(Modifier.PRIVATE) @@ -82,6 +88,29 @@ public static MethodSpec createEqualTo( .build(); } + private static int collectionsLastForEquals(FieldSpec field1, FieldSpec field2) { + if (COLLECTION_TYPES.contains(getTypeForEquals(field1.type))) { + if (COLLECTION_TYPES.contains(getTypeForEquals(field2.type))) { + return 0; // both are collections, keep in place + } + return 1; // sort collections last for equals comparison + } + return 0; // keep in place + } + + private static String getTypeForEquals(TypeName typeName) { + if (typeName instanceof ParameterizedTypeName) { + ParameterizedTypeName parameterizedTypeName = (ParameterizedTypeName) typeName; + String canonicalName = parameterizedTypeName.rawType.canonicalName(); + if ("java.util.Optional".equals(canonicalName)) { + return getTypeForEquals( + parameterizedTypeName.typeArguments.iterator().next()); + } + return canonicalName; + } + return typeName.toString(); + } + private static CodeBlock createEqualsStatement(FieldSpec field) { String thisField = "this." + field.name; String otherField = "other." + field.name;