package org.inferred.freebuilder.processor.util; import static org.inferred.freebuilder.processor.util.feature.SourceLevel.SOURCE_LEVEL; import javax.lang.model.type.TypeKind; public class ObjectsExcerpts { public enum Nullability { NULLABLE, NOT_NULLABLE; public boolean isNullable() { return this == NULLABLE; } } /** * Returns an Excerpt equivalent to {@code Objects.equals(a, b)}. * * <p>If Objects is not available, {@code kind} and {@code nullability} are needed to generate * the most idiomatic equivalent. */ public static Excerpt equals(Object a, Object b, TypeKind kind, Nullability nullability) { return new EqualsExcerpt(true, a, b, kind, nullability); } /** * Returns an Excerpt equivalent to {@code !Objects.equals(a, b)}. * * <p>If Objects is not available, {@code kind} and {@code nullability} are needed to generate * the most idiomatic equivalent. */ public static Excerpt notEquals(Object a, Object b, TypeKind kind, Nullability nullability) { return new EqualsExcerpt(false, a, b, kind, nullability); } private static class EqualsExcerpt extends Excerpt { private final boolean areEqual; private final Object a; private final Object b; private final TypeKind kind; private final Nullability nullability; EqualsExcerpt(boolean areEqual, Object a, Object b, TypeKind kind, Nullability nullability) { this.areEqual = areEqual; this.a = a; this.b = b; this.kind = kind; this.nullability = nullability; } @Override public void addTo(SourceBuilder code) { QualifiedName javaUtilObjects = code.feature(SOURCE_LEVEL).javaUtilObjects().orNull(); if (javaUtilObjects != null) { code.add("%s%s.equals(%s, %s)", areEqual ? "" : "!", javaUtilObjects, a, b); } else if (nullability.isNullable()) { if (areEqual) { code.add("%1$s == %2$s || (%1$s != null && %1$s.equals(%2$s))", a, b); } else { code.add("%1$s != %2$s && (%1$s == null || !%1$s.equals(%2$s))", a, b); } } else if (kind.isPrimitive()) { switch (kind) { case FLOAT: code.add("%1$s.floatToIntBits(%2$s) %3$s %1$s.floatToIntBits(%4$s)", Float.class, a, areEqual ? "==" : "!=", b); break; case DOUBLE: code.add("%1$s.doubleToLongBits(%2$s) %3$s %1$s.doubleToLongBits(%4$s)", Double.class, a, areEqual ? "==" : "!=", b); break; default: code.add("%s %s %s", a, areEqual ? "==" : "!=", b); } } else { code.add("%s%s.equals(%s)", areEqual ? "" : "!", a, b); } } @Override protected void addFields(FieldReceiver fields) { fields.add("areEqual", areEqual); fields.add("a", a); fields.add("b", b); fields.add("kind", kind); fields.add("nullable", nullability); } } private ObjectsExcerpts() {} }