From 80374c5469929146172383598e8733ab0b7d6e6f Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 8 Mar 2024 13:09:49 +0100 Subject: [PATCH 01/74] Introduces new instantiation interfaces --- .../internal/checkers/FieldsChecker.java | 6 ++- .../fieldchecks/BigDecimalFieldCheck.java | 51 ++++++++++--------- .../checkers/fieldchecks/FieldCheck.java | 11 ++-- .../fieldchecks/FloatAndDoubleFieldCheck.java | 30 +++++------ .../FieldInstantiationStrategy.java | 8 +++ .../instantiation/SubjectCreator.java | 36 +++++++++++++ .../VintageFieldInstantiationStrategy.java | 24 +++++++++ 7 files changed, 121 insertions(+), 45 deletions(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldInstantiationStrategy.java create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageFieldInstantiationStrategy.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index ab958f5fe..e1675abc7 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -3,6 +3,7 @@ import java.util.function.Predicate; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.*; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; @@ -32,6 +33,7 @@ public FieldsChecker(Configuration config) { final PrefabValues prefabValues = config.getPrefabValues(); final TypeTag typeTag = config.getTypeTag(); + final SubjectCreator subjectCreator = new SubjectCreator<>(typeTag, prefabValues); final String cachedHashCodeFieldName = config .getCachedHashCodeInitializer() @@ -40,7 +42,7 @@ public FieldsChecker(Configuration config) { a.getFieldName().equals(cachedHashCodeFieldName); this.arrayFieldCheck = new ArrayFieldCheck<>(config.getCachedHashCodeInitializer()); - this.floatAndDoubleFieldCheck = new FloatAndDoubleFieldCheck<>(); + this.floatAndDoubleFieldCheck = new FloatAndDoubleFieldCheck<>(subjectCreator); this.mutableStateFieldCheck = new MutableStateFieldCheck<>(prefabValues, typeTag, isCachedHashCodeField); this.reflexivityFieldCheck = new ReflexivityFieldCheck<>(config); @@ -54,7 +56,7 @@ public FieldsChecker(Configuration config) { this.stringFieldCheck = new StringFieldCheck<>(config.getPrefabValues(), config.getCachedHashCodeInitializer()); this.bigDecimalFieldCheck = - new BigDecimalFieldCheck<>(config.getCachedHashCodeInitializer()); + new BigDecimalFieldCheck<>(subjectCreator, config.getCachedHashCodeInitializer()); this.jpaLazyGetterFieldCheck = new JpaLazyGetterFieldCheck<>(config); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java index 9c3fda89b..ee1e2b4da 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java @@ -6,7 +6,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -15,39 +15,40 @@ public class BigDecimalFieldCheck implements FieldCheck { public static final String ERROR_DOC_TITLE = "BigDecimal equality"; + private final SubjectCreator subjectCreator; private final CachedHashCodeInitializer cachedHashCodeInitializer; - public BigDecimalFieldCheck(CachedHashCodeInitializer cachedHashCodeInitializer) { + public BigDecimalFieldCheck( + SubjectCreator subjectCreator, + CachedHashCodeInitializer cachedHashCodeInitializer + ) { + this.subjectCreator = subjectCreator; this.cachedHashCodeInitializer = cachedHashCodeInitializer; } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - if (BigDecimal.class.equals(fieldAccessor.getFieldType())) { - Field field = fieldAccessor.getField(); - BigDecimal referenceField = (BigDecimal) referenceAccessor.getField(field); - BigDecimal changedField = referenceField.setScale( - referenceField.scale() + 1, + public void execute(Field changedField) { + if (BigDecimal.class.equals(changedField.getType())) { + T left = subjectCreator.plain(); + ObjectAccessor acc = ObjectAccessor.of(left); + + BigDecimal referenceValue = (BigDecimal) acc.getField(changedField); + BigDecimal changedValue = referenceValue.setScale( + referenceValue.scale() + 1, RoundingMode.UNNECESSARY ); - ObjectAccessor changed = copyAccessor.withFieldSetTo(field, changedField); - T left = referenceAccessor.get(); - T right = changed.get(); + T right = subjectCreator.withFieldSetTo(changedField, changedValue); - checkEquals(field, referenceField, changedField, left, right); - checkHashCode(field, referenceField, changedField, left, right); + checkEquals(changedField, referenceValue, changedValue, left, right); + checkHashCode(changedField, referenceValue, changedValue, left, right); } } private void checkEquals( Field field, - BigDecimal referenceField, - BigDecimal changedField, + BigDecimal referenceValue, + BigDecimal changedValue, T left, T right ) { @@ -58,8 +59,8 @@ private void checkEquals( "\nIf these values should be considered equal then use compareTo rather than equals for this field." + "\nIf these values should not be considered equal, suppress Warning.%% to disable this check.", field.getName(), - referenceField, - changedField, + referenceValue, + changedValue, Warning.BIGDECIMAL_EQUALITY ); assertEquals(f, left, right); @@ -67,8 +68,8 @@ private void checkEquals( private void checkHashCode( Field field, - BigDecimal referenceField, - BigDecimal changedField, + BigDecimal referenceValue, + BigDecimal changedValue, T left, T right ) { @@ -79,8 +80,8 @@ private void checkHashCode( "\nIf these values should be considered equal then make sure to derive the same constituent hashCode from this field." + "\nIf these values should not be considered equal, suppress Warning.%% to disable this check.", field.getName(), - referenceField, - changedField, + referenceValue, + changedValue, Warning.BIGDECIMAL_EQUALITY ); int leftHashCode = cachedHashCodeInitializer.getInitializedHashCode(left); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java index fd0cbd05f..d896d9972 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java @@ -1,13 +1,18 @@ package nl.jqno.equalsverifier.internal.checkers.fieldchecks; +import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; -@FunctionalInterface +// @FunctionalInterface public interface FieldCheck { - void execute( + default void execute( ObjectAccessor referenceAccessor, ObjectAccessor copyAccessor, FieldAccessor fieldAccessor - ); + ) { + execute(fieldAccessor.getField()); + } + + default void execute(Field changedField) {} } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java index 110e0d351..821876edd 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java @@ -3,39 +3,39 @@ import static nl.jqno.equalsverifier.internal.util.Assert.assertEquals; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; public class FloatAndDoubleFieldCheck implements FieldCheck { + private final SubjectCreator subjectCreator; + + public FloatAndDoubleFieldCheck(SubjectCreator subjectCreator) { + this.subjectCreator = subjectCreator; + } + @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - Class type = fieldAccessor.getFieldType(); - Field field = fieldAccessor.getField(); + public void execute(Field changedField) { + Class type = changedField.getType(); if (isFloat(type)) { - T reference = referenceAccessor.withFieldSetTo(field, Float.NaN).get(); - T copy = copyAccessor.withFieldSetTo(field, Float.NaN).get(); + T reference = subjectCreator.withFieldSetTo(changedField, Float.NaN); + T copy = subjectCreator.withFieldSetTo(changedField, Float.NaN); assertEquals( Formatter.of( "Float: equals doesn't use Float.compare for field %%.", - field.getName() + changedField.getName() ), reference, copy ); } if (isDouble(type)) { - T reference = referenceAccessor.withFieldSetTo(field, Double.NaN).get(); - T copy = copyAccessor.withFieldSetTo(field, Double.NaN).get(); + T reference = subjectCreator.withFieldSetTo(changedField, Double.NaN); + T copy = subjectCreator.withFieldSetTo(changedField, Double.NaN); assertEquals( Formatter.of( "Double: equals doesn't use Double.compare for field %%.", - field.getName() + changedField.getName() ), reference, copy diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldInstantiationStrategy.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldInstantiationStrategy.java new file mode 100644 index 000000000..9b3676f5e --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldInstantiationStrategy.java @@ -0,0 +1,8 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; + +public interface FieldInstantiationStrategy { + Tuple instantiate(TypeTag tag); +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java new file mode 100644 index 000000000..def06917e --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -0,0 +1,36 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; +import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; + +public class SubjectCreator { + + private final TypeTag typeTag; + private final PrefabValues prefabValues; + + @SuppressFBWarnings( + value = "EI_EXPOSE_REP2", + justification = "PrefabValues is inherently mutable." + ) + public SubjectCreator(TypeTag typeTag, PrefabValues prefabValues) { + this.typeTag = typeTag; + this.prefabValues = prefabValues; + } + + public T plain() { + return createSubject().get(); + } + + public T withFieldSetTo(Field field, Object value) { + return createSubject().withFieldSetTo(field, value).get(); + } + + private ObjectAccessor createSubject() { + ClassAccessor accessor = ClassAccessor.of(typeTag.getType(), prefabValues); + return accessor.getRedAccessor(TypeTag.NULL); + } +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageFieldInstantiationStrategy.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageFieldInstantiationStrategy.java new file mode 100644 index 000000000..4bb1ee37d --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageFieldInstantiationStrategy.java @@ -0,0 +1,24 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; + +public class VintageFieldInstantiationStrategy implements FieldInstantiationStrategy { + + private final PrefabValues prefabValues; + + @SuppressFBWarnings( + value = "EI_EXPOSE_REP2", + justification = "PrefabValues is inherently mutable." + ) + public VintageFieldInstantiationStrategy(PrefabValues prefabValues) { + this.prefabValues = prefabValues; + } + + @Override + public Tuple instantiate(TypeTag tag) { + return prefabValues.giveTuple(tag); + } +} From 876d6d44187fcd2ec3fd9eddba1bcf80eaa63db3 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 8 Mar 2024 16:18:35 +0100 Subject: [PATCH 02/74] Introduces SubjectCreator in several FieldChecks --- .../internal/checkers/FieldsChecker.java | 5 +-- .../checkers/fieldchecks/ArrayFieldCheck.java | 32 +++++++++++-------- .../fieldchecks/MutableStateFieldCheck.java | 31 ++++++------------ .../instantiation/SubjectCreator.java | 4 +++ 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index e1675abc7..f3fd7ee6f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -41,10 +41,11 @@ public FieldsChecker(Configuration config) { final Predicate isCachedHashCodeField = a -> a.getFieldName().equals(cachedHashCodeFieldName); - this.arrayFieldCheck = new ArrayFieldCheck<>(config.getCachedHashCodeInitializer()); + this.arrayFieldCheck = + new ArrayFieldCheck<>(subjectCreator, config.getCachedHashCodeInitializer()); this.floatAndDoubleFieldCheck = new FloatAndDoubleFieldCheck<>(subjectCreator); this.mutableStateFieldCheck = - new MutableStateFieldCheck<>(prefabValues, typeTag, isCachedHashCodeField); + new MutableStateFieldCheck<>(subjectCreator, isCachedHashCodeField); this.reflexivityFieldCheck = new ReflexivityFieldCheck<>(config); this.significantFieldCheck = new SignificantFieldCheck<>(config, isCachedHashCodeField, false); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java index 02a98cc4f..4539a2ed1 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java @@ -4,6 +4,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; @@ -11,29 +12,31 @@ public class ArrayFieldCheck implements FieldCheck { + private SubjectCreator subjectCreator; private CachedHashCodeInitializer cachedHashCodeInitializer; - public ArrayFieldCheck(CachedHashCodeInitializer cachedHashCodeInitializer) { + public ArrayFieldCheck( + SubjectCreator subjectCreator, + CachedHashCodeInitializer cachedHashCodeInitializer + ) { + this.subjectCreator = subjectCreator; this.cachedHashCodeInitializer = cachedHashCodeInitializer; } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - Class arrayType = fieldAccessor.getFieldType(); + public void execute(Field changedField) { + Class arrayType = changedField.getType(); if (!arrayType.isArray()) { return; } + FieldAccessor fieldAccessor = FieldAccessor.of(changedField); if (!fieldAccessor.canBeModifiedReflectively()) { return; } - String fieldName = fieldAccessor.getFieldName(); - T reference = referenceAccessor.get(); - T changed = replaceInnermostArrayValue(copyAccessor, fieldAccessor.getField()).get(); + String fieldName = changedField.getName(); + T reference = subjectCreator.plain(); + T changed = replaceInnermostArrayValue(reference, changedField); if (arrayType.getComponentType().isArray()) { assertDeep(fieldName, reference, changed); @@ -42,9 +45,12 @@ public void execute( } } - private ObjectAccessor replaceInnermostArrayValue(ObjectAccessor accessor, Field field) { - Object newArray = arrayCopy(accessor.getField(field)); - return accessor.withFieldSetTo(field, newArray); + private T replaceInnermostArrayValue(T reference, Field field) { + // Object newArray = arrayCopy(accessor.getField(field)); + // return accessor.withFieldSetTo(field, newArray); + ObjectAccessor objectAccessor = ObjectAccessor.of(reference); + Object newArray = arrayCopy(objectAccessor.getField(field)); + return subjectCreator.withFieldSetTo(field, newArray); } private Object arrayCopy(Object array) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java index c886c06ed..e1b19ab30 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java @@ -5,16 +5,13 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; import java.util.function.Predicate; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Formatter; public class MutableStateFieldCheck implements FieldCheck { - private final PrefabValues prefabValues; - private final TypeTag typeTag; + private final SubjectCreator subjectCreator; private final Predicate isCachedHashCodeField; @SuppressFBWarnings( @@ -22,31 +19,25 @@ public class MutableStateFieldCheck implements FieldCheck { justification = "PrefabValues is inherently mutable." ) public MutableStateFieldCheck( - PrefabValues prefabValues, - TypeTag typeTag, + SubjectCreator subjectCreator, Predicate isCachedHashCodeField ) { - this.prefabValues = prefabValues; - this.typeTag = typeTag; + this.subjectCreator = subjectCreator; this.isCachedHashCodeField = isCachedHashCodeField; } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { + public void execute(Field changedField) { + FieldAccessor fieldAccessor = FieldAccessor.of(changedField); if (isCachedHashCodeField.test(fieldAccessor)) { return; } - Field field = fieldAccessor.getField(); - T reference = referenceAccessor.get(); - T copy = copyAccessor.get(); + T reference = subjectCreator.plain(); + T copy = subjectCreator.plain(); boolean equalBefore = reference.equals(copy); - T changed = copyAccessor.withChangedField(field, prefabValues, typeTag).get(); + T changed = subjectCreator.withFieldChanged(changedField); boolean equalAfter = reference.equals(changed); if (equalBefore && !equalAfter && !fieldAccessor.fieldIsFinal()) { @@ -54,9 +45,7 @@ public void execute( "Mutability: equals depends on mutable field %%.\n" + "Make the field final, suppress Warning.NONFINAL_FIELDS or use" + " EqualsVerifier.simple()"; - fail(Formatter.of(message, field.getName())); + fail(Formatter.of(message, changedField.getName())); } - - referenceAccessor.withChangedField(field, prefabValues, typeTag); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index def06917e..b989fa7f4 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -29,6 +29,10 @@ public T withFieldSetTo(Field field, Object value) { return createSubject().withFieldSetTo(field, value).get(); } + public T withFieldChanged(Field field) { + return createSubject().withChangedField(field, prefabValues, typeTag).get(); + } + private ObjectAccessor createSubject() { ClassAccessor accessor = ClassAccessor.of(typeTag.getType(), prefabValues); return accessor.getRedAccessor(TypeTag.NULL); From 732ba8bff75ff7af5185c7e551b0b20ab2b8d613 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 8 Mar 2024 20:07:31 +0100 Subject: [PATCH 03/74] Introduces SubjectCreator in several FieldChecks --- .../internal/checkers/FieldsChecker.java | 2 +- .../checkers/fieldchecks/ArrayFieldCheck.java | 4 +- .../fieldchecks/TransitivityFieldCheck.java | 44 ++++--------------- .../instantiation/SubjectCreator.java | 9 ++++ 4 files changed, 20 insertions(+), 39 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index f3fd7ee6f..dc270bdd0 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -53,7 +53,7 @@ public FieldsChecker(Configuration config) { new SignificantFieldCheck<>(config, isCachedHashCodeField, true); this.symmetryFieldCheck = new SymmetryFieldCheck<>(prefabValues, typeTag); this.transientFieldsCheck = new TransientFieldsCheck<>(config); - this.transitivityFieldCheck = new TransitivityFieldCheck<>(prefabValues, typeTag); + this.transitivityFieldCheck = new TransitivityFieldCheck<>(subjectCreator); this.stringFieldCheck = new StringFieldCheck<>(config.getPrefabValues(), config.getCachedHashCodeInitializer()); this.bigDecimalFieldCheck = diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java index 4539a2ed1..364d15218 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java @@ -12,8 +12,8 @@ public class ArrayFieldCheck implements FieldCheck { - private SubjectCreator subjectCreator; - private CachedHashCodeInitializer cachedHashCodeInitializer; + private final SubjectCreator subjectCreator; + private final CachedHashCodeInitializer cachedHashCodeInitializer; public ArrayFieldCheck( SubjectCreator subjectCreator, diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java index 8bf74a553..7edbf3691 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java @@ -4,37 +4,26 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; public class TransitivityFieldCheck implements FieldCheck { - private final PrefabValues prefabValues; - private final TypeTag typeTag; + private final SubjectCreator subjectCreator; @SuppressFBWarnings( value = "EI_EXPOSE_REP2", justification = "PrefabValues is inherently mutable." ) - public TransitivityFieldCheck(PrefabValues prefabValues, TypeTag typeTag) { - this.prefabValues = prefabValues; - this.typeTag = typeTag; + public TransitivityFieldCheck(SubjectCreator subjectCreator) { + this.subjectCreator = subjectCreator; } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - Field field = fieldAccessor.getField(); - T a1 = referenceAccessor.get(); - T b1 = buildB1(copyAccessor, field); - T b2 = buildB2(referenceAccessor, field); + public void execute(Field changedField) { + T a1 = subjectCreator.plain(); + T b1 = subjectCreator.withFieldChanged(changedField); + T b2 = subjectCreator.withAllFieldsChanged(); boolean x = a1.equals(b1); boolean y = b1.equals(b2); @@ -53,23 +42,6 @@ public void execute( } } - private T buildB1(ObjectAccessor accessor, Field field) { - accessor.withChangedField(field, prefabValues, typeTag); - return accessor.get(); - } - - private T buildB2(ObjectAccessor referenceAccessor, Field field) { - T copy = referenceAccessor.copy(); - ObjectAccessor objectAccessor = ObjectAccessor.of(copy); - objectAccessor = objectAccessor.withChangedField(field, prefabValues, typeTag); - for (Field f : FieldIterable.of(referenceAccessor.type())) { - if (!f.equals(field)) { - objectAccessor = objectAccessor.withChangedField(f, prefabValues, typeTag); - } - } - return objectAccessor.get(); - } - private int countFalses(boolean... bools) { int result = 0; for (boolean b : bools) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index b989fa7f4..87fa8f97b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -5,6 +5,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; public class SubjectCreator { @@ -33,6 +34,14 @@ public T withFieldChanged(Field field) { return createSubject().withChangedField(field, prefabValues, typeTag).get(); } + public T withAllFieldsChanged() { + ObjectAccessor accessor = createSubject(); + for (Field f : FieldIterable.of(typeTag.getType())) { + accessor = accessor.withChangedField(f, prefabValues, typeTag); + } + return accessor.get(); + } + private ObjectAccessor createSubject() { ClassAccessor accessor = ClassAccessor.of(typeTag.getType(), prefabValues); return accessor.getRedAccessor(TypeTag.NULL); From 207224876cc36fef2e47a4132041e3b767ecc232 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sat, 9 Mar 2024 09:37:29 +0100 Subject: [PATCH 04/74] Introduces SubjectCreator in several FieldChecks --- .../internal/checkers/FieldsChecker.java | 13 +++-- .../internal/checkers/NullChecker.java | 8 ++- .../NullPointerExceptionFieldCheck.java | 37 ++++++------ .../fieldchecks/ReflexivityFieldCheck.java | 57 +++++++------------ .../fieldchecks/StringFieldCheck.java | 23 ++++---- .../fieldchecks/SymmetryFieldCheck.java | 51 +++++------------ .../fieldchecks/TransientFieldsCheck.java | 40 +++++++------ .../instantiation/SubjectCreator.java | 4 ++ 8 files changed, 106 insertions(+), 127 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index dc270bdd0..a8792e869 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -46,16 +46,21 @@ public FieldsChecker(Configuration config) { this.floatAndDoubleFieldCheck = new FloatAndDoubleFieldCheck<>(subjectCreator); this.mutableStateFieldCheck = new MutableStateFieldCheck<>(subjectCreator, isCachedHashCodeField); - this.reflexivityFieldCheck = new ReflexivityFieldCheck<>(config); + this.reflexivityFieldCheck = new ReflexivityFieldCheck<>(subjectCreator, config); this.significantFieldCheck = new SignificantFieldCheck<>(config, isCachedHashCodeField, false); this.skippingSignificantFieldCheck = new SignificantFieldCheck<>(config, isCachedHashCodeField, true); - this.symmetryFieldCheck = new SymmetryFieldCheck<>(prefabValues, typeTag); - this.transientFieldsCheck = new TransientFieldsCheck<>(config); + this.symmetryFieldCheck = new SymmetryFieldCheck<>(subjectCreator); + this.transientFieldsCheck = + new TransientFieldsCheck<>(subjectCreator, typeTag, config.getAnnotationCache()); this.transitivityFieldCheck = new TransitivityFieldCheck<>(subjectCreator); this.stringFieldCheck = - new StringFieldCheck<>(config.getPrefabValues(), config.getCachedHashCodeInitializer()); + new StringFieldCheck<>( + subjectCreator, + config.getPrefabValues(), + config.getCachedHashCodeInitializer() + ); this.bigDecimalFieldCheck = new BigDecimalFieldCheck<>(subjectCreator, config.getCachedHashCodeInitializer()); this.jpaLazyGetterFieldCheck = new JpaLazyGetterFieldCheck<>(config); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java index 006ff02a9..5da8f478e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java @@ -2,6 +2,7 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.NullPointerExceptionFieldCheck; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -21,6 +22,11 @@ public void check() { ClassAccessor classAccessor = config.getClassAccessor(); FieldInspector inspector = new FieldInspector<>(classAccessor, config.getTypeTag()); - inspector.check(new NullPointerExceptionFieldCheck<>(config)); + inspector.check( + new NullPointerExceptionFieldCheck<>( + new SubjectCreator<>(config.getTypeTag(), config.getPrefabValues()), + config + ) + ); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java index 1aab5cdca..97e43b828 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java @@ -4,6 +4,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldModifier; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; @@ -17,40 +18,40 @@ ) public class NullPointerExceptionFieldCheck implements FieldCheck { - private Configuration config; + private final SubjectCreator subjectCreator; + private final Configuration config; - public NullPointerExceptionFieldCheck(Configuration config) { + public NullPointerExceptionFieldCheck( + SubjectCreator subjectCreator, + Configuration config + ) { + this.subjectCreator = subjectCreator; this.config = config; } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - if (config.getNonnullFields().contains(fieldAccessor.getFieldName())) { + public void execute(Field changedField) { + if (config.getNonnullFields().contains(changedField.getName())) { return; } - if (fieldAccessor.getFieldType().isPrimitive()) { + if (changedField.getType().isPrimitive()) { return; } - Field field = fieldAccessor.getField(); - if (NonnullAnnotationVerifier.fieldIsNonnull(field, config.getAnnotationCache())) { + if (NonnullAnnotationVerifier.fieldIsNonnull(changedField, config.getAnnotationCache())) { return; } - if (fieldAccessor.fieldIsStatic()) { - FieldModifier fieldModifier = FieldModifier.of(field, referenceAccessor.get()); - Object saved = referenceAccessor.getField(field); + if (FieldAccessor.of(changedField).fieldIsStatic()) { + T reference = subjectCreator.plain(); + FieldModifier fieldModifier = FieldModifier.of(changedField, reference); + Object saved = ObjectAccessor.of(reference).getField(changedField); fieldModifier.defaultStaticField(); - performTests(field, referenceAccessor.get(), copyAccessor.get()); + performTests(changedField, subjectCreator.plain(), subjectCreator.plain()); fieldModifier.set(saved); } else { - ObjectAccessor changed = copyAccessor.withDefaultedField(field); - performTests(field, referenceAccessor.get(), changed.get()); - referenceAccessor.withDefaultedField(field); + T changed = subjectCreator.withFieldDefaulted(changedField); + performTests(changedField, subjectCreator.plain(), changed); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index e9f221996..22d70dd4c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -7,11 +7,11 @@ import java.util.EnumSet; import java.util.Set; import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.NonnullAnnotationVerifier; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; @@ -20,13 +20,15 @@ public class ReflexivityFieldCheck implements FieldCheck { + private final SubjectCreator subjectCreator; private final TypeTag typeTag; private final PrefabValues prefabValues; private final EnumSet warningsToSuppress; private final Set nonnullFields; private final AnnotationCache annotationCache; - public ReflexivityFieldCheck(Configuration config) { + public ReflexivityFieldCheck(SubjectCreator subjectCreator, Configuration config) { + this.subjectCreator = subjectCreator; this.typeTag = config.getTypeTag(); this.prefabValues = config.getPrefabValues(); this.warningsToSuppress = config.getWarningsToSuppress(); @@ -35,43 +37,31 @@ public ReflexivityFieldCheck(Configuration config) { } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { + public void execute(Field changedField) { if (warningsToSuppress.contains(Warning.IDENTICAL_COPY_FOR_VERSIONED_ENTITY)) { return; } - checkReferenceReflexivity(referenceAccessor, copyAccessor); - checkValueReflexivity(referenceAccessor, copyAccessor, fieldAccessor); - checkNullReflexivity(referenceAccessor, copyAccessor, fieldAccessor); + checkReferenceReflexivity(); + checkValueReflexivity(changedField); + checkNullReflexivity(changedField); } - private void checkReferenceReflexivity( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor - ) { - T left = referenceAccessor.get(); - T right = copyAccessor.get(); + private void checkReferenceReflexivity() { + T left = subjectCreator.plain(); + T right = subjectCreator.plain(); checkReflexivityFor(left, right); } - private void checkValueReflexivity( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - Field field = fieldAccessor.getField(); - Class fieldType = field.getType(); + private void checkValueReflexivity(Field changedField) { + Class fieldType = changedField.getType(); if (warningsToSuppress.contains(Warning.REFERENCE_EQUALITY)) { return; } if (fieldType.equals(Object.class) || fieldType.isInterface()) { return; } - if (fieldAccessor.fieldIsStatic()) { + if (FieldAccessor.of(changedField).fieldIsStatic()) { return; } ClassAccessor fieldTypeAccessor = ClassAccessor.of(fieldType, prefabValues); @@ -83,24 +73,21 @@ private void checkValueReflexivity( return; } - TypeTag tag = TypeTag.of(field, typeTag); - Object left = referenceAccessor.withFieldSetTo(field, prefabValues.giveRed(tag)).get(); - Object right = copyAccessor.withFieldSetTo(field, prefabValues.giveRedCopy(tag)).get(); + TypeTag tag = TypeTag.of(changedField, typeTag); + Object left = subjectCreator.withFieldSetTo(changedField, prefabValues.giveRed(tag)); + Object right = subjectCreator.withFieldSetTo(changedField, prefabValues.giveRedCopy(tag)); Formatter f = Formatter.of( "Reflexivity: == used instead of .equals() on field: %%" + "\nIf this is intentional, consider suppressing Warning.%%", - field.getName(), + changedField.getName(), Warning.REFERENCE_EQUALITY.toString() ); assertEquals(f, left, right); } - private void checkNullReflexivity( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { + private void checkNullReflexivity(Field changedField) { + FieldAccessor fieldAccessor = FieldAccessor.of(changedField); if (fieldAccessor.fieldIsPrimitive() && warningsToSuppress.contains(Warning.ZERO_FIELDS)) { return; } @@ -113,8 +100,8 @@ private void checkNullReflexivity( return; } - T left = referenceAccessor.withDefaultedField(field).get(); - T right = copyAccessor.withDefaultedField(field).get(); + T left = subjectCreator.withFieldDefaulted(field); + T right = subjectCreator.withFieldDefaulted(field); checkReflexivityFor(left, right); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java index c2437c09d..51fa87a40 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java @@ -5,10 +5,10 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -16,6 +16,7 @@ public class StringFieldCheck implements FieldCheck { public static final String ERROR_DOC_TITLE = "String equality"; + private final SubjectCreator subjectCreator; private final PrefabValues prefabValues; private final CachedHashCodeInitializer cachedHashCodeInitializer; @@ -24,9 +25,11 @@ public class StringFieldCheck implements FieldCheck { justification = "PrefabValues is inherently mutable." ) public StringFieldCheck( + SubjectCreator subjectCreator, PrefabValues prefabValues, CachedHashCodeInitializer cachedHashCodeInitializer ) { + this.subjectCreator = subjectCreator; this.prefabValues = prefabValues; this.cachedHashCodeInitializer = cachedHashCodeInitializer; } @@ -36,20 +39,18 @@ public StringFieldCheck( value = "DM_CONVERT_CASE", justification = "String prefab values are probably not localized." ) - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - if (String.class.equals(fieldAccessor.getFieldType()) && !fieldAccessor.fieldIsStatic()) { - Field field = fieldAccessor.getField(); + public void execute(Field changedField) { + if ( + String.class.equals(changedField.getType()) && + !FieldAccessor.of(changedField).fieldIsStatic() + ) { String red = prefabValues.giveRed(new TypeTag(String.class)); final T reference; final T copy; try { - reference = referenceAccessor.withFieldSetTo(field, red.toLowerCase()).get(); - copy = copyAccessor.withFieldSetTo(field, red.toUpperCase()).get(); + reference = subjectCreator.withFieldSetTo(changedField, red.toLowerCase()); + copy = subjectCreator.withFieldSetTo(changedField, red.toUpperCase()); } catch (ReflectionException ignored) { // Differently-cased String is not allowed, so cannot cause problems either. return; @@ -66,7 +67,7 @@ public void execute( ERROR_DOC_TITLE + ": class uses equalsIgnoreCase to compare String field %%, but hashCode is case-sensitive." + " Use toUpperCase() to determine the hashCode.", - field.getName() + changedField.getName() ) ); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java index b5318cff6..2cc8a3916 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java @@ -4,57 +4,34 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; public class SymmetryFieldCheck implements FieldCheck { - private final PrefabValues prefabValues; - private final TypeTag typeTag; + private final SubjectCreator subjectCreator; @SuppressFBWarnings( value = "EI_EXPOSE_REP2", justification = "PrefabValues is inherently mutable." ) - public SymmetryFieldCheck(PrefabValues prefabValues, TypeTag typeTag) { - this.prefabValues = prefabValues; - this.typeTag = typeTag; + public SymmetryFieldCheck(SubjectCreator subjectCreator) { + this.subjectCreator = subjectCreator; } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - Field field = fieldAccessor.getField(); - - checkSymmetry(referenceAccessor, copyAccessor); - - ObjectAccessor changedAccessor = copyAccessor.withChangedField( - field, - prefabValues, - typeTag - ); - checkSymmetry(referenceAccessor, changedAccessor); - - ObjectAccessor changedReferenceAccessor = referenceAccessor.withChangedField( - field, - prefabValues, - typeTag - ); - checkSymmetry(changedReferenceAccessor, changedAccessor); + public void execute(Field changedField) { + T left = subjectCreator.plain(); + T right = subjectCreator.plain(); + T changedLeft = subjectCreator.withFieldChanged(changedField); + T changedRight = subjectCreator.withFieldChanged(changedField); + + checkSymmetry(left, right); + checkSymmetry(left, changedRight); + checkSymmetry(changedLeft, changedRight); } - private void checkSymmetry( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor - ) { - T left = referenceAccessor.get(); - T right = copyAccessor.get(); + private void checkSymmetry(T left, T right) { assertTrue( Formatter.of("Symmetry: objects are not symmetric:\n %%\nand\n %%", left, right), left.equals(right) == right.equals(left) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java index 5e849ed4b..b3faa02ea 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java @@ -2,54 +2,52 @@ import static nl.jqno.equalsverifier.internal.util.Assert.fail; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; -import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Formatter; public class TransientFieldsCheck implements FieldCheck { - private final PrefabValues prefabValues; + private final SubjectCreator subjectCreator; private final TypeTag typeTag; private final AnnotationCache annotationCache; - public TransientFieldsCheck(Configuration config) { - this.prefabValues = config.getPrefabValues(); - this.typeTag = config.getTypeTag(); - this.annotationCache = config.getAnnotationCache(); + @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "A cache is inherently mutable.") + public TransientFieldsCheck( + SubjectCreator subjectCreator, + TypeTag typeTag, + AnnotationCache annotationCache + ) { + this.subjectCreator = subjectCreator; + this.typeTag = typeTag; + this.annotationCache = annotationCache; } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - Field field = fieldAccessor.getField(); - T reference = referenceAccessor.get(); - T changed = copyAccessor.withChangedField(field, prefabValues, typeTag).get(); + public void execute(Field changedField) { + T reference = subjectCreator.plain(); + T changed = subjectCreator.withFieldChanged(changedField); boolean equalsChanged = !reference.equals(changed); boolean hasAnnotation = annotationCache.hasFieldAnnotation( typeTag.getType(), - field.getName(), + changedField.getName(), SupportedAnnotations.TRANSIENT ); - boolean fieldIsTransient = fieldAccessor.fieldIsTransient() || hasAnnotation; + boolean fieldIsTransient = + FieldAccessor.of(changedField).fieldIsTransient() || hasAnnotation; if (equalsChanged && fieldIsTransient) { fail( Formatter.of( "Transient field %% should not be included in equals/hashCode contract.", - field.getName() + changedField.getName() ) ); } - - referenceAccessor.withChangedField(field, prefabValues, typeTag); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index 87fa8f97b..cf880bd20 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -26,6 +26,10 @@ public T plain() { return createSubject().get(); } + public T withFieldDefaulted(Field field) { + return createSubject().withDefaultedField(field).get(); + } + public T withFieldSetTo(Field field, Object value) { return createSubject().withFieldSetTo(field, value).get(); } From de369be0870e86ebeda93e12e779f9f7d50aba07 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Wed, 13 Mar 2024 11:27:28 +0100 Subject: [PATCH 05/74] Introduces SubjectCreator in more FieldChecks --- .../internal/checkers/FieldsChecker.java | 2 +- .../fieldchecks/JpaLazyGetterFieldCheck.java | 51 +++++++------------ 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index a8792e869..633e6b6fa 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -63,7 +63,7 @@ public FieldsChecker(Configuration config) { ); this.bigDecimalFieldCheck = new BigDecimalFieldCheck<>(subjectCreator, config.getCachedHashCodeInitializer()); - this.jpaLazyGetterFieldCheck = new JpaLazyGetterFieldCheck<>(config); + this.jpaLazyGetterFieldCheck = new JpaLazyGetterFieldCheck<>(subjectCreator, config); } @Override diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index 5ecd18ca9..fe9bb4628 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -4,16 +4,15 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static nl.jqno.equalsverifier.internal.util.Assert.assertTrue; +import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.function.Function; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.Instantiator; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.*; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -21,36 +20,32 @@ public class JpaLazyGetterFieldCheck implements FieldCheck { + private final SubjectCreator subjectCreator; private final Class type; private final ClassAccessor accessor; private final PrefabValues prefabValues; private final AnnotationCache annotationCache; private final Function fieldnameToGetter; - private final TypeTag typeTag; private final boolean strictHashcode; - public JpaLazyGetterFieldCheck(Configuration config) { + public JpaLazyGetterFieldCheck(SubjectCreator subjectCreator, Configuration config) { + this.subjectCreator = subjectCreator; this.type = config.getType(); this.accessor = config.getClassAccessor(); this.prefabValues = config.getPrefabValues(); this.annotationCache = config.getAnnotationCache(); this.fieldnameToGetter = config.getFieldnameToGetter(); - this.typeTag = config.getTypeTag(); this.strictHashcode = config.getWarningsToSuppress().contains(Warning.STRICT_HASHCODE); } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - String fieldName = fieldAccessor.getFieldName(); + public void execute(Field changedField) { + String fieldName = changedField.getName(); String getterName = fieldnameToGetter.apply(fieldName); if ( - !fieldIsUsed(referenceAccessor, copyAccessor, fieldAccessor, true) || - !fieldIsLazy(fieldAccessor) || + !fieldIsUsed(changedField, true) || + !fieldIsLazy(fieldName) || Modifier.isFinal(type.getModifiers()) ) { return; @@ -70,8 +65,7 @@ public void execute( } assertEntity(fieldName, "equals", getterName, equalsExceptionCaught); - boolean usedInHashcode = - !strictHashcode || fieldIsUsed(referenceAccessor, copyAccessor, fieldAccessor, false); + boolean usedInHashcode = !strictHashcode || fieldIsUsed(changedField, false); boolean hashCodeExceptionCaught = false; try { red1.hashCode(); @@ -81,16 +75,9 @@ public void execute( assertEntity(fieldName, "hashCode", getterName, hashCodeExceptionCaught || !usedInHashcode); } - private boolean fieldIsUsed( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor, - boolean forEquals - ) { - T red = referenceAccessor.get(); - T blue = copyAccessor - .withChangedField(fieldAccessor.getField(), prefabValues, typeTag) - .get(); + private boolean fieldIsUsed(Field changedField, boolean forEquals) { + T red = subjectCreator.plain(); + T blue = subjectCreator.withFieldChanged(changedField); if (forEquals) { return !red.equals(blue); @@ -99,18 +86,14 @@ private boolean fieldIsUsed( } } - private boolean fieldIsLazy(FieldAccessor fieldAccessor) { + private boolean fieldIsLazy(String fieldName) { return ( annotationCache.hasFieldAnnotation( type, - fieldAccessor.getFieldName(), + fieldName, SupportedAnnotations.JPA_LINKED_FIELD ) || - annotationCache.hasFieldAnnotation( - type, - fieldAccessor.getFieldName(), - SupportedAnnotations.JPA_LAZY_FIELD - ) + annotationCache.hasFieldAnnotation(type, fieldName, SupportedAnnotations.JPA_LAZY_FIELD) ); } From a1e4205e4d75eded6a1b89060a5a81b743ed4142 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Wed, 13 Mar 2024 19:24:17 +0100 Subject: [PATCH 06/74] Introduces SubjectCreator in last FieldChecks, refactors FieldCheck itself --- .../internal/checkers/FieldInspector.java | 55 ++--------- .../internal/checkers/FieldsChecker.java | 19 +--- .../internal/checkers/NullChecker.java | 11 +-- .../checkers/fieldchecks/ArrayFieldCheck.java | 16 ++-- .../fieldchecks/BigDecimalFieldCheck.java | 15 ++- .../checkers/fieldchecks/FieldCheck.java | 16 +--- .../fieldchecks/FloatAndDoubleFieldCheck.java | 18 ++-- .../fieldchecks/JpaLazyGetterFieldCheck.java | 16 ++-- .../fieldchecks/MutableStateFieldCheck.java | 10 +- .../NullPointerExceptionFieldCheck.java | 26 +++-- .../fieldchecks/ReflexivityFieldCheck.java | 28 +++--- .../fieldchecks/SignificantFieldCheck.java | 95 ++++++++++--------- .../fieldchecks/StringFieldCheck.java | 14 +-- .../fieldchecks/SymmetryFieldCheck.java | 8 +- .../fieldchecks/TransientFieldsCheck.java | 12 +-- .../fieldchecks/TransitivityFieldCheck.java | 6 +- .../internal/instantiation/FieldProbe.java | 68 +++++++++++++ .../instantiation/SubjectCreator.java | 26 ++++- .../internal/checkers/FieldInspectorTest.java | 72 -------------- 19 files changed, 247 insertions(+), 284 deletions(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java delete mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/checkers/FieldInspectorTest.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java index f3886e32e..f90e91961 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java @@ -1,60 +1,25 @@ package nl.jqno.equalsverifier.internal.checkers; import java.lang.reflect.Field; -import java.util.Set; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.FieldCheck; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; -import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; +import nl.jqno.equalsverifier.internal.util.Configuration; public class FieldInspector { - private final ClassAccessor classAccessor; - private final TypeTag typeTag; + private final Class type; + private final Configuration config; - public FieldInspector(ClassAccessor classAccessor, TypeTag typeTag) { - this.classAccessor = classAccessor; - this.typeTag = typeTag; + public FieldInspector(Class type, Configuration config) { + this.type = type; + this.config = config; } public void check(FieldCheck check) { - for (Field field : FieldIterable.of(classAccessor.getType())) { - ObjectAccessor reference = classAccessor.getRedAccessor(typeTag); - ObjectAccessor copy = classAccessor.getRedAccessor(typeTag); - FieldAccessor fieldAccessor = FieldAccessor.of(field); - - check.execute(reference, copy, fieldAccessor); - } - } - - public void checkWithNull( - boolean isNullWarningSuppressed, - boolean isZeroWarningSuppressed, - Set nonnullFields, - AnnotationCache annotationCache, - FieldCheck check - ) { - for (Field field : FieldIterable.of(classAccessor.getType())) { - ObjectAccessor reference = classAccessor.getDefaultValuesAccessor( - typeTag, - isNullWarningSuppressed, - isZeroWarningSuppressed, - nonnullFields, - annotationCache - ); - ObjectAccessor changed = classAccessor.getDefaultValuesAccessor( - typeTag, - isNullWarningSuppressed, - isZeroWarningSuppressed, - nonnullFields, - annotationCache - ); - FieldAccessor fieldAccessor = FieldAccessor.of(field); - - check.execute(reference, changed, fieldAccessor); + for (Field field : FieldIterable.of(type)) { + FieldProbe fieldProbe = FieldProbe.of(field, config); + check.execute(fieldProbe); } } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index 633e6b6fa..d277dfba7 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -4,7 +4,6 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.*; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; @@ -20,7 +19,6 @@ public class FieldsChecker implements Checker { private final MutableStateFieldCheck mutableStateFieldCheck; private final ReflexivityFieldCheck reflexivityFieldCheck; private final SignificantFieldCheck significantFieldCheck; - private final SignificantFieldCheck skippingSignificantFieldCheck; private final SymmetryFieldCheck symmetryFieldCheck; private final TransientFieldsCheck transientFieldsCheck; private final TransitivityFieldCheck transitivityFieldCheck; @@ -31,9 +29,8 @@ public class FieldsChecker implements Checker { public FieldsChecker(Configuration config) { this.config = config; - final PrefabValues prefabValues = config.getPrefabValues(); final TypeTag typeTag = config.getTypeTag(); - final SubjectCreator subjectCreator = new SubjectCreator<>(typeTag, prefabValues); + final SubjectCreator subjectCreator = new SubjectCreator<>(config); final String cachedHashCodeFieldName = config .getCachedHashCodeInitializer() @@ -48,9 +45,7 @@ public FieldsChecker(Configuration config) { new MutableStateFieldCheck<>(subjectCreator, isCachedHashCodeField); this.reflexivityFieldCheck = new ReflexivityFieldCheck<>(subjectCreator, config); this.significantFieldCheck = - new SignificantFieldCheck<>(config, isCachedHashCodeField, false); - this.skippingSignificantFieldCheck = - new SignificantFieldCheck<>(config, isCachedHashCodeField, true); + new SignificantFieldCheck<>(subjectCreator, config, isCachedHashCodeField); this.symmetryFieldCheck = new SymmetryFieldCheck<>(subjectCreator); this.transientFieldsCheck = new TransientFieldsCheck<>(subjectCreator, typeTag, config.getAnnotationCache()); @@ -69,7 +64,7 @@ public FieldsChecker(Configuration config) { @Override public void check() { ClassAccessor classAccessor = config.getClassAccessor(); - FieldInspector inspector = new FieldInspector<>(classAccessor, config.getTypeTag()); + FieldInspector inspector = new FieldInspector<>(classAccessor.getType(), config); if (!classAccessor.isEqualsInheritedFromObject()) { inspector.check(arrayFieldCheck); @@ -90,14 +85,6 @@ public void check() { inspector.check(transitivityFieldCheck); inspector.check(stringFieldCheck); - inspector.checkWithNull( - config.getWarningsToSuppress().contains(Warning.NULL_FIELDS), - config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS), - config.getNonnullFields(), - config.getAnnotationCache(), - skippingSignificantFieldCheck - ); - if (!config.getWarningsToSuppress().contains(Warning.BIGDECIMAL_EQUALITY)) { inspector.check(bigDecimalFieldCheck); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java index 5da8f478e..bb9cda882 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java @@ -3,7 +3,6 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.NullPointerExceptionFieldCheck; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; public class NullChecker implements Checker { @@ -20,13 +19,7 @@ public void check() { return; } - ClassAccessor classAccessor = config.getClassAccessor(); - FieldInspector inspector = new FieldInspector<>(classAccessor, config.getTypeTag()); - inspector.check( - new NullPointerExceptionFieldCheck<>( - new SubjectCreator<>(config.getTypeTag(), config.getPrefabValues()), - config - ) - ); + FieldInspector inspector = new FieldInspector<>(config.getType(), config); + inspector.check(new NullPointerExceptionFieldCheck<>(new SubjectCreator<>(config), config)); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java index 364d15218..7e3c9bd6e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java @@ -4,6 +4,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; @@ -24,30 +25,27 @@ public ArrayFieldCheck( } @Override - public void execute(Field changedField) { - Class arrayType = changedField.getType(); + public void execute(FieldProbe fieldProbe) { + Class arrayType = fieldProbe.getType(); if (!arrayType.isArray()) { return; } - FieldAccessor fieldAccessor = FieldAccessor.of(changedField); + FieldAccessor fieldAccessor = FieldAccessor.of(fieldProbe.getField()); if (!fieldAccessor.canBeModifiedReflectively()) { return; } - String fieldName = changedField.getName(); T reference = subjectCreator.plain(); - T changed = replaceInnermostArrayValue(reference, changedField); + T changed = replaceInnermostArrayValue(reference, fieldProbe.getField()); if (arrayType.getComponentType().isArray()) { - assertDeep(fieldName, reference, changed); + assertDeep(fieldProbe.getName(), reference, changed); } else { - assertArray(fieldName, reference, changed); + assertArray(fieldProbe.getName(), reference, changed); } } private T replaceInnermostArrayValue(T reference, Field field) { - // Object newArray = arrayCopy(accessor.getField(field)); - // return accessor.withFieldSetTo(field, newArray); ObjectAccessor objectAccessor = ObjectAccessor.of(reference); Object newArray = arrayCopy(objectAccessor.getField(field)); return subjectCreator.withFieldSetTo(field, newArray); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java index ee1e2b4da..92902567a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java @@ -6,8 +6,8 @@ import java.math.BigDecimal; import java.math.RoundingMode; import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -27,21 +27,20 @@ public BigDecimalFieldCheck( } @Override - public void execute(Field changedField) { - if (BigDecimal.class.equals(changedField.getType())) { + public void execute(FieldProbe fieldProbe) { + if (BigDecimal.class.equals(fieldProbe.getType())) { T left = subjectCreator.plain(); - ObjectAccessor acc = ObjectAccessor.of(left); - BigDecimal referenceValue = (BigDecimal) acc.getField(changedField); + BigDecimal referenceValue = (BigDecimal) fieldProbe.getValue(left); BigDecimal changedValue = referenceValue.setScale( referenceValue.scale() + 1, RoundingMode.UNNECESSARY ); - T right = subjectCreator.withFieldSetTo(changedField, changedValue); + T right = subjectCreator.withFieldSetTo(fieldProbe.getField(), changedValue); - checkEquals(changedField, referenceValue, changedValue, left, right); - checkHashCode(changedField, referenceValue, changedValue, left, right); + checkEquals(fieldProbe.getField(), referenceValue, changedValue, left, right); + checkHashCode(fieldProbe.getField(), referenceValue, changedValue, left, right); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java index d896d9972..0a5b060f8 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java @@ -1,18 +1,8 @@ package nl.jqno.equalsverifier.internal.checkers.fieldchecks; -import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -// @FunctionalInterface +@FunctionalInterface public interface FieldCheck { - default void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - execute(fieldAccessor.getField()); - } - - default void execute(Field changedField) {} + void execute(FieldProbe fieldProbe); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java index 821876edd..3caba6eeb 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java @@ -2,7 +2,7 @@ import static nl.jqno.equalsverifier.internal.util.Assert.assertEquals; -import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -15,27 +15,27 @@ public FloatAndDoubleFieldCheck(SubjectCreator subjectCreator) { } @Override - public void execute(Field changedField) { - Class type = changedField.getType(); + public void execute(FieldProbe fieldProbe) { + Class type = fieldProbe.getType(); if (isFloat(type)) { - T reference = subjectCreator.withFieldSetTo(changedField, Float.NaN); - T copy = subjectCreator.withFieldSetTo(changedField, Float.NaN); + T reference = subjectCreator.withFieldSetTo(fieldProbe.getField(), Float.NaN); + T copy = subjectCreator.withFieldSetTo(fieldProbe.getField(), Float.NaN); assertEquals( Formatter.of( "Float: equals doesn't use Float.compare for field %%.", - changedField.getName() + fieldProbe.getName() ), reference, copy ); } if (isDouble(type)) { - T reference = subjectCreator.withFieldSetTo(changedField, Double.NaN); - T copy = subjectCreator.withFieldSetTo(changedField, Double.NaN); + T reference = subjectCreator.withFieldSetTo(fieldProbe.getField(), Double.NaN); + T copy = subjectCreator.withFieldSetTo(fieldProbe.getField(), Double.NaN); assertEquals( Formatter.of( "Double: equals doesn't use Double.compare for field %%.", - changedField.getName() + fieldProbe.getName() ), reference, copy diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index fe9bb4628..b93dc5dec 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -9,10 +9,12 @@ import java.util.function.Function; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.*; +import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; +import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -39,12 +41,12 @@ public JpaLazyGetterFieldCheck(SubjectCreator subjectCreator, Configuration subjectCreator, Configuration } @Override - public void execute(Field changedField) { + public void execute(FieldProbe fieldProbe) { if (warningsToSuppress.contains(Warning.IDENTICAL_COPY_FOR_VERSIONED_ENTITY)) { return; } checkReferenceReflexivity(); - checkValueReflexivity(changedField); - checkNullReflexivity(changedField); + checkValueReflexivity(fieldProbe.getField()); + checkNullReflexivity(fieldProbe); } private void checkReferenceReflexivity() { @@ -53,15 +54,15 @@ private void checkReferenceReflexivity() { checkReflexivityFor(left, right); } - private void checkValueReflexivity(Field changedField) { - Class fieldType = changedField.getType(); + private void checkValueReflexivity(Field field) { + Class fieldType = field.getType(); if (warningsToSuppress.contains(Warning.REFERENCE_EQUALITY)) { return; } if (fieldType.equals(Object.class) || fieldType.isInterface()) { return; } - if (FieldAccessor.of(changedField).fieldIsStatic()) { + if (FieldAccessor.of(field).fieldIsStatic()) { return; } ClassAccessor fieldTypeAccessor = ClassAccessor.of(fieldType, prefabValues); @@ -73,26 +74,25 @@ private void checkValueReflexivity(Field changedField) { return; } - TypeTag tag = TypeTag.of(changedField, typeTag); - Object left = subjectCreator.withFieldSetTo(changedField, prefabValues.giveRed(tag)); - Object right = subjectCreator.withFieldSetTo(changedField, prefabValues.giveRedCopy(tag)); + TypeTag tag = TypeTag.of(field, typeTag); + Object left = subjectCreator.withFieldSetTo(field, prefabValues.giveRed(tag)); + Object right = subjectCreator.withFieldSetTo(field, prefabValues.giveRedCopy(tag)); Formatter f = Formatter.of( "Reflexivity: == used instead of .equals() on field: %%" + "\nIf this is intentional, consider suppressing Warning.%%", - changedField.getName(), + field.getName(), Warning.REFERENCE_EQUALITY.toString() ); assertEquals(f, left, right); } - private void checkNullReflexivity(Field changedField) { - FieldAccessor fieldAccessor = FieldAccessor.of(changedField); - if (fieldAccessor.fieldIsPrimitive() && warningsToSuppress.contains(Warning.ZERO_FIELDS)) { + private void checkNullReflexivity(FieldProbe fieldProbe) { + Field field = fieldProbe.getField(); + if (fieldProbe.fieldIsPrimitive() && warningsToSuppress.contains(Warning.ZERO_FIELDS)) { return; } - Field field = fieldAccessor.getField(); boolean nullWarningIsSuppressed = warningsToSuppress.contains(Warning.NULL_FIELDS); boolean fieldIsNonNull = NonnullAnnotationVerifier.fieldIsNonnull(field, annotationCache); boolean fieldIsMentionedExplicitly = nonnullFields.contains(field.getName()); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java index 3199b058b..2192cd466 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java @@ -8,65 +8,73 @@ import java.util.Set; import java.util.function.Predicate; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; -import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; -import nl.jqno.equalsverifier.internal.util.Configuration; -import nl.jqno.equalsverifier.internal.util.Formatter; -import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; +import nl.jqno.equalsverifier.internal.util.*; public class SignificantFieldCheck implements FieldCheck { + private final SubjectCreator subjectCreator; private final Class type; - private final TypeTag typeTag; - private final PrefabValues prefabValues; private final EnumSet warningsToSuppress; private final Set ignoredFields; private final CachedHashCodeInitializer cachedHashCodeInitializer; private final AnnotationCache annotationCache; private final Predicate isCachedHashCodeField; - private final boolean skipCertainTestsThatDontMatterWhenValuesAreNull; public SignificantFieldCheck( + SubjectCreator subjectCreator, Configuration config, - Predicate isCachedHashCodeField, - boolean skipCertainTestsThatDontMatterWhenValuesAreNull + Predicate isCachedHashCodeField ) { + this.subjectCreator = subjectCreator; this.type = config.getType(); - this.typeTag = config.getTypeTag(); - this.prefabValues = config.getPrefabValues(); this.warningsToSuppress = config.getWarningsToSuppress(); this.ignoredFields = config.getIgnoredFields(); this.cachedHashCodeInitializer = config.getCachedHashCodeInitializer(); this.annotationCache = config.getAnnotationCache(); this.isCachedHashCodeField = isCachedHashCodeField; - this.skipCertainTestsThatDontMatterWhenValuesAreNull = - skipCertainTestsThatDontMatterWhenValuesAreNull; } @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { + public void execute(FieldProbe fieldProbe) { + Field changedField = fieldProbe.getField(); + FieldAccessor fieldAccessor = FieldAccessor.of(changedField); if (isCachedHashCodeField.test(fieldAccessor)) { return; } - Field field = fieldAccessor.getField(); - T reference = referenceAccessor.get(); - T copy = copyAccessor.get(); - String fieldName = field.getName(); - - boolean equalToItself = reference.equals(copy); + checkValues( + subjectCreator.plain(), + subjectCreator.plain(), + subjectCreator.withFieldChanged(fieldProbe.getField()), + fieldProbe, + false + ); + if (fieldProbe.canBeDefault()) { + checkValues( + subjectCreator.withAllFieldsDefaulted(), + subjectCreator.withAllFieldsDefaulted(), + subjectCreator.withAllFieldsDefaultedExcept(fieldProbe.getField()), + fieldProbe, + true + ); + } + } - T changed = copyAccessor.withChangedField(field, prefabValues, typeTag).get(); + private void checkValues( + T reference, + T copy, + T changed, + FieldProbe probe, + boolean testWithNull + ) { + String fieldName = probe.getField().getName(); + boolean equalToItself = reference.equals(copy); boolean equalsChanged = !reference.equals(changed); boolean hashCodeChanged = cachedHashCodeInitializer.getInitializedHashCode(reference) != @@ -77,17 +85,17 @@ public void execute( hashCodeChanged, reference, changed, - fieldName + fieldName, + testWithNull ); assertFieldShouldBeIgnored( equalToItself, equalsChanged, - referenceAccessor.get(), - fieldAccessor, - fieldName + reference, + FieldAccessor.of(probe.getField()), + fieldName, + testWithNull ); - - referenceAccessor.withChangedField(field, prefabValues, typeTag); } private void assertEqualsAndHashCodeRelyOnSameFields( @@ -95,12 +103,12 @@ private void assertEqualsAndHashCodeRelyOnSameFields( boolean hashCodeChanged, T reference, T changed, - String fieldName + String fieldName, + boolean testWithNull ) { if (equalsChanged != hashCodeChanged) { boolean skipEqualsHasMoreThanHashCodeTest = - warningsToSuppress.contains(Warning.STRICT_HASHCODE) || - skipCertainTestsThatDontMatterWhenValuesAreNull; + warningsToSuppress.contains(Warning.STRICT_HASHCODE) || testWithNull; if (!skipEqualsHasMoreThanHashCodeTest) { Formatter formatter = Formatter.of( "Significant fields: equals relies on %%, but hashCode does not." + @@ -129,7 +137,8 @@ private void assertFieldShouldBeIgnored( boolean equalsChanged, T object, FieldAccessor fieldAccessor, - String fieldName + String fieldName, + boolean testWithNull ) { if (!shouldAllFieldsBeUsed(fieldAccessor) || !isFieldEligible(fieldAccessor)) { return; @@ -165,7 +174,8 @@ private void assertFieldShouldBeIgnored( equalsChanged, fieldShouldBeIgnored, thisFieldIsMarkedAsId, - anotherFieldIsMarkedAsId + anotherFieldIsMarkedAsId, + testWithNull ); } @@ -236,7 +246,8 @@ private void assertFieldShouldNotBeUsed( boolean equalsChanged, boolean fieldShouldBeIgnored, boolean thisFieldIsMarkedAsId, - boolean anotherFieldIsMarkedAsId + boolean anotherFieldIsMarkedAsId, + boolean testWithNull ) { final String message; if (thisFieldIsMarkedAsId) { @@ -255,9 +266,7 @@ private void assertFieldShouldNotBeUsed( assertTrue( Formatter.of(message, fieldName), - !fieldShouldBeIgnored || - !equalsChanged || - skipCertainTestsThatDontMatterWhenValuesAreNull + !fieldShouldBeIgnored || !equalsChanged || testWithNull ); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java index 51fa87a40..d692f92a2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java @@ -3,8 +3,8 @@ import static nl.jqno.equalsverifier.internal.util.Assert.fail; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; @@ -39,18 +39,18 @@ public StringFieldCheck( value = "DM_CONVERT_CASE", justification = "String prefab values are probably not localized." ) - public void execute(Field changedField) { + public void execute(FieldProbe fieldProbe) { if ( - String.class.equals(changedField.getType()) && - !FieldAccessor.of(changedField).fieldIsStatic() + String.class.equals(fieldProbe.getType()) && + !FieldAccessor.of(fieldProbe.getField()).fieldIsStatic() ) { String red = prefabValues.giveRed(new TypeTag(String.class)); final T reference; final T copy; try { - reference = subjectCreator.withFieldSetTo(changedField, red.toLowerCase()); - copy = subjectCreator.withFieldSetTo(changedField, red.toUpperCase()); + reference = subjectCreator.withFieldSetTo(fieldProbe.getField(), red.toLowerCase()); + copy = subjectCreator.withFieldSetTo(fieldProbe.getField(), red.toUpperCase()); } catch (ReflectionException ignored) { // Differently-cased String is not allowed, so cannot cause problems either. return; @@ -67,7 +67,7 @@ public void execute(Field changedField) { ERROR_DOC_TITLE + ": class uses equalsIgnoreCase to compare String field %%, but hashCode is case-sensitive." + " Use toUpperCase() to determine the hashCode.", - changedField.getName() + fieldProbe.getName() ) ); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java index 2cc8a3916..dabfaf02f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java @@ -3,7 +3,7 @@ import static nl.jqno.equalsverifier.internal.util.Assert.assertTrue; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -20,11 +20,11 @@ public SymmetryFieldCheck(SubjectCreator subjectCreator) { } @Override - public void execute(Field changedField) { + public void execute(FieldProbe fieldProbe) { T left = subjectCreator.plain(); T right = subjectCreator.plain(); - T changedLeft = subjectCreator.withFieldChanged(changedField); - T changedRight = subjectCreator.withFieldChanged(changedField); + T changedLeft = subjectCreator.withFieldChanged(fieldProbe.getField()); + T changedRight = subjectCreator.withFieldChanged(fieldProbe.getField()); checkSymmetry(left, right); checkSymmetry(left, changedRight); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java index b3faa02ea..1b03c7343 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java @@ -3,7 +3,7 @@ import static nl.jqno.equalsverifier.internal.util.Assert.fail; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; @@ -29,23 +29,23 @@ public TransientFieldsCheck( } @Override - public void execute(Field changedField) { + public void execute(FieldProbe fieldProbe) { T reference = subjectCreator.plain(); - T changed = subjectCreator.withFieldChanged(changedField); + T changed = subjectCreator.withFieldChanged(fieldProbe.getField()); boolean equalsChanged = !reference.equals(changed); boolean hasAnnotation = annotationCache.hasFieldAnnotation( typeTag.getType(), - changedField.getName(), + fieldProbe.getName(), SupportedAnnotations.TRANSIENT ); boolean fieldIsTransient = - FieldAccessor.of(changedField).fieldIsTransient() || hasAnnotation; + FieldAccessor.of(fieldProbe.getField()).fieldIsTransient() || hasAnnotation; if (equalsChanged && fieldIsTransient) { fail( Formatter.of( "Transient field %% should not be included in equals/hashCode contract.", - changedField.getName() + fieldProbe.getName() ) ); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java index 7edbf3691..6b01d3970 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java @@ -3,7 +3,7 @@ import static nl.jqno.equalsverifier.internal.util.Assert.fail; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -20,9 +20,9 @@ public TransitivityFieldCheck(SubjectCreator subjectCreator) { } @Override - public void execute(Field changedField) { + public void execute(FieldProbe fieldProbe) { T a1 = subjectCreator.plain(); - T b1 = subjectCreator.withFieldChanged(changedField); + T b1 = subjectCreator.withFieldChanged(fieldProbe.getField()); T b2 = subjectCreator.withAllFieldsChanged(); boolean x = a1.equals(b1); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java new file mode 100644 index 000000000..6ed788778 --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java @@ -0,0 +1,68 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.lang.reflect.Field; +import java.util.Set; +import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; +import nl.jqno.equalsverifier.internal.reflection.annotations.NonnullAnnotationVerifier; +import nl.jqno.equalsverifier.internal.util.Configuration; + +public final class FieldProbe { + + private final Field field; + private final boolean isWarningZeroSuppressed; + private final boolean isWarningNullSuppressed; + private final Set nonnullFields; + private final AnnotationCache annotationCache; + + private FieldProbe(Field field, Configuration config) { + this.field = field; + this.isWarningZeroSuppressed = config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS); + this.isWarningNullSuppressed = config.getWarningsToSuppress().contains(Warning.NULL_FIELDS); + this.nonnullFields = config.getNonnullFields(); + this.annotationCache = config.getAnnotationCache(); + } + + public static FieldProbe of(Field field, Configuration config) { + return new FieldProbe(field, config); + } + + @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "Can't defensively copy a Field.") + public Field getField() { + return field; + } + + @SuppressFBWarnings( + value = "DP_DO_INSIDE_DO_PRIVILEGED", + justification = "Only called in test code, not production." + ) + public Object getValue(Object object) { + field.setAccessible(true); + return rethrow(() -> field.get(object)); + } + + public Class getType() { + return field.getType(); + } + + public String getName() { + return field.getName(); + } + + public boolean fieldIsPrimitive() { + return getType().isPrimitive(); + } + + public boolean canBeDefault() { + if (fieldIsPrimitive()) { + return !isWarningZeroSuppressed; + } + + boolean isAnnotated = NonnullAnnotationVerifier.fieldIsNonnull(field, annotationCache); + boolean isMentionedExplicitly = nonnullFields.contains(field.getName()); + return !isWarningNullSuppressed && !isAnnotated && !isMentionedExplicitly; + } +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index cf880bd20..380ceaebc 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -2,24 +2,28 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; +import java.util.function.BiFunction; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.util.Configuration; public class SubjectCreator { private final TypeTag typeTag; private final PrefabValues prefabValues; + private final Configuration config; @SuppressFBWarnings( value = "EI_EXPOSE_REP2", justification = "PrefabValues is inherently mutable." ) - public SubjectCreator(TypeTag typeTag, PrefabValues prefabValues) { - this.typeTag = typeTag; - this.prefabValues = prefabValues; + public SubjectCreator(Configuration config) { + this.typeTag = config.getTypeTag(); + this.prefabValues = config.getPrefabValues(); + this.config = config; } public T plain() { @@ -30,6 +34,16 @@ public T withFieldDefaulted(Field field) { return createSubject().withDefaultedField(field).get(); } + public T withAllFieldsDefaulted() { + return withAllFields((acc, f) -> + FieldProbe.of(f, config).canBeDefault() ? acc.withDefaultedField(f) : acc + ); + } + + public T withAllFieldsDefaultedExcept(Field field) { + return withAllFields((acc, f) -> f.equals(field) ? acc : acc.withDefaultedField(f)); + } + public T withFieldSetTo(Field field, Object value) { return createSubject().withFieldSetTo(field, value).get(); } @@ -39,9 +53,13 @@ public T withFieldChanged(Field field) { } public T withAllFieldsChanged() { + return withAllFields((acc, f) -> acc.withChangedField(f, prefabValues, typeTag)); + } + + private T withAllFields(BiFunction, Field, ObjectAccessor> modifier) { ObjectAccessor accessor = createSubject(); for (Field f : FieldIterable.of(typeTag.getType())) { - accessor = accessor.withChangedField(f, prefabValues, typeTag); + accessor = modifier.apply(accessor, f); } return accessor.get(); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/checkers/FieldInspectorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/checkers/FieldInspectorTest.java deleted file mode 100644 index 1b0454a41..000000000 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/checkers/FieldInspectorTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package nl.jqno.equalsverifier.internal.checkers; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.lang.reflect.Field; -import java.util.HashSet; -import java.util.Set; -import nl.jqno.equalsverifier.internal.checkers.fieldchecks.FieldCheck; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; -import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; -import nl.jqno.equalsverifier.testhelpers.FactoryCacheFactory; -import nl.jqno.equalsverifier.testhelpers.types.Point; -import org.junit.jupiter.api.Test; - -public class FieldInspectorTest { - - private final PrefabValues prefabValues = new PrefabValues( - FactoryCacheFactory.withPrimitiveFactories() - ); - private final ClassAccessor accessor = ClassAccessor.of(Point.class, prefabValues); - - @Test - public void objectsAreReset_whenEachIterationBegins() { - FieldInspector inspector = new FieldInspector<>(accessor, TypeTag.NULL); - - inspector.check(new ResetObjectForEachIterationCheck<>()); - } - - @Test - public void objectsAreReset_whenEachIterationBegins_givenNullObjects() { - FieldInspector inspector = new FieldInspector<>(accessor, TypeTag.NULL); - Set nullFields = new HashSet<>(); - AnnotationCache annotationCache = new AnnotationCache(); - - inspector.checkWithNull( - false, - false, - nullFields, - annotationCache, - new ResetObjectForEachIterationCheck<>() - ); - } - - private final class ResetObjectForEachIterationCheck implements FieldCheck { - - private Object originalReference; - private Object originalChanged; - - @Override - public void execute( - ObjectAccessor referenceAccessor, - ObjectAccessor copyAccessor, - FieldAccessor fieldAccessor - ) { - if (originalReference == null) { - originalReference = referenceAccessor.copy(); - originalChanged = copyAccessor.copy(); - } else { - assertEquals(originalReference, referenceAccessor.get()); - assertEquals(originalChanged, copyAccessor.get()); - } - Field field = fieldAccessor.getField(); - - referenceAccessor.withChangedField(field, prefabValues, TypeTag.NULL); - copyAccessor.withChangedField(field, prefabValues, TypeTag.NULL); - } - } -} From fe9616200553b10960ee134576834bd75f2ef7d5 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 30 Aug 2024 12:11:08 +0200 Subject: [PATCH 07/74] Introduces InstanceCreator in several FieldChecks and Checkers --- .../MapEntryHashCodeRequirementChecker.java | 15 ++++++--------- .../fieldchecks/JpaLazyGetterFieldCheck.java | 18 +++++++++--------- ...ationStrategy.java => InstanceCreator.java} | 2 +- ...rategy.java => VintageInstanceCreator.java} | 4 ++-- .../internal/util/Configuration.java | 8 ++++++++ 5 files changed, 26 insertions(+), 21 deletions(-) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/{FieldInstantiationStrategy.java => InstanceCreator.java} (82%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/{VintageFieldInstantiationStrategy.java => VintageInstanceCreator.java} (79%) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java index 23ba70a04..afc286579 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java @@ -4,30 +4,27 @@ import java.util.Map; import java.util.Objects; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; -import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Formatter; public class MapEntryHashCodeRequirementChecker implements Checker { private final Configuration config; - private final ClassAccessor classAccessor; - private final CachedHashCodeInitializer cachedHashCodeInitializer; public MapEntryHashCodeRequirementChecker(Configuration config) { this.config = config; - this.classAccessor = config.getClassAccessor(); - this.cachedHashCodeInitializer = config.getCachedHashCodeInitializer(); } @Override public void check() { - if (Map.Entry.class.isAssignableFrom(classAccessor.getType())) { - Map.Entry e = (Map.Entry) classAccessor.getRedObject(config.getTypeTag()); + if (Map.Entry.class.isAssignableFrom(config.getType())) { + Map.Entry e = (Map.Entry) config + .getInstanceCreator() + .instantiate(config.getTypeTag()) + .getRed(); int expectedHashCode = Objects.hashCode(e.getKey()) ^ Objects.hashCode(e.getValue()); - int actualHashCode = cachedHashCodeInitializer.getInitializedHashCode(e); + int actualHashCode = config.getCachedHashCodeInitializer().getInitializedHashCode(e); Formatter f = Formatter.of( "Map.Entry: hashCode for\n %%\nshould be %% but was %%.\n" + diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index b93dc5dec..4dd7000eb 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -10,11 +10,12 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; +import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.Instantiator; +import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -23,18 +24,18 @@ public class JpaLazyGetterFieldCheck implements FieldCheck { private final SubjectCreator subjectCreator; + private final InstanceCreator instanceCreator; private final Class type; private final ClassAccessor accessor; - private final PrefabValues prefabValues; private final AnnotationCache annotationCache; private final Function fieldnameToGetter; private final boolean strictHashcode; public JpaLazyGetterFieldCheck(SubjectCreator subjectCreator, Configuration config) { this.subjectCreator = subjectCreator; + this.instanceCreator = config.getInstanceCreator(); this.type = config.getType(); this.accessor = config.getClassAccessor(); - this.prefabValues = config.getPrefabValues(); this.annotationCache = config.getAnnotationCache(); this.fieldnameToGetter = config.getFieldnameToGetter(); this.strictHashcode = config.getWarningsToSuppress().contains(Warning.STRICT_HASHCODE); @@ -54,10 +55,10 @@ public void execute(FieldProbe fieldProbe) { } assertEntity(fieldName, "equals", getterName, accessor.hasMethod(getterName)); - ClassAccessor subAccessor = throwingGetterAccessor(getterName); - T red1 = subAccessor.getRedObject(TypeTag.NULL); - T red2 = subAccessor.getRedObject(TypeTag.NULL); + Class sub = throwingGetterCreator(getterName); + T red1 = instanceCreator.instantiate(new TypeTag(sub)).getRed(); + T red2 = ObjectAccessor.of(red1, sub).copy(); boolean equalsExceptionCaught = false; try { @@ -99,8 +100,8 @@ private boolean fieldIsLazy(String fieldName) { ); } - private ClassAccessor throwingGetterAccessor(String getterName) { - Class sub = Instantiator.giveDynamicSubclass( + private Class throwingGetterCreator(String getterName) { + return Instantiator.giveDynamicSubclass( type, getterName, builder -> @@ -108,7 +109,6 @@ private ClassAccessor throwingGetterAccessor(String getterName) { .method(named(getterName)) .intercept(throwing(EqualsVerifierInternalBugException.class)) ); - return ClassAccessor.of(sub, prefabValues); } private void assertEntity( diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldInstantiationStrategy.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java similarity index 82% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldInstantiationStrategy.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java index 9b3676f5e..a6ccea506 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldInstantiationStrategy.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java @@ -3,6 +3,6 @@ import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -public interface FieldInstantiationStrategy { +public interface InstanceCreator { Tuple instantiate(TypeTag tag); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageFieldInstantiationStrategy.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java similarity index 79% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageFieldInstantiationStrategy.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java index 4bb1ee37d..a950028f6 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageFieldInstantiationStrategy.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java @@ -5,7 +5,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -public class VintageFieldInstantiationStrategy implements FieldInstantiationStrategy { +public class VintageInstanceCreator implements InstanceCreator { private final PrefabValues prefabValues; @@ -13,7 +13,7 @@ public class VintageFieldInstantiationStrategy implements FieldInstantiationStra value = "EI_EXPOSE_REP2", justification = "PrefabValues is inherently mutable." ) - public VintageFieldInstantiationStrategy(PrefabValues prefabValues) { + public VintageInstanceCreator(PrefabValues prefabValues) { this.prefabValues = prefabValues; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index 2924db52c..333ae0646 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -10,6 +10,8 @@ import java.util.function.Function; import java.util.stream.Collectors; import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; +import nl.jqno.equalsverifier.internal.instantiation.VintageInstanceCreator; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; @@ -39,6 +41,7 @@ public final class Configuration { private final ClassAccessor classAccessor; private final AnnotationCache annotationCache; private final Set ignoredFields; + private final InstanceCreator instanceCreator; private final List equalExamples; private final List unequalExamples; @@ -76,6 +79,7 @@ private Configuration( this.fieldnameToGetter = fieldnameToGetter; this.equalExamples = equalExamples; this.unequalExamples = unequalExamples; + this.instanceCreator = new VintageInstanceCreator(prefabValues); } public static Configuration build( @@ -285,4 +289,8 @@ public AnnotationCache getAnnotationCache() { public Set getIgnoredFields() { return Collections.unmodifiableSet(ignoredFields); } + + public InstanceCreator getInstanceCreator() { + return instanceCreator; + } } From 88396617905b6443a144437b2109c68a04dfd0d4 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 30 Aug 2024 12:36:15 +0200 Subject: [PATCH 08/74] Refactors SubjectCreator into Configuration --- .../internal/checkers/FieldsChecker.java | 9 ++++----- .../equalsverifier/internal/checkers/NullChecker.java | 3 +-- .../checkers/fieldchecks/JpaLazyGetterFieldCheck.java | 4 ++-- .../fieldchecks/NullPointerExceptionFieldCheck.java | 9 +++------ .../checkers/fieldchecks/ReflexivityFieldCheck.java | 4 ++-- .../checkers/fieldchecks/SignificantFieldCheck.java | 9 +++++---- .../internal/instantiation/SubjectCreator.java | 10 ++++------ .../equalsverifier/internal/util/Configuration.java | 7 +++++++ 8 files changed, 28 insertions(+), 27 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index d277dfba7..f99546439 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -30,7 +30,7 @@ public FieldsChecker(Configuration config) { this.config = config; final TypeTag typeTag = config.getTypeTag(); - final SubjectCreator subjectCreator = new SubjectCreator<>(config); + final SubjectCreator subjectCreator = config.getSubjectCreator(); final String cachedHashCodeFieldName = config .getCachedHashCodeInitializer() @@ -43,9 +43,8 @@ public FieldsChecker(Configuration config) { this.floatAndDoubleFieldCheck = new FloatAndDoubleFieldCheck<>(subjectCreator); this.mutableStateFieldCheck = new MutableStateFieldCheck<>(subjectCreator, isCachedHashCodeField); - this.reflexivityFieldCheck = new ReflexivityFieldCheck<>(subjectCreator, config); - this.significantFieldCheck = - new SignificantFieldCheck<>(subjectCreator, config, isCachedHashCodeField); + this.reflexivityFieldCheck = new ReflexivityFieldCheck<>(config); + this.significantFieldCheck = new SignificantFieldCheck<>(config, isCachedHashCodeField); this.symmetryFieldCheck = new SymmetryFieldCheck<>(subjectCreator); this.transientFieldsCheck = new TransientFieldsCheck<>(subjectCreator, typeTag, config.getAnnotationCache()); @@ -58,7 +57,7 @@ public FieldsChecker(Configuration config) { ); this.bigDecimalFieldCheck = new BigDecimalFieldCheck<>(subjectCreator, config.getCachedHashCodeInitializer()); - this.jpaLazyGetterFieldCheck = new JpaLazyGetterFieldCheck<>(subjectCreator, config); + this.jpaLazyGetterFieldCheck = new JpaLazyGetterFieldCheck<>(config); } @Override diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java index bb9cda882..e2887045e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java @@ -2,7 +2,6 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.NullPointerExceptionFieldCheck; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Configuration; public class NullChecker implements Checker { @@ -20,6 +19,6 @@ public void check() { } FieldInspector inspector = new FieldInspector<>(config.getType(), config); - inspector.check(new NullPointerExceptionFieldCheck<>(new SubjectCreator<>(config), config)); + inspector.check(new NullPointerExceptionFieldCheck<>(config)); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index 4dd7000eb..8ef79488a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -31,8 +31,8 @@ public class JpaLazyGetterFieldCheck implements FieldCheck { private final Function fieldnameToGetter; private final boolean strictHashcode; - public JpaLazyGetterFieldCheck(SubjectCreator subjectCreator, Configuration config) { - this.subjectCreator = subjectCreator; + public JpaLazyGetterFieldCheck(Configuration config) { + this.subjectCreator = config.getSubjectCreator(); this.instanceCreator = config.getInstanceCreator(); this.type = config.getType(); this.accessor = config.getClassAccessor(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java index 4783364de..d541b74de 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java @@ -19,15 +19,12 @@ ) public class NullPointerExceptionFieldCheck implements FieldCheck { - private final SubjectCreator subjectCreator; private final Configuration config; + private final SubjectCreator subjectCreator; - public NullPointerExceptionFieldCheck( - SubjectCreator subjectCreator, - Configuration config - ) { - this.subjectCreator = subjectCreator; + public NullPointerExceptionFieldCheck(Configuration config) { this.config = config; + this.subjectCreator = config.getSubjectCreator(); } @Override diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index 492994d4d..fe0baf063 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -28,8 +28,8 @@ public class ReflexivityFieldCheck implements FieldCheck { private final Set nonnullFields; private final AnnotationCache annotationCache; - public ReflexivityFieldCheck(SubjectCreator subjectCreator, Configuration config) { - this.subjectCreator = subjectCreator; + public ReflexivityFieldCheck(Configuration config) { + this.subjectCreator = config.getSubjectCreator(); this.typeTag = config.getTypeTag(); this.prefabValues = config.getPrefabValues(); this.warningsToSuppress = config.getWarningsToSuppress(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java index 2192cd466..fe978635b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java @@ -17,6 +17,7 @@ public class SignificantFieldCheck implements FieldCheck { + private final Configuration config; private final SubjectCreator subjectCreator; private final Class type; private final EnumSet warningsToSuppress; @@ -26,11 +27,11 @@ public class SignificantFieldCheck implements FieldCheck { private final Predicate isCachedHashCodeField; public SignificantFieldCheck( - SubjectCreator subjectCreator, Configuration config, Predicate isCachedHashCodeField ) { - this.subjectCreator = subjectCreator; + this.config = config; + this.subjectCreator = config.getSubjectCreator(); this.type = config.getType(); this.warningsToSuppress = config.getWarningsToSuppress(); this.ignoredFields = config.getIgnoredFields(); @@ -56,8 +57,8 @@ public void execute(FieldProbe fieldProbe) { ); if (fieldProbe.canBeDefault()) { checkValues( - subjectCreator.withAllFieldsDefaulted(), - subjectCreator.withAllFieldsDefaulted(), + subjectCreator.withAllFieldsDefaulted(config), + subjectCreator.withAllFieldsDefaulted(config), subjectCreator.withAllFieldsDefaultedExcept(fieldProbe.getField()), fieldProbe, true diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index 380ceaebc..2e0ba1b24 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -14,16 +14,14 @@ public class SubjectCreator { private final TypeTag typeTag; private final PrefabValues prefabValues; - private final Configuration config; @SuppressFBWarnings( value = "EI_EXPOSE_REP2", justification = "PrefabValues is inherently mutable." ) - public SubjectCreator(Configuration config) { - this.typeTag = config.getTypeTag(); - this.prefabValues = config.getPrefabValues(); - this.config = config; + public SubjectCreator(TypeTag typeTag, PrefabValues prefabValues) { + this.typeTag = typeTag; + this.prefabValues = prefabValues; } public T plain() { @@ -34,7 +32,7 @@ public T withFieldDefaulted(Field field) { return createSubject().withDefaultedField(field).get(); } - public T withAllFieldsDefaulted() { + public T withAllFieldsDefaulted(Configuration config) { return withAllFields((acc, f) -> FieldProbe.of(f, config).canBeDefault() ? acc.withDefaultedField(f) : acc ); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index 333ae0646..9253dde70 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -11,6 +11,7 @@ import java.util.stream.Collectors; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.instantiation.VintageInstanceCreator; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; @@ -41,6 +42,7 @@ public final class Configuration { private final ClassAccessor classAccessor; private final AnnotationCache annotationCache; private final Set ignoredFields; + private final SubjectCreator subjectCreator; private final InstanceCreator instanceCreator; private final List equalExamples; @@ -80,6 +82,7 @@ private Configuration( this.equalExamples = equalExamples; this.unequalExamples = unequalExamples; this.instanceCreator = new VintageInstanceCreator(prefabValues); + this.subjectCreator = new SubjectCreator<>(typeTag, prefabValues); } public static Configuration build( @@ -290,6 +293,10 @@ public Set getIgnoredFields() { return Collections.unmodifiableSet(ignoredFields); } + public SubjectCreator getSubjectCreator() { + return subjectCreator; + } + public InstanceCreator getInstanceCreator() { return instanceCreator; } From 8d41696d7ddeab42a8aff6f3412bca772d90e890 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 30 Aug 2024 12:48:43 +0200 Subject: [PATCH 09/74] Introduces SubjectCreator in several Checkers --- .../internal/checkers/HierarchyChecker.java | 23 ++++++++----------- .../internal/checkers/RecordChecker.java | 17 ++++---------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java index 10a3e083b..fbf0775a2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java @@ -7,6 +7,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; @@ -20,6 +21,7 @@ public class HierarchyChecker implements Checker { private final Configuration config; private final Class type; private final TypeTag typeTag; + private final SubjectCreator subjectCreator; private final ClassAccessor classAccessor; private final Class redefinedSubclass; private final boolean strictnessSuppressed; @@ -44,6 +46,7 @@ public HierarchyChecker(Configuration config) { this.type = config.getType(); this.typeTag = config.getTypeTag(); + this.subjectCreator = config.getSubjectCreator(); this.classAccessor = config.getClassAccessor(); this.redefinedSubclass = config.getRedefinedSubclass(); this.typeIsFinal = Modifier.isFinal(type.getModifiers()); @@ -67,7 +70,7 @@ private void checkSuperclass() { } if (config.hasRedefinedSuperclass() || config.isUsingGetClass()) { - T reference = classAccessor.getRedObject(typeTag); + T reference = subjectCreator.plain(); Object equalSuper = getEqualSuper(reference); Formatter formatter = Formatter.of( @@ -87,15 +90,9 @@ private void checkSuperclass() { // instance. } } else { - safelyCheckSuperProperties(classAccessor.getRedAccessor(typeTag)); + safelyCheckSuperProperties(ObjectAccessor.of(subjectCreator.plain())); safelyCheckSuperProperties( - classAccessor.getDefaultValuesAccessor( - typeTag, - config.getWarningsToSuppress().contains(Warning.NULL_FIELDS), - config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS), - config.getNonnullFields(), - config.getAnnotationCache() - ) + ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted(config)) ); } } @@ -167,8 +164,8 @@ private void checkSubclass() { return; } - ObjectAccessor referenceAccessor = classAccessor.getRedAccessor(typeTag); - T reference = referenceAccessor.get(); + T reference = subjectCreator.plain(); + ObjectAccessor referenceAccessor = ObjectAccessor.of(reference); T equalSub = referenceAccessor.copyIntoAnonymousSubclass(); if (config.isUsingGetClass()) { @@ -204,8 +201,8 @@ private void checkRedefinedSubclass() { ); } - ObjectAccessor referenceAccessor = classAccessor.getRedAccessor(typeTag); - T reference = referenceAccessor.get(); + T reference = subjectCreator.plain(); + ObjectAccessor referenceAccessor = ObjectAccessor.of(reference); T redefinedSub = referenceAccessor.copyIntoSubclass(redefinedSubclass); assertFalse( Formatter.of( diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java index aa466296c..b61be051a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java @@ -1,6 +1,6 @@ package nl.jqno.equalsverifier.internal.checkers; -import static nl.jqno.equalsverifier.internal.util.Assert.*; +import static nl.jqno.equalsverifier.internal.util.Assert.fail; import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; import java.lang.reflect.Field; @@ -9,7 +9,7 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; @@ -31,16 +31,9 @@ public void check() { return; } - verifyRecordPrecondition(accessor.getRedAccessor(config.getTypeTag())); - verifyRecordPrecondition( - accessor.getDefaultValuesAccessor( - config.getTypeTag(), - config.getWarningsToSuppress().contains(Warning.NULL_FIELDS), - config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS), - config.getNonnullFields(), - config.getAnnotationCache() - ) - ); + SubjectCreator subjectCreator = config.getSubjectCreator(); + verifyRecordPrecondition(ObjectAccessor.of(subjectCreator.plain())); + verifyRecordPrecondition(ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted(config))); } private void verifyRecordPrecondition(ObjectAccessor originalAccessor) { From 3b8462cd1ce2996453a8d8fa0ab6098bc74a3faf Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 30 Aug 2024 13:14:00 +0200 Subject: [PATCH 10/74] Introduces ClassProbe --- .../checkers/AbstractDelegationChecker.java | 10 +- .../internal/checkers/FieldsChecker.java | 6 +- .../internal/checkers/HierarchyChecker.java | 12 +- .../internal/checkers/RecordChecker.java | 6 +- .../internal/checkers/SignatureChecker.java | 8 +- .../fieldchecks/JpaLazyGetterFieldCheck.java | 11 +- .../fieldchecks/ReflexivityFieldCheck.java | 6 +- .../internal/instantiation/ClassProbe.java | 134 ++++++++++++++++++ .../internal/util/Configuration.java | 15 +- 9 files changed, 171 insertions(+), 37 deletions(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java index 57534112a..425904e7b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java @@ -4,10 +4,10 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -18,14 +18,14 @@ public class AbstractDelegationChecker implements Checker { private final Class type; private final TypeTag typeTag; private final PrefabValues prefabValues; - private final ClassAccessor classAccessor; + private final ClassProbe classProbe; private final CachedHashCodeInitializer cachedHashCodeInitializer; public AbstractDelegationChecker(Configuration config) { this.type = config.getType(); this.typeTag = config.getTypeTag(); this.prefabValues = config.getPrefabValues(); - this.classAccessor = config.getClassAccessor(); + this.classProbe = config.getClassProbe(); this.cachedHashCodeInitializer = config.getCachedHashCodeInitializer(); } @@ -41,8 +41,8 @@ public void check() { } private void checkAbstractEqualsAndHashCode() { - boolean equalsIsAbstract = classAccessor.isEqualsAbstract(); - boolean hashCodeIsAbstract = classAccessor.isHashCodeAbstract(); + boolean equalsIsAbstract = classProbe.isEqualsAbstract(); + boolean hashCodeIsAbstract = classProbe.isHashCodeAbstract(); if (equalsIsAbstract && hashCodeIsAbstract) { fail( diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index f99546439..8fc0e6cfd 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -5,7 +5,6 @@ import nl.jqno.equalsverifier.internal.checkers.fieldchecks.*; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; @@ -62,10 +61,9 @@ public FieldsChecker(Configuration config) { @Override public void check() { - ClassAccessor classAccessor = config.getClassAccessor(); - FieldInspector inspector = new FieldInspector<>(classAccessor.getType(), config); + FieldInspector inspector = new FieldInspector<>(config.getType(), config); - if (!classAccessor.isEqualsInheritedFromObject()) { + if (!config.getClassProbe().isEqualsInheritedFromObject()) { inspector.check(arrayFieldCheck); inspector.check(floatAndDoubleFieldCheck); inspector.check(reflexivityFieldCheck); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java index fbf0775a2..58fba5a85 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java @@ -7,9 +7,9 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; @@ -22,7 +22,7 @@ public class HierarchyChecker implements Checker { private final Class type; private final TypeTag typeTag; private final SubjectCreator subjectCreator; - private final ClassAccessor classAccessor; + private final ClassProbe classProbe; private final Class redefinedSubclass; private final boolean strictnessSuppressed; private final boolean hasRedefinedSubclass; @@ -47,10 +47,10 @@ public HierarchyChecker(Configuration config) { this.type = config.getType(); this.typeTag = config.getTypeTag(); this.subjectCreator = config.getSubjectCreator(); - this.classAccessor = config.getClassAccessor(); + this.classProbe = config.getClassProbe(); this.redefinedSubclass = config.getRedefinedSubclass(); this.typeIsFinal = Modifier.isFinal(type.getModifiers()); - this.typeIsSealed = classAccessor.isSealed(); + this.typeIsSealed = classProbe.isSealed(); this.cachedHashCodeInitializer = config.getCachedHashCodeInitializer(); } @@ -64,8 +64,8 @@ public void check() { } private void checkSuperclass() { - ClassAccessor superAccessor = classAccessor.getSuperAccessor(); - if (superAccessor.isEqualsInheritedFromObject() || superAccessor.isSealed()) { + ClassProbe superProbe = classProbe.getSuperProbe(); + if (superProbe.isEqualsInheritedFromObject() || superProbe.isSealed()) { return; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java index b61be051a..fdfd2ff6d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -26,8 +26,8 @@ public RecordChecker(Configuration config) { @Override public void check() { - ClassAccessor accessor = config.getClassAccessor(); - if (!accessor.isRecord()) { + ClassProbe probe = config.getClassProbe(); + if (!probe.isRecord()) { return; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java index d0c5542e5..5244d967e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java @@ -8,19 +8,19 @@ import java.util.List; import java.util.Set; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; +import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Formatter; public class SignatureChecker implements Checker { private final Class type; - private final ClassAccessor classAccessor; + private final ClassProbe classProbe; private final Set warningsToSuppress; public SignatureChecker(Configuration config) { this.type = config.getType(); - this.classAccessor = config.getClassAccessor(); + this.classProbe = config.getClassProbe(); this.warningsToSuppress = config.getWarningsToSuppress(); } @@ -78,7 +78,7 @@ private void checkEqualsIsDefined() { boolean dontAllowDirectlyInherited = !warningsToSuppress.contains( Warning.INHERITED_DIRECTLY_FROM_OBJECT ); - boolean isDirectlyInherited = classAccessor.isEqualsInheritedFromObject(); + boolean isDirectlyInherited = classProbe.isEqualsInheritedFromObject(); if (dontAllowDirectlyInherited && isDirectlyInherited) { fail( Formatter.of( diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index 8ef79488a..039931ad1 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -9,11 +9,8 @@ import java.util.function.Function; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.instantiation.*; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; @@ -26,7 +23,7 @@ public class JpaLazyGetterFieldCheck implements FieldCheck { private final SubjectCreator subjectCreator; private final InstanceCreator instanceCreator; private final Class type; - private final ClassAccessor accessor; + private final ClassProbe classProbe; private final AnnotationCache annotationCache; private final Function fieldnameToGetter; private final boolean strictHashcode; @@ -35,7 +32,7 @@ public JpaLazyGetterFieldCheck(Configuration config) { this.subjectCreator = config.getSubjectCreator(); this.instanceCreator = config.getInstanceCreator(); this.type = config.getType(); - this.accessor = config.getClassAccessor(); + this.classProbe = config.getClassProbe(); this.annotationCache = config.getAnnotationCache(); this.fieldnameToGetter = config.getFieldnameToGetter(); this.strictHashcode = config.getWarningsToSuppress().contains(Warning.STRICT_HASHCODE); @@ -54,7 +51,7 @@ public void execute(FieldProbe fieldProbe) { return; } - assertEntity(fieldName, "equals", getterName, accessor.hasMethod(getterName)); + assertEntity(fieldName, "equals", getterName, classProbe.hasMethod(getterName)); Class sub = throwingGetterCreator(getterName); T red1 = instanceCreator.instantiate(new TypeTag(sub)).getRed(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index fe0baf063..aa75b2bbe 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -7,11 +7,11 @@ import java.util.EnumSet; import java.util.Set; import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.NonnullAnnotationVerifier; @@ -65,8 +65,8 @@ private void checkValueReflexivity(Field field) { if (FieldAccessor.of(field).fieldIsStatic()) { return; } - ClassAccessor fieldTypeAccessor = ClassAccessor.of(fieldType, prefabValues); - if (!fieldTypeAccessor.declaresEquals()) { + ClassProbe fieldTypeProbe = new ClassProbe<>(fieldType); + if (!fieldTypeProbe.declaresEquals()) { return; } if (fieldType.isSynthetic()) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java new file mode 100644 index 000000000..3cf1148aa --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java @@ -0,0 +1,134 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; + +import java.lang.reflect.Modifier; +import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; +import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; +import nl.jqno.equalsverifier.internal.reflection.SealedTypesHelper; + +public class ClassProbe { + + private final Class type; + + public ClassProbe(Class type) { + this.type = type; + } + + /** @return The class on which {@link ClassAccessor} operates. */ + public Class getType() { + return type; + } + + /** + * Determines whether T is a Java Record. + * + * @return true if T is a Java Record. + */ + public boolean isRecord() { + return RecordsHelper.isRecord(type); + } + + /** + * Determines whether T is a sealed class. + * + * @return true if T is a sealed class + */ + public boolean isSealed() { + return SealedTypesHelper.isSealed(type); + } + + /** + * Determines whether T has an {@code equals} method. + * + * @return True if T has an {@code equals} method. + */ + public boolean declaresEquals() { + return declaresMethod(type, "equals", Object.class); + } + + /** + * Determines whether T has an {@code hashCode} method. + * + * @return True if T has an {@code hashCode} method. + */ + public boolean declaresHashCode() { + return declaresMethod(type, "hashCode"); + } + + /** + * Determines whether T has a method with the given name and parameters. + * + * @param name The name of the method we're looking for. + * @return True if T has a method with the given name and parameters. + */ + public boolean hasMethod(String name) { + Class t = type; + while (t != null) { + if (declaresMethod(t, name)) { + return true; + } + t = t.getSuperclass(); + } + return false; + } + + private static boolean declaresMethod(Class type, String name, Class... parameterTypes) { + try { + type.getDeclaredMethod(name, parameterTypes); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } + + /** + * Determines whether T's {@code equals} method is abstract. + * + * @return True if T's {@code equals} method is abstract. + */ + public boolean isEqualsAbstract() { + return isMethodAbstract("equals", Object.class); + } + + /** + * Determines whether T's {@code hashCode} method is abstract. + * + * @return True if T's {@code hashCode} method is abstract. + */ + public boolean isHashCodeAbstract() { + return isMethodAbstract("hashCode"); + } + + private boolean isMethodAbstract(String name, Class... parameterTypes) { + return rethrow(() -> + Modifier.isAbstract(type.getMethod(name, parameterTypes).getModifiers()) + ); + } + + /** + * Determines whether T's {@code equals} method is inherited from {@link Object}. + * + * @return true if T's {@code equals} method is inherited from {@link Object}; false if it is + * overridden in T or in any of its superclasses (except {@link Object}). + */ + public boolean isEqualsInheritedFromObject() { + ClassProbe i = this; + while (i.getType() != Object.class) { + if (i.declaresEquals() && !i.isEqualsAbstract()) { + return false; + } + i = i.getSuperProbe(); + } + return true; + } + + /** + * Returns a probe for T's superclass. + * + * @return A probe for T's superclass. + */ + public ClassProbe getSuperProbe() { + return new ClassProbe<>(type.getSuperclass()); + } +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index 9253dde70..bd4d5ed47 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -10,9 +10,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.instantiation.VintageInstanceCreator; +import nl.jqno.equalsverifier.internal.instantiation.*; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; @@ -42,12 +40,14 @@ public final class Configuration { private final ClassAccessor classAccessor; private final AnnotationCache annotationCache; private final Set ignoredFields; - private final SubjectCreator subjectCreator; - private final InstanceCreator instanceCreator; private final List equalExamples; private final List unequalExamples; + private final SubjectCreator subjectCreator; + private final InstanceCreator instanceCreator; + private final ClassProbe classProbe; + // CHECKSTYLE OFF: ParameterNumber private Configuration( Class type, @@ -83,6 +83,7 @@ private Configuration( this.unequalExamples = unequalExamples; this.instanceCreator = new VintageInstanceCreator(prefabValues); this.subjectCreator = new SubjectCreator<>(typeTag, prefabValues); + this.classProbe = new ClassProbe<>(type); } public static Configuration build( @@ -300,4 +301,8 @@ public SubjectCreator getSubjectCreator() { public InstanceCreator getInstanceCreator() { return instanceCreator; } + + public ClassProbe getClassProbe() { + return classProbe; + } } From dbf8bd8b8f47d679f8f757180ffb1dac1b6f9043 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 30 Aug 2024 13:48:02 +0200 Subject: [PATCH 11/74] Introduces InstanceCreator in several FieldChecks and Checkers --- .../checkers/AbstractDelegationChecker.java | 13 +++++++------ .../internal/checkers/FieldsChecker.java | 2 +- .../fieldchecks/JpaLazyGetterFieldCheck.java | 7 ++++--- .../fieldchecks/ReflexivityFieldCheck.java | 19 +++++++++---------- .../fieldchecks/StringFieldCheck.java | 10 +++++----- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java index 425904e7b..63f3529d2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java @@ -5,7 +5,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; @@ -17,14 +17,14 @@ public class AbstractDelegationChecker implements Checker { private final Class type; private final TypeTag typeTag; - private final PrefabValues prefabValues; + private final InstanceCreator instanceCreator; private final ClassProbe classProbe; private final CachedHashCodeInitializer cachedHashCodeInitializer; public AbstractDelegationChecker(Configuration config) { this.type = config.getType(); this.typeTag = config.getTypeTag(); - this.prefabValues = config.getPrefabValues(); + this.instanceCreator = config.getInstanceCreator(); this.classProbe = config.getClassProbe(); this.cachedHashCodeInitializer = config.getCachedHashCodeInitializer(); } @@ -35,8 +35,9 @@ public void check() { checkAbstractDelegationInFields(); - T instance = prefabValues.giveRed(typeTag); - T copy = prefabValues.giveBlue(typeTag); + Tuple tuple = instanceCreator.instantiate(typeTag); + T instance = tuple.getRed(); + T copy = tuple.getBlue(); checkAbstractDelegation(instance, copy); } @@ -72,7 +73,7 @@ private void checkAbstractDelegationInFields() { private Tuple safelyGetTuple(TypeTag tag) { try { - return prefabValues.giveTuple(tag); + return instanceCreator.instantiate(tag); } catch (Exception ignored) { // If it fails for some reason, any reason, just return null so we can skip the test. return null; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index 8fc0e6cfd..f024ae9e2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -51,7 +51,7 @@ public FieldsChecker(Configuration config) { this.stringFieldCheck = new StringFieldCheck<>( subjectCreator, - config.getPrefabValues(), + config.getInstanceCreator(), config.getCachedHashCodeInitializer() ); this.bigDecimalFieldCheck = diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index 039931ad1..9f1f79678 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -10,9 +10,9 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; import nl.jqno.equalsverifier.internal.instantiation.*; +import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.Instantiator; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -54,8 +54,9 @@ public void execute(FieldProbe fieldProbe) { assertEntity(fieldName, "equals", getterName, classProbe.hasMethod(getterName)); Class sub = throwingGetterCreator(getterName); - T red1 = instanceCreator.instantiate(new TypeTag(sub)).getRed(); - T red2 = ObjectAccessor.of(red1, sub).copy(); + Tuple tuple = instanceCreator.instantiate(new TypeTag(sub)); + T red1 = tuple.getRed(); + T red2 = tuple.getRedCopy(); boolean equalsExceptionCaught = false; try { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index aa75b2bbe..c4199cb96 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -7,10 +7,8 @@ import java.util.EnumSet; import java.util.Set; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.instantiation.*; +import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; @@ -21,17 +19,17 @@ public class ReflexivityFieldCheck implements FieldCheck { - private final SubjectCreator subjectCreator; private final TypeTag typeTag; - private final PrefabValues prefabValues; + private final SubjectCreator subjectCreator; + private final InstanceCreator instanceCreator; private final EnumSet warningsToSuppress; private final Set nonnullFields; private final AnnotationCache annotationCache; public ReflexivityFieldCheck(Configuration config) { - this.subjectCreator = config.getSubjectCreator(); this.typeTag = config.getTypeTag(); - this.prefabValues = config.getPrefabValues(); + this.subjectCreator = config.getSubjectCreator(); + this.instanceCreator = config.getInstanceCreator(); this.warningsToSuppress = config.getWarningsToSuppress(); this.nonnullFields = config.getNonnullFields(); this.annotationCache = config.getAnnotationCache(); @@ -75,8 +73,9 @@ private void checkValueReflexivity(Field field) { } TypeTag tag = TypeTag.of(field, typeTag); - Object left = subjectCreator.withFieldSetTo(field, prefabValues.giveRed(tag)); - Object right = subjectCreator.withFieldSetTo(field, prefabValues.giveRedCopy(tag)); + Tuple tuple = instanceCreator.instantiate(tag); + Object left = subjectCreator.withFieldSetTo(field, tuple.getRed()); + Object right = subjectCreator.withFieldSetTo(field, tuple.getRedCopy()); Formatter f = Formatter.of( "Reflexivity: == used instead of .equals() on field: %%" + diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java index d692f92a2..6c46c4b6d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java @@ -5,8 +5,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; +import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; @@ -17,7 +17,7 @@ public class StringFieldCheck implements FieldCheck { public static final String ERROR_DOC_TITLE = "String equality"; private final SubjectCreator subjectCreator; - private final PrefabValues prefabValues; + private final InstanceCreator instanceCreator; private final CachedHashCodeInitializer cachedHashCodeInitializer; @SuppressFBWarnings( @@ -26,11 +26,11 @@ public class StringFieldCheck implements FieldCheck { ) public StringFieldCheck( SubjectCreator subjectCreator, - PrefabValues prefabValues, + InstanceCreator instanceCreator, CachedHashCodeInitializer cachedHashCodeInitializer ) { this.subjectCreator = subjectCreator; - this.prefabValues = prefabValues; + this.instanceCreator = instanceCreator; this.cachedHashCodeInitializer = cachedHashCodeInitializer; } @@ -44,7 +44,7 @@ public void execute(FieldProbe fieldProbe) { String.class.equals(fieldProbe.getType()) && !FieldAccessor.of(fieldProbe.getField()).fieldIsStatic() ) { - String red = prefabValues.giveRed(new TypeTag(String.class)); + String red = instanceCreator.instantiate(new TypeTag(String.class)).getRed(); final T reference; final T copy; From 01bf705d1194588ad4d46affabefa5f89f38214d Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sat, 31 Aug 2024 09:23:53 +0200 Subject: [PATCH 12/74] Adds ArchUnit test to enforce non-usage of vintage instantiation methods --- .../internal/architecture/ArchitectureTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index 4b396b798..6f9b31600 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -5,10 +5,23 @@ import com.tngtech.archunit.junit.AnalyzeClasses; import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchRule; +import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; @AnalyzeClasses(packages = "nl.jqno.equalsverifier") public final class ArchitectureTest { + @ArchTest + public static final ArchRule DONT_USE_VINTAGE_REFLECTION_DIRECTLY = noClasses() + .that() + .resideInAPackage("nl.jqno.equalsverifier.internal.checkers..") + .should() + .accessClassesThat() + .areAssignableTo(ClassAccessor.class) + .orShould() + .accessClassesThat() + .areAssignableTo(PrefabValues.class); + @ArchTest public static final ArchRule APACHE_COMMONS = noClasses() .that() From 7402fe9a8efa76d49cc0beab14b9d333173e6e7d Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sat, 31 Aug 2024 09:34:26 +0200 Subject: [PATCH 13/74] Makes SubjectCreator an interface --- .../instantiation/SubjectCreator.java | 71 ++--------------- .../instantiation/VintageSubjectCreator.java | 76 +++++++++++++++++++ .../internal/util/Configuration.java | 18 +---- 3 files changed, 88 insertions(+), 77 deletions(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index 2e0ba1b24..5efda9ba2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -1,69 +1,14 @@ package nl.jqno.equalsverifier.internal.instantiation; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; -import java.util.function.BiFunction; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; -public class SubjectCreator { - - private final TypeTag typeTag; - private final PrefabValues prefabValues; - - @SuppressFBWarnings( - value = "EI_EXPOSE_REP2", - justification = "PrefabValues is inherently mutable." - ) - public SubjectCreator(TypeTag typeTag, PrefabValues prefabValues) { - this.typeTag = typeTag; - this.prefabValues = prefabValues; - } - - public T plain() { - return createSubject().get(); - } - - public T withFieldDefaulted(Field field) { - return createSubject().withDefaultedField(field).get(); - } - - public T withAllFieldsDefaulted(Configuration config) { - return withAllFields((acc, f) -> - FieldProbe.of(f, config).canBeDefault() ? acc.withDefaultedField(f) : acc - ); - } - - public T withAllFieldsDefaultedExcept(Field field) { - return withAllFields((acc, f) -> f.equals(field) ? acc : acc.withDefaultedField(f)); - } - - public T withFieldSetTo(Field field, Object value) { - return createSubject().withFieldSetTo(field, value).get(); - } - - public T withFieldChanged(Field field) { - return createSubject().withChangedField(field, prefabValues, typeTag).get(); - } - - public T withAllFieldsChanged() { - return withAllFields((acc, f) -> acc.withChangedField(f, prefabValues, typeTag)); - } - - private T withAllFields(BiFunction, Field, ObjectAccessor> modifier) { - ObjectAccessor accessor = createSubject(); - for (Field f : FieldIterable.of(typeTag.getType())) { - accessor = modifier.apply(accessor, f); - } - return accessor.get(); - } - - private ObjectAccessor createSubject() { - ClassAccessor accessor = ClassAccessor.of(typeTag.getType(), prefabValues); - return accessor.getRedAccessor(TypeTag.NULL); - } +public interface SubjectCreator { + T plain(); + T withFieldDefaulted(Field field); + T withAllFieldsDefaulted(Configuration config); + T withAllFieldsDefaultedExcept(Field field); + T withFieldSetTo(Field field, Object value); + T withFieldChanged(Field field); + T withAllFieldsChanged(); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java new file mode 100644 index 000000000..eda225af4 --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java @@ -0,0 +1,76 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.lang.reflect.Field; +import java.util.function.BiFunction; +import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.util.Configuration; + +public class VintageSubjectCreator implements SubjectCreator { + + private final TypeTag typeTag; + private final PrefabValues prefabValues; + + @SuppressFBWarnings( + value = "EI_EXPOSE_REP2", + justification = "PrefabValues is inherently mutable." + ) + public VintageSubjectCreator(TypeTag typeTag, PrefabValues prefabValues) { + this.typeTag = typeTag; + this.prefabValues = prefabValues; + } + + @Override + public T plain() { + return createSubject().get(); + } + + @Override + public T withFieldDefaulted(Field field) { + return createSubject().withDefaultedField(field).get(); + } + + @Override + public T withAllFieldsDefaulted(Configuration config) { + return withAllFields((acc, f) -> + FieldProbe.of(f, config).canBeDefault() ? acc.withDefaultedField(f) : acc + ); + } + + @Override + public T withAllFieldsDefaultedExcept(Field field) { + return withAllFields((acc, f) -> f.equals(field) ? acc : acc.withDefaultedField(f)); + } + + @Override + public T withFieldSetTo(Field field, Object value) { + return createSubject().withFieldSetTo(field, value).get(); + } + + @Override + public T withFieldChanged(Field field) { + return createSubject().withChangedField(field, prefabValues, typeTag).get(); + } + + @Override + public T withAllFieldsChanged() { + return withAllFields((acc, f) -> acc.withChangedField(f, prefabValues, typeTag)); + } + + private T withAllFields(BiFunction, Field, ObjectAccessor> modifier) { + ObjectAccessor accessor = createSubject(); + for (Field f : FieldIterable.of(typeTag.getType())) { + accessor = modifier.apply(accessor, f); + } + return accessor.get(); + } + + private ObjectAccessor createSubject() { + ClassAccessor accessor = ClassAccessor.of(typeTag.getType(), prefabValues); + return accessor.getRedAccessor(TypeTag.NULL); + } +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index bd4d5ed47..61c11e1bf 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -1,25 +1,15 @@ package nl.jqno.equalsverifier.internal.util; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.instantiation.*; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.prefabvalues.*; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.annotations.Annotation; -import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; -import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCacheBuilder; -import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; +import nl.jqno.equalsverifier.internal.reflection.annotations.*; public final class Configuration { @@ -82,7 +72,7 @@ private Configuration( this.equalExamples = equalExamples; this.unequalExamples = unequalExamples; this.instanceCreator = new VintageInstanceCreator(prefabValues); - this.subjectCreator = new SubjectCreator<>(typeTag, prefabValues); + this.subjectCreator = new VintageSubjectCreator<>(typeTag, prefabValues); this.classProbe = new ClassProbe<>(type); } From df86c852a438b587852b484149f3311af44f33c1 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sat, 31 Aug 2024 10:30:15 +0200 Subject: [PATCH 14/74] Introduces an incomplete ModernSubjectCreator --- .../instantiation/ModernSubjectCreator.java | 100 ++++++++++++++++++ .../internal/util/Configuration.java | 2 +- 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java new file mode 100644 index 000000000..908fbfa07 --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -0,0 +1,100 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.util.Configuration; + +public class ModernSubjectCreator implements SubjectCreator { + + private final TypeTag typeTag; + private final InstanceCreator instanceCreator; + + public ModernSubjectCreator(TypeTag typeTag, InstanceCreator instanceCreator) { + this.typeTag = typeTag; + this.instanceCreator = instanceCreator; + } + + @Override + public T plain() { + return createInstance(empty()); + } + + @Override + public T withFieldDefaulted(Field field) { + return createInstance(with(field, null)); + } + + @Override + public T withAllFieldsDefaulted(Configuration config) { + Map values = empty(); + for (Field f : fields()) { + values.put(f, null); + } + return createInstance(values); + } + + @Override + public T withAllFieldsDefaultedExcept(Field field) { + Map values = empty(); + for (Field f : fields()) { + if (!f.equals(field)) { + values.put(f, null); + } + } + return createInstance(values); + } + + @Override + public T withFieldSetTo(Field field, Object value) { + return createInstance(with(field, value)); + } + + @Override + public T withFieldChanged(Field field) { + Object value = instantiate(field).getBlue(); + return createInstance(with(field, value)); + } + + @Override + public T withAllFieldsChanged() { + Map values = empty(); + for (Field f : fields()) { + Object value = instantiate(f).getBlue(); + values.put(f, value); + } + return createInstance(values); + } + + private T createInstance(Map values) { + for (Field f : fields()) { + if (!values.containsKey(f)) { + Object value = instantiate(f).getRed(); + values.put(f, value); + } + } + // maak een instance met veld-waardes uit `values`: kijk af uit FallbackFactory + return null; + } + + private Map empty() { + return new HashMap<>(); + } + + private Map with(Field f, Object v) { + Map result = empty(); + result.put(f, v); + return result; + } + + private FieldIterable fields() { + return FieldIterable.of(typeTag.getType()); + } + + private Tuple instantiate(Field f) { + return instanceCreator.instantiate(TypeTag.of(f, typeTag)); + } +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index 61c11e1bf..ce9db60a2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -72,7 +72,7 @@ private Configuration( this.equalExamples = equalExamples; this.unequalExamples = unequalExamples; this.instanceCreator = new VintageInstanceCreator(prefabValues); - this.subjectCreator = new VintageSubjectCreator<>(typeTag, prefabValues); + this.subjectCreator = new ModernSubjectCreator<>(typeTag, instanceCreator); this.classProbe = new ClassProbe<>(type); } From 1cc7790c2377c527843849b9d25e32017c7e1bef Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 6 Sep 2024 09:14:07 +0200 Subject: [PATCH 15/74] Partially implements ModernSubjectCreator --- .../instantiation/ModernSubjectCreator.java | 30 +++++++++++++++++-- .../internal/util/Configuration.java | 4 +-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index 908fbfa07..e0bf4afb2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -6,16 +6,24 @@ import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.Instantiator; +import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; public class ModernSubjectCreator implements SubjectCreator { private final TypeTag typeTag; private final InstanceCreator instanceCreator; + private final ClassProbe classProbe; - public ModernSubjectCreator(TypeTag typeTag, InstanceCreator instanceCreator) { + public ModernSubjectCreator( + TypeTag typeTag, + InstanceCreator instanceCreator, + ClassProbe classProbe + ) { this.typeTag = typeTag; this.instanceCreator = instanceCreator; + this.classProbe = classProbe; } @Override @@ -76,8 +84,24 @@ private T createInstance(Map values) { values.put(f, value); } } + // maak een instance met veld-waardes uit `values`: kijk af uit FallbackFactory - return null; + if (classProbe.isRecord()) { + return null; + } else { + T instance = Instantiator.of(typeTag.getType()).instantiate(); + ObjectAccessor accessor = ObjectAccessor.of(instance); + for (Field f : values.keySet()) { + Object value = values.get(f); + if (value == null) { + // TODO if fieldProbe.canBeDefault()... + accessor.withDefaultedField(f); + } else { + accessor.withFieldSetTo(f, value); + } + } + return instance; + } } private Map empty() { @@ -91,7 +115,7 @@ private Map with(Field f, Object v) { } private FieldIterable fields() { - return FieldIterable.of(typeTag.getType()); + return FieldIterable.ofIgnoringStatic(typeTag.getType()); } private Tuple instantiate(Field f) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index ce9db60a2..f2f5d50ef 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -71,9 +71,9 @@ private Configuration( this.fieldnameToGetter = fieldnameToGetter; this.equalExamples = equalExamples; this.unequalExamples = unequalExamples; - this.instanceCreator = new VintageInstanceCreator(prefabValues); - this.subjectCreator = new ModernSubjectCreator<>(typeTag, instanceCreator); this.classProbe = new ClassProbe<>(type); + this.instanceCreator = new VintageInstanceCreator(prefabValues); + this.subjectCreator = new ModernSubjectCreator<>(typeTag, instanceCreator, classProbe); } public static Configuration build( From 66f3f8079d01f8a03b7b0727e15a0c1a698be9ab Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 6 Sep 2024 09:54:13 +0200 Subject: [PATCH 16/74] Separates Context out from Configuration --- .../api/SingleTypeEqualsVerifierApi.java | 34 +++++++-------- .../checkers/AbstractDelegationChecker.java | 13 +++--- .../internal/checkers/FieldsChecker.java | 23 ++++++----- .../internal/checkers/HierarchyChecker.java | 14 +++---- .../MapEntryHashCodeRequirementChecker.java | 13 +++--- .../internal/checkers/NullChecker.java | 17 ++++---- .../internal/checkers/RecordChecker.java | 18 ++++---- .../internal/checkers/SignatureChecker.java | 10 ++--- .../fieldchecks/JpaLazyGetterFieldCheck.java | 13 +++--- .../NullPointerExceptionFieldCheck.java | 7 ++-- .../fieldchecks/ReflexivityFieldCheck.java | 9 ++-- .../fieldchecks/SignificantFieldCheck.java | 7 ++-- .../internal/util/Configuration.java | 20 --------- .../equalsverifier/internal/util/Context.java | 41 +++++++++++++++++++ 14 files changed, 136 insertions(+), 103 deletions(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index 4bde026d1..8da96b3b1 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -25,14 +25,7 @@ import nl.jqno.equalsverifier.internal.checkers.SignatureChecker; import nl.jqno.equalsverifier.internal.exceptions.MessagingException; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; -import nl.jqno.equalsverifier.internal.util.Configuration; -import nl.jqno.equalsverifier.internal.util.ErrorMessage; -import nl.jqno.equalsverifier.internal.util.FieldNameExtractor; -import nl.jqno.equalsverifier.internal.util.Formatter; -import nl.jqno.equalsverifier.internal.util.ObjenesisWrapper; -import nl.jqno.equalsverifier.internal.util.PrefabValuesApi; -import nl.jqno.equalsverifier.internal.util.Validations; +import nl.jqno.equalsverifier.internal.util.*; /** * Helps to construct an {@link EqualsVerifier} test with a fluent API. @@ -412,6 +405,7 @@ private void performVerification() { Validations.validateClassCanBeVerified(type); Configuration config = buildConfig(); + Context context = new Context<>(config); Validations.validateProcessedAnnotations( type, config.getAnnotationCache(), @@ -420,8 +414,8 @@ private void performVerification() { allExcludedFields ); - verifyWithoutExamples(config); - verifyWithExamples(config); + verifyWithoutExamples(context); + verifyWithExamples(context); } private Configuration buildConfig() { @@ -444,12 +438,13 @@ private Configuration buildConfig() { ); } - private void verifyWithoutExamples(Configuration config) { + private void verifyWithoutExamples(Context context) { + Configuration config = context.getConfiguration(); Checker[] checkers = { - new SignatureChecker<>(config), - new AbstractDelegationChecker<>(config), - new NullChecker<>(config), - new RecordChecker<>(config), + new SignatureChecker<>(context), + new AbstractDelegationChecker<>(context), + new NullChecker<>(context), + new RecordChecker<>(context), new CachedHashCodeChecker<>(config) }; @@ -458,12 +453,13 @@ private void verifyWithoutExamples(Configuration config) { } } - private void verifyWithExamples(Configuration config) { + private void verifyWithExamples(Context context) { + Configuration config = context.getConfiguration(); Checker[] checkers = { new ExamplesChecker<>(config), - new HierarchyChecker<>(config), - new FieldsChecker<>(config), - new MapEntryHashCodeRequirementChecker<>(config) + new HierarchyChecker<>(context), + new FieldsChecker<>(context), + new MapEntryHashCodeRequirementChecker<>(context) }; for (Checker checker : checkers) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java index 63f3529d2..1bf718960 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java @@ -9,9 +9,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; -import nl.jqno.equalsverifier.internal.util.Configuration; -import nl.jqno.equalsverifier.internal.util.Formatter; +import nl.jqno.equalsverifier.internal.util.*; public class AbstractDelegationChecker implements Checker { @@ -21,11 +19,12 @@ public class AbstractDelegationChecker implements Checker { private final ClassProbe classProbe; private final CachedHashCodeInitializer cachedHashCodeInitializer; - public AbstractDelegationChecker(Configuration config) { - this.type = config.getType(); + public AbstractDelegationChecker(Context context) { + Configuration config = context.getConfiguration(); + this.type = context.getType(); this.typeTag = config.getTypeTag(); - this.instanceCreator = config.getInstanceCreator(); - this.classProbe = config.getClassProbe(); + this.instanceCreator = context.getInstanceCreator(); + this.classProbe = context.getClassProbe(); this.cachedHashCodeInitializer = config.getCachedHashCodeInitializer(); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index f024ae9e2..dd0ea1b21 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -9,9 +9,11 @@ import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.Context; public class FieldsChecker implements Checker { + private final Context context; private final Configuration config; private final ArrayFieldCheck arrayFieldCheck; private final FloatAndDoubleFieldCheck floatAndDoubleFieldCheck; @@ -25,11 +27,12 @@ public class FieldsChecker implements Checker { private final BigDecimalFieldCheck bigDecimalFieldCheck; private final JpaLazyGetterFieldCheck jpaLazyGetterFieldCheck; - public FieldsChecker(Configuration config) { - this.config = config; + public FieldsChecker(Context context) { + this.context = context; + this.config = context.getConfiguration(); final TypeTag typeTag = config.getTypeTag(); - final SubjectCreator subjectCreator = config.getSubjectCreator(); + final SubjectCreator subjectCreator = context.getSubjectCreator(); final String cachedHashCodeFieldName = config .getCachedHashCodeInitializer() @@ -42,8 +45,8 @@ public FieldsChecker(Configuration config) { this.floatAndDoubleFieldCheck = new FloatAndDoubleFieldCheck<>(subjectCreator); this.mutableStateFieldCheck = new MutableStateFieldCheck<>(subjectCreator, isCachedHashCodeField); - this.reflexivityFieldCheck = new ReflexivityFieldCheck<>(config); - this.significantFieldCheck = new SignificantFieldCheck<>(config, isCachedHashCodeField); + this.reflexivityFieldCheck = new ReflexivityFieldCheck<>(context); + this.significantFieldCheck = new SignificantFieldCheck<>(context, isCachedHashCodeField); this.symmetryFieldCheck = new SymmetryFieldCheck<>(subjectCreator); this.transientFieldsCheck = new TransientFieldsCheck<>(subjectCreator, typeTag, config.getAnnotationCache()); @@ -51,25 +54,25 @@ public FieldsChecker(Configuration config) { this.stringFieldCheck = new StringFieldCheck<>( subjectCreator, - config.getInstanceCreator(), + context.getInstanceCreator(), config.getCachedHashCodeInitializer() ); this.bigDecimalFieldCheck = new BigDecimalFieldCheck<>(subjectCreator, config.getCachedHashCodeInitializer()); - this.jpaLazyGetterFieldCheck = new JpaLazyGetterFieldCheck<>(config); + this.jpaLazyGetterFieldCheck = new JpaLazyGetterFieldCheck<>(context); } @Override public void check() { - FieldInspector inspector = new FieldInspector<>(config.getType(), config); + FieldInspector inspector = new FieldInspector<>(context.getType(), config); - if (!config.getClassProbe().isEqualsInheritedFromObject()) { + if (!context.getClassProbe().isEqualsInheritedFromObject()) { inspector.check(arrayFieldCheck); inspector.check(floatAndDoubleFieldCheck); inspector.check(reflexivityFieldCheck); } - if (!ignoreMutability(config.getType())) { + if (!ignoreMutability(context.getType())) { inspector.check(mutableStateFieldCheck); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java index 58fba5a85..45af90e77 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java @@ -12,9 +12,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; -import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; -import nl.jqno.equalsverifier.internal.util.Configuration; -import nl.jqno.equalsverifier.internal.util.Formatter; +import nl.jqno.equalsverifier.internal.util.*; public class HierarchyChecker implements Checker { @@ -30,8 +28,8 @@ public class HierarchyChecker implements Checker { private final boolean typeIsSealed; private final CachedHashCodeInitializer cachedHashCodeInitializer; - public HierarchyChecker(Configuration config) { - this.config = config; + public HierarchyChecker(Context context) { + this.config = context.getConfiguration(); this.strictnessSuppressed = config.getWarningsToSuppress().contains(Warning.STRICT_INHERITANCE); @@ -44,10 +42,10 @@ public HierarchyChecker(Configuration config) { ); } - this.type = config.getType(); + this.type = context.getType(); this.typeTag = config.getTypeTag(); - this.subjectCreator = config.getSubjectCreator(); - this.classProbe = config.getClassProbe(); + this.subjectCreator = context.getSubjectCreator(); + this.classProbe = context.getClassProbe(); this.redefinedSubclass = config.getRedefinedSubclass(); this.typeIsFinal = Modifier.isFinal(type.getModifiers()); this.typeIsSealed = classProbe.isSealed(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java index afc286579..3bcd11d16 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java @@ -4,23 +4,26 @@ import java.util.Map; import java.util.Objects; +import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; public class MapEntryHashCodeRequirementChecker implements Checker { private final Configuration config; + private final InstanceCreator instanceCreator; - public MapEntryHashCodeRequirementChecker(Configuration config) { - this.config = config; + public MapEntryHashCodeRequirementChecker(Context context) { + this.config = context.getConfiguration(); + this.instanceCreator = context.getInstanceCreator(); } @Override public void check() { if (Map.Entry.class.isAssignableFrom(config.getType())) { - Map.Entry e = (Map.Entry) config - .getInstanceCreator() - .instantiate(config.getTypeTag()) + Map.Entry e = instanceCreator + .>instantiate(config.getTypeTag()) .getRed(); int expectedHashCode = Objects.hashCode(e.getKey()) ^ Objects.hashCode(e.getValue()); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java index e2887045e..f02c44c61 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java @@ -2,23 +2,26 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.NullPointerExceptionFieldCheck; -import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.Context; public class NullChecker implements Checker { - private final Configuration config; + private final Context context; - public NullChecker(Configuration config) { - this.config = config; + public NullChecker(Context context) { + this.context = context; } @Override public void check() { - if (config.getWarningsToSuppress().contains(Warning.NULL_FIELDS)) { + if (context.getConfiguration().getWarningsToSuppress().contains(Warning.NULL_FIELDS)) { return; } - FieldInspector inspector = new FieldInspector<>(config.getType(), config); - inspector.check(new NullPointerExceptionFieldCheck<>(config)); + FieldInspector inspector = new FieldInspector<>( + context.getType(), + context.getConfiguration() + ); + inspector.check(new NullPointerExceptionFieldCheck<>(context)); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java index fdfd2ff6d..90b104ccc 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java @@ -13,31 +13,33 @@ import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; -import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; public class RecordChecker implements Checker { - private final Configuration config; + private final Context context; - public RecordChecker(Configuration config) { - this.config = config; + public RecordChecker(Context context) { + this.context = context; } @Override public void check() { - ClassProbe probe = config.getClassProbe(); + ClassProbe probe = context.getClassProbe(); if (!probe.isRecord()) { return; } - SubjectCreator subjectCreator = config.getSubjectCreator(); + SubjectCreator subjectCreator = context.getSubjectCreator(); verifyRecordPrecondition(ObjectAccessor.of(subjectCreator.plain())); - verifyRecordPrecondition(ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted(config))); + verifyRecordPrecondition( + ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted(context.getConfiguration())) + ); } private void verifyRecordPrecondition(ObjectAccessor originalAccessor) { - Class type = config.getType(); + Class type = context.getType(); T original = originalAccessor.get(); T copy = originalAccessor.copy(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java index 5244d967e..0da257cc4 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java @@ -9,7 +9,7 @@ import java.util.Set; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; -import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; public class SignatureChecker implements Checker { @@ -18,10 +18,10 @@ public class SignatureChecker implements Checker { private final ClassProbe classProbe; private final Set warningsToSuppress; - public SignatureChecker(Configuration config) { - this.type = config.getType(); - this.classProbe = config.getClassProbe(); - this.warningsToSuppress = config.getWarningsToSuppress(); + public SignatureChecker(Context context) { + this.type = context.getType(); + this.classProbe = context.getClassProbe(); + this.warningsToSuppress = context.getConfiguration().getWarningsToSuppress(); } @Override diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index 9f1f79678..7d4813e61 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -16,6 +16,7 @@ import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; public class JpaLazyGetterFieldCheck implements FieldCheck { @@ -28,11 +29,13 @@ public class JpaLazyGetterFieldCheck implements FieldCheck { private final Function fieldnameToGetter; private final boolean strictHashcode; - public JpaLazyGetterFieldCheck(Configuration config) { - this.subjectCreator = config.getSubjectCreator(); - this.instanceCreator = config.getInstanceCreator(); - this.type = config.getType(); - this.classProbe = config.getClassProbe(); + public JpaLazyGetterFieldCheck(Context context) { + this.subjectCreator = context.getSubjectCreator(); + this.instanceCreator = context.getInstanceCreator(); + this.type = context.getType(); + this.classProbe = context.getClassProbe(); + + Configuration config = context.getConfiguration(); this.annotationCache = config.getAnnotationCache(); this.fieldnameToGetter = config.getFieldnameToGetter(); this.strictHashcode = config.getWarningsToSuppress().contains(Warning.STRICT_HASHCODE); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java index d541b74de..d14243332 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java @@ -11,6 +11,7 @@ import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.NonnullAnnotationVerifier; import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; @SuppressFBWarnings( @@ -22,9 +23,9 @@ public class NullPointerExceptionFieldCheck implements FieldCheck { private final Configuration config; private final SubjectCreator subjectCreator; - public NullPointerExceptionFieldCheck(Configuration config) { - this.config = config; - this.subjectCreator = config.getSubjectCreator(); + public NullPointerExceptionFieldCheck(Context context) { + this.config = context.getConfiguration(); + this.subjectCreator = context.getSubjectCreator(); } @Override diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index c4199cb96..692bce427 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -15,6 +15,7 @@ import nl.jqno.equalsverifier.internal.reflection.annotations.NonnullAnnotationVerifier; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; public class ReflexivityFieldCheck implements FieldCheck { @@ -26,10 +27,12 @@ public class ReflexivityFieldCheck implements FieldCheck { private final Set nonnullFields; private final AnnotationCache annotationCache; - public ReflexivityFieldCheck(Configuration config) { + public ReflexivityFieldCheck(Context context) { + this.subjectCreator = context.getSubjectCreator(); + this.instanceCreator = context.getInstanceCreator(); + + Configuration config = context.getConfiguration(); this.typeTag = config.getTypeTag(); - this.subjectCreator = config.getSubjectCreator(); - this.instanceCreator = config.getInstanceCreator(); this.warningsToSuppress = config.getWarningsToSuppress(); this.nonnullFields = config.getNonnullFields(); this.annotationCache = config.getAnnotationCache(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java index fe978635b..8153c0f6b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java @@ -27,11 +27,11 @@ public class SignificantFieldCheck implements FieldCheck { private final Predicate isCachedHashCodeField; public SignificantFieldCheck( - Configuration config, + Context context, Predicate isCachedHashCodeField ) { - this.config = config; - this.subjectCreator = config.getSubjectCreator(); + this.subjectCreator = context.getSubjectCreator(); + this.config = context.getConfiguration(); this.type = config.getType(); this.warningsToSuppress = config.getWarningsToSuppress(); this.ignoredFields = config.getIgnoredFields(); @@ -57,6 +57,7 @@ public void execute(FieldProbe fieldProbe) { ); if (fieldProbe.canBeDefault()) { checkValues( + // TODO: Configuration weghalen als field? subjectCreator.withAllFieldsDefaulted(config), subjectCreator.withAllFieldsDefaulted(config), subjectCreator.withAllFieldsDefaultedExcept(fieldProbe.getField()), diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index f2f5d50ef..e07a750cb 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -6,7 +6,6 @@ import java.util.function.Function; import java.util.stream.Collectors; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.instantiation.*; import nl.jqno.equalsverifier.internal.prefabvalues.*; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.*; @@ -34,10 +33,6 @@ public final class Configuration { private final List equalExamples; private final List unequalExamples; - private final SubjectCreator subjectCreator; - private final InstanceCreator instanceCreator; - private final ClassProbe classProbe; - // CHECKSTYLE OFF: ParameterNumber private Configuration( Class type, @@ -71,9 +66,6 @@ private Configuration( this.fieldnameToGetter = fieldnameToGetter; this.equalExamples = equalExamples; this.unequalExamples = unequalExamples; - this.classProbe = new ClassProbe<>(type); - this.instanceCreator = new VintageInstanceCreator(prefabValues); - this.subjectCreator = new ModernSubjectCreator<>(typeTag, instanceCreator, classProbe); } public static Configuration build( @@ -283,16 +275,4 @@ public AnnotationCache getAnnotationCache() { public Set getIgnoredFields() { return Collections.unmodifiableSet(ignoredFields); } - - public SubjectCreator getSubjectCreator() { - return subjectCreator; - } - - public InstanceCreator getInstanceCreator() { - return instanceCreator; - } - - public ClassProbe getClassProbe() { - return classProbe; - } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java new file mode 100644 index 000000000..c9ff905d8 --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -0,0 +1,41 @@ +package nl.jqno.equalsverifier.internal.util; + +import nl.jqno.equalsverifier.internal.instantiation.*; + +public final class Context { + + private final Class type; + private final Configuration configuration; + private final ClassProbe classProbe; + private final SubjectCreator subjectCreator; + private final InstanceCreator instanceCreator; + + public Context(Configuration configuration) { + this.type = configuration.getType(); + this.configuration = configuration; + this.classProbe = new ClassProbe<>(configuration.getType()); + this.instanceCreator = new VintageInstanceCreator(configuration.getPrefabValues()); + this.subjectCreator = + new ModernSubjectCreator<>(configuration.getTypeTag(), instanceCreator, classProbe); + } + + public Class getType() { + return type; + } + + public Configuration getConfiguration() { + return configuration; + } + + public ClassProbe getClassProbe() { + return classProbe; + } + + public InstanceCreator getInstanceCreator() { + return instanceCreator; + } + + public SubjectCreator getSubjectCreator() { + return subjectCreator; + } +} From 2090d659ceb3e51a4b263200d72a8b87d66e3b16 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 6 Sep 2024 09:59:25 +0200 Subject: [PATCH 17/74] Removes Configuration from SubjectCreator method signature --- .../internal/checkers/HierarchyChecker.java | 4 +--- .../internal/checkers/RecordChecker.java | 4 +--- .../checkers/fieldchecks/SignificantFieldCheck.java | 8 +++----- .../internal/instantiation/ModernSubjectCreator.java | 3 +-- .../internal/instantiation/SubjectCreator.java | 3 +-- .../internal/instantiation/VintageSubjectCreator.java | 10 ++++++++-- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java index 45af90e77..42463b12e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java @@ -89,9 +89,7 @@ private void checkSuperclass() { } } else { safelyCheckSuperProperties(ObjectAccessor.of(subjectCreator.plain())); - safelyCheckSuperProperties( - ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted(config)) - ); + safelyCheckSuperProperties(ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted())); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java index 90b104ccc..8dc3e012e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java @@ -33,9 +33,7 @@ public void check() { SubjectCreator subjectCreator = context.getSubjectCreator(); verifyRecordPrecondition(ObjectAccessor.of(subjectCreator.plain())); - verifyRecordPrecondition( - ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted(context.getConfiguration())) - ); + verifyRecordPrecondition(ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted())); } private void verifyRecordPrecondition(ObjectAccessor originalAccessor) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java index 8153c0f6b..a5e465b8c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java @@ -17,7 +17,6 @@ public class SignificantFieldCheck implements FieldCheck { - private final Configuration config; private final SubjectCreator subjectCreator; private final Class type; private final EnumSet warningsToSuppress; @@ -31,7 +30,7 @@ public SignificantFieldCheck( Predicate isCachedHashCodeField ) { this.subjectCreator = context.getSubjectCreator(); - this.config = context.getConfiguration(); + Configuration config = context.getConfiguration(); this.type = config.getType(); this.warningsToSuppress = config.getWarningsToSuppress(); this.ignoredFields = config.getIgnoredFields(); @@ -57,9 +56,8 @@ public void execute(FieldProbe fieldProbe) { ); if (fieldProbe.canBeDefault()) { checkValues( - // TODO: Configuration weghalen als field? - subjectCreator.withAllFieldsDefaulted(config), - subjectCreator.withAllFieldsDefaulted(config), + subjectCreator.withAllFieldsDefaulted(), + subjectCreator.withAllFieldsDefaulted(), subjectCreator.withAllFieldsDefaultedExcept(fieldProbe.getField()), fieldProbe, true diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index e0bf4afb2..b7dc77faf 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -8,7 +8,6 @@ import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; -import nl.jqno.equalsverifier.internal.util.Configuration; public class ModernSubjectCreator implements SubjectCreator { @@ -37,7 +36,7 @@ public T withFieldDefaulted(Field field) { } @Override - public T withAllFieldsDefaulted(Configuration config) { + public T withAllFieldsDefaulted() { Map values = empty(); for (Field f : fields()) { values.put(f, null); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index 5efda9ba2..5c664cc56 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -1,12 +1,11 @@ package nl.jqno.equalsverifier.internal.instantiation; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.util.Configuration; public interface SubjectCreator { T plain(); T withFieldDefaulted(Field field); - T withAllFieldsDefaulted(Configuration config); + T withAllFieldsDefaulted(); T withAllFieldsDefaultedExcept(Field field); T withFieldSetTo(Field field, Object value); T withFieldChanged(Field field); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java index eda225af4..a425917b0 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java @@ -13,14 +13,20 @@ public class VintageSubjectCreator implements SubjectCreator { private final TypeTag typeTag; + private final Configuration config; private final PrefabValues prefabValues; @SuppressFBWarnings( value = "EI_EXPOSE_REP2", justification = "PrefabValues is inherently mutable." ) - public VintageSubjectCreator(TypeTag typeTag, PrefabValues prefabValues) { + public VintageSubjectCreator( + TypeTag typeTag, + Configuration config, + PrefabValues prefabValues + ) { this.typeTag = typeTag; + this.config = config; this.prefabValues = prefabValues; } @@ -35,7 +41,7 @@ public T withFieldDefaulted(Field field) { } @Override - public T withAllFieldsDefaulted(Configuration config) { + public T withAllFieldsDefaulted() { return withAllFields((acc, f) -> FieldProbe.of(f, config).canBeDefault() ? acc.withDefaultedField(f) : acc ); From 37b26c1b3ac1ffbcb690b30c4a8ad6459ffdd0bb Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 6 Sep 2024 10:12:34 +0200 Subject: [PATCH 18/74] Lets ModernSubjectCreator check nullability --- .../internal/instantiation/ModernSubjectCreator.java | 10 ++++++++-- .../nl/jqno/equalsverifier/internal/util/Context.java | 7 ++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index b7dc77faf..41ce676cf 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -8,19 +8,23 @@ import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.util.Configuration; public class ModernSubjectCreator implements SubjectCreator { private final TypeTag typeTag; + private final Configuration config; private final InstanceCreator instanceCreator; private final ClassProbe classProbe; public ModernSubjectCreator( TypeTag typeTag, + Configuration config, InstanceCreator instanceCreator, ClassProbe classProbe ) { this.typeTag = typeTag; + this.config = config; this.instanceCreator = instanceCreator; this.classProbe = classProbe; } @@ -78,7 +82,10 @@ public T withAllFieldsChanged() { private T createInstance(Map values) { for (Field f : fields()) { - if (!values.containsKey(f)) { + boolean fieldIsAbsent = !values.containsKey(f); + boolean fieldCannotBeNull = + values.get(f) == null && !FieldProbe.of(f, config).canBeDefault(); + if (fieldIsAbsent || fieldCannotBeNull) { Object value = instantiate(f).getRed(); values.put(f, value); } @@ -93,7 +100,6 @@ private T createInstance(Map values) { for (Field f : values.keySet()) { Object value = values.get(f); if (value == null) { - // TODO if fieldProbe.canBeDefault()... accessor.withDefaultedField(f); } else { accessor.withFieldSetTo(f, value); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index c9ff905d8..e11ce831a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -16,7 +16,12 @@ public Context(Configuration configuration) { this.classProbe = new ClassProbe<>(configuration.getType()); this.instanceCreator = new VintageInstanceCreator(configuration.getPrefabValues()); this.subjectCreator = - new ModernSubjectCreator<>(configuration.getTypeTag(), instanceCreator, classProbe); + new ModernSubjectCreator<>( + configuration.getTypeTag(), + configuration, + instanceCreator, + classProbe + ); } public Class getType() { From acb235f47575b54a0416d547b22abb3735fa969f Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 6 Sep 2024 10:56:56 +0200 Subject: [PATCH 19/74] Fixes remaining non-record issues with ModernSubjectCreator --- .../equalsverifier/internal/instantiation/FieldProbe.java | 5 +++++ .../internal/instantiation/ModernSubjectCreator.java | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java index 6ed788778..3e0605569 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java @@ -4,6 +4,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.Set; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; @@ -56,6 +57,10 @@ public boolean fieldIsPrimitive() { return getType().isPrimitive(); } + public boolean fieldIsStatic() { + return Modifier.isStatic(field.getModifiers()); + } + public boolean canBeDefault() { if (fieldIsPrimitive()) { return !isWarningZeroSuppressed; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index 41ce676cf..1811d2324 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -66,6 +66,9 @@ public T withFieldSetTo(Field field, Object value) { @Override public T withFieldChanged(Field field) { + if (FieldProbe.of(field, config).fieldIsStatic()) { + return plain(); + } Object value = instantiate(field).getBlue(); return createInstance(with(field, value)); } @@ -97,7 +100,7 @@ private T createInstance(Map values) { } else { T instance = Instantiator.of(typeTag.getType()).instantiate(); ObjectAccessor accessor = ObjectAccessor.of(instance); - for (Field f : values.keySet()) { + for (Field f : fields()) { Object value = values.get(f); if (value == null) { accessor.withDefaultedField(f); From 9021ec2dc31bdc38ac0a672dd50e448aca621b88 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 6 Sep 2024 13:18:29 +0200 Subject: [PATCH 20/74] Partially implements records in ModernSubjectCreator --- .../instantiation/ModernSubjectCreator.java | 14 +-- .../internal/instantiation/RecordProbe.java | 86 +++++++++++++++++++ 2 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index 1811d2324..f3d2c6d63 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -1,8 +1,7 @@ package nl.jqno.equalsverifier.internal.instantiation; import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; @@ -94,11 +93,16 @@ private T createInstance(Map values) { } } - // maak een instance met veld-waardes uit `values`: kijk af uit FallbackFactory + Class type = typeTag.getType(); if (classProbe.isRecord()) { - return null; + List params = new ArrayList<>(); + for (Field f : fields()) { + params.add(values.get(f)); + } + RecordProbe recordProbe = new RecordProbe<>(type); + return recordProbe.callRecordConstructor(params); } else { - T instance = Instantiator.of(typeTag.getType()).instantiate(); + T instance = Instantiator.of(type).instantiate(); ObjectAccessor accessor = ObjectAccessor.of(instance); for (Field f : fields()) { Object value = values.get(f); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java new file mode 100644 index 000000000..ec3ded6f6 --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java @@ -0,0 +1,86 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; + +public class RecordProbe { + + private final Class type; + + public RecordProbe(Class type) { + this.type = type; + } + + public T callRecordConstructor(List params) { + Constructor constructor = getRecordConstructor(); + return rethrow( + () -> constructor.newInstance(params.toArray(new Object[0])), + e -> buildMessage(e, params) + ); + } + + private Constructor getRecordConstructor() { + return rethrow(() -> { + List> constructorTypes = fields() + .map(Field::getType) + .collect(Collectors.toList()); + Constructor result = type.getDeclaredConstructor( + constructorTypes.toArray(new Class[0]) + ); + result.setAccessible(true); + return result; + }); + } + + private Stream fields() { + return StreamSupport.stream(FieldIterable.ofIgnoringStatic(type).spliterator(), false); + } + + private String buildMessage(Throwable e, List params) { + String prefix = + "Record: failed to run constructor for record type " + + type.getName() + + "\n These were the values passed to the constructor: " + + params; + + if (e.getCause() instanceof NullPointerException) { + return ( + prefix + + "\n If the record does not accept null values for its constructor parameters," + + " consider suppressing Warning.NULL_FIELDS." + ); + } + + boolean hasZeros = false; + boolean hasSomethingElse = false; + for (Object p : params) { + if (PrimitiveMappers.ZEROS.contains(p)) { + hasZeros = true; + } else { + // nulls are already eliminated + hasSomethingElse = true; + } + } + + String msg = prefix; + if (hasZeros) { + msg += + "\n If the record does not accept 0 or false as a value for its constructor parameters," + + " consider suppressing Warning.ZERO_FIELDS."; + } + if (hasSomethingElse) { + msg += + "\n If the record does not accept any of the given values for its constructor parameters," + + " consider providing prefab values for the types of those fields."; + } + return msg; + } +} From ac63686f5b1550f841ead25f28a6ef99210a02b1 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 6 Sep 2024 13:27:39 +0200 Subject: [PATCH 21/74] Accounts for primitive values in records --- .../internal/instantiation/ModernSubjectCreator.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index f3d2c6d63..a28be9df6 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -8,6 +8,7 @@ import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; public class ModernSubjectCreator implements SubjectCreator { @@ -97,7 +98,13 @@ private T createInstance(Map values) { if (classProbe.isRecord()) { List params = new ArrayList<>(); for (Field f : fields()) { - params.add(values.get(f)); + Object value = values.get(f); + if (value == null) { + Object def = PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(f.getType()); + params.add(def); + } else { + params.add(value); + } } RecordProbe recordProbe = new RecordProbe<>(type); return recordProbe.callRecordConstructor(params); From bd66a102ba44644e648cc67796389f6c7670640d Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 6 Sep 2024 13:38:11 +0200 Subject: [PATCH 22/74] Tidies up RecordObjectAccessor --- .../internal/instantiation/RecordProbe.java | 8 +- .../reflection/RecordObjectAccessor.java | 76 ++----------------- 2 files changed, 11 insertions(+), 73 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java index ec3ded6f6..65acbfc4d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java @@ -19,6 +19,10 @@ public RecordProbe(Class type) { this.type = type; } + public Stream fields() { + return StreamSupport.stream(FieldIterable.ofIgnoringStatic(type).spliterator(), false); + } + public T callRecordConstructor(List params) { Constructor constructor = getRecordConstructor(); return rethrow( @@ -40,10 +44,6 @@ private Constructor getRecordConstructor() { }); } - private Stream fields() { - return StreamSupport.stream(FieldIterable.ofIgnoringStatic(type).spliterator(), false); - } - private String buildMessage(Throwable e, List params) { String prefix = "Record: failed to run constructor for record type " + diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessor.java index 600586fad..7fd4a142d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessor.java @@ -1,17 +1,13 @@ package nl.jqno.equalsverifier.internal.reflection; -import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; - -import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.LinkedHashSet; import java.util.List; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; +import nl.jqno.equalsverifier.internal.instantiation.RecordProbe; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; @@ -25,18 +21,18 @@ */ final class RecordObjectAccessor extends ObjectAccessor { - private final Constructor constructor; + private final RecordProbe probe; /** Package-private constructor. Call {@link ObjectAccessor#of(Object)} to instantiate. */ /* default */RecordObjectAccessor(T object, Class type) { super(object, type); - this.constructor = getRecordConstructor(); + this.probe = new RecordProbe<>(type); } /** {@inheritDoc} */ @Override public T copy() { - List params = fields().map(this::getField).collect(Collectors.toList()); + List params = probe.fields().map(this::getField).collect(Collectors.toList()); return callRecordConstructor(params); } @@ -120,71 +116,13 @@ private ObjectAccessor modify(Field field, Object value) { } private ObjectAccessor makeAccessor(Function determineValue) { - List params = fields().map(determineValue).collect(Collectors.toList()); + List params = probe.fields().map(determineValue).collect(Collectors.toList()); T newObject = callRecordConstructor(params); return ObjectAccessor.of(newObject); } - private Stream fields() { - return StreamSupport.stream(FieldIterable.ofIgnoringStatic(type()).spliterator(), false); - } - - private Constructor getRecordConstructor() { - return rethrow(() -> { - List> constructorTypes = fields() - .map(Field::getType) - .collect(Collectors.toList()); - Constructor result = type() - .getDeclaredConstructor(constructorTypes.toArray(new Class[0])); - result.setAccessible(true); - return result; - }); - } - private T callRecordConstructor(List params) { - return rethrow( - () -> constructor.newInstance(params.toArray(new Object[0])), - e -> buildMessage(e, constructor.getDeclaringClass(), params) - ); - } - - private String buildMessage(Throwable e, Class type, List params) { - String prefix = - "Record: failed to run constructor for record type " + - type.getName() + - "\n These were the values passed to the constructor: " + - params; - - if (e.getCause() instanceof NullPointerException) { - return ( - prefix + - "\n If the record does not accept null values for its constructor parameters," + - " consider suppressing Warning.NULL_FIELDS." - ); - } - - boolean hasZeros = false; - boolean hasSomethingElse = false; - for (Object p : params) { - if (PrimitiveMappers.ZEROS.contains(p)) { - hasZeros = true; - } else { - // nulls are already eliminated - hasSomethingElse = true; - } - } - - String msg = prefix; - if (hasZeros) { - msg += - "\n If the record does not accept 0 or false as a value for its constructor parameters," + - " consider suppressing Warning.ZERO_FIELDS."; - } - if (hasSomethingElse) { - msg += - "\n If the record does not accept any of the given values for its constructor parameters," + - " consider providing prefab values for the types of those fields."; - } - return msg; + RecordProbe p = new RecordProbe<>(type()); + return p.callRecordConstructor(params); } } From f822584e3a85716164c734dcc56942aa0ffbd0af Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 9 Sep 2024 09:56:06 +0200 Subject: [PATCH 23/74] Makes a field final --- .../internal/prefabvalues/factories/CopyFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java index 1ab9660b1..9190cb482 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java @@ -9,7 +9,7 @@ public class CopyFactory extends AbstractGenericFactory { private final Class source; - private Function copy; + private final Function copy; public CopyFactory(Class source, Function copy) { this.source = source; From 7504f6df953faa0cbecb80d5f05d528b45817d4a Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Wed, 11 Sep 2024 19:25:18 +0200 Subject: [PATCH 24/74] Adds tests and javadoc for ClassProbe and FieldProbe --- .../internal/instantiation/ClassProbe.java | 3 + .../internal/instantiation/FieldProbe.java | 61 +++++++- .../instantiation/ClassProbeTest.java | 148 ++++++++++++++++++ .../instantiation/FieldProbeTest.java | 128 +++++++++++++++ .../internal/util/ConfigurationHelper.java | 58 +++++++ .../testhelpers/types/TypeHelper.java | 6 + 6 files changed, 402 insertions(+), 2 deletions(-) create mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbeTest.java create mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java create mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java index 3cf1148aa..c8a239857 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java @@ -7,6 +7,9 @@ import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; import nl.jqno.equalsverifier.internal.reflection.SealedTypesHelper; +/** + * Provides read-only reflective access to a class. + */ public class ClassProbe { private final Class type; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java index 3e0605569..c379cfcea 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java @@ -1,5 +1,6 @@ package nl.jqno.equalsverifier.internal.instantiation; +import static nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations.*; import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -7,10 +8,13 @@ import java.lang.reflect.Modifier; import java.util.Set; import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; -import nl.jqno.equalsverifier.internal.reflection.annotations.NonnullAnnotationVerifier; import nl.jqno.equalsverifier.internal.util.Configuration; +/** + * Provides read-only reflective access to one field of an object. + */ public final class FieldProbe { private final Field field; @@ -19,6 +23,7 @@ public final class FieldProbe { private final Set nonnullFields; private final AnnotationCache annotationCache; + /** Private constructor. Call {@link #of(Field, Configuration)} to instantiate. */ private FieldProbe(Field field, Configuration config) { this.field = field; this.isWarningZeroSuppressed = config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS); @@ -27,15 +32,30 @@ private FieldProbe(Field field, Configuration config) { this.annotationCache = config.getAnnotationCache(); } + /** + * Factory method. + * + * @param field The field to access. + * @param config A configuration object; cannot be null. + * @return A {@link FieldProbe} for {@link #field}. + */ public static FieldProbe of(Field field, Configuration config) { return new FieldProbe(field, config); } + /** @return The field itself. */ @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "Can't defensively copy a Field.") public Field getField() { return field; } + /** + * Tries to get the field's value. + * + * @param object The object that contains the field whose value we want to get. + * @return The field's value. + * @throws ReflectionException If the operation fails. + */ @SuppressFBWarnings( value = "DP_DO_INSIDE_DO_PRIVILEGED", justification = "Only called in test code, not production." @@ -45,29 +65,66 @@ public Object getValue(Object object) { return rethrow(() -> field.get(object)); } + /** @return The field's type. */ public Class getType() { return field.getType(); } + /** @return The field's name. */ public String getName() { return field.getName(); } + /** @return Whether the field is of a primitive type. */ public boolean fieldIsPrimitive() { return getType().isPrimitive(); } + /** @return Whether the field is marked with the static modifier. */ public boolean fieldIsStatic() { return Modifier.isStatic(field.getModifiers()); } + /** @return Whether the field can be set to the default value for its type. */ public boolean canBeDefault() { if (fieldIsPrimitive()) { return !isWarningZeroSuppressed; } - boolean isAnnotated = NonnullAnnotationVerifier.fieldIsNonnull(field, annotationCache); + boolean isAnnotated = isNonnull(field, annotationCache); boolean isMentionedExplicitly = nonnullFields.contains(field.getName()); return !isWarningNullSuppressed && !isAnnotated && !isMentionedExplicitly; } + + /** + * Checks whether the given field is marked with an Nonnull annotation, whether directly, or + * through some default annotation mechanism. + * + * @param field The field to be checked. + * @param annotationCache To provide access to the annotations on the field and the field's + * class + * @return True if the field is to be treated as Nonnull. + */ + public static boolean isNonnull(Field field, AnnotationCache annotationCache) { + Class type = field.getDeclaringClass(); + if (annotationCache.hasFieldAnnotation(type, field.getName(), NONNULL)) { + return true; + } + if (annotationCache.hasFieldAnnotation(type, field.getName(), NULLABLE)) { + return false; + } + boolean hasFindbugsAnnotation = annotationCache.hasClassAnnotation( + type, + FINDBUGS1X_DEFAULT_ANNOTATION_NONNULL + ); + boolean hasJsr305Annotation = annotationCache.hasClassAnnotation( + type, + JSR305_DEFAULT_ANNOTATION_NONNULL + ); + boolean hasDefaultAnnotation = annotationCache.hasClassAnnotation( + type, + DEFAULT_ANNOTATION_NONNULL + ); + return hasFindbugsAnnotation || hasJsr305Annotation || hasDefaultAnnotation; + } } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbeTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbeTest.java new file mode 100644 index 000000000..012956bc5 --- /dev/null +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbeTest.java @@ -0,0 +1,148 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import static org.junit.jupiter.api.Assertions.*; + +import nl.jqno.equalsverifier.testhelpers.types.ColorPoint3D; +import nl.jqno.equalsverifier.testhelpers.types.Point3D; +import nl.jqno.equalsverifier.testhelpers.types.PointContainer; +import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.AbstractEqualsAndHashCode; +import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.Empty; +import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.NoFieldsSubWithFields; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class ClassProbeTest { + + private ClassProbe pointProbe; + private ClassProbe abstractProbe; + + @BeforeEach + public void setup() { + pointProbe = new ClassProbe<>(PointContainer.class); + abstractProbe = new ClassProbe<>(AbstractEqualsAndHashCode.class); + } + + @Test + public void getType() { + assertSame(PointContainer.class, pointProbe.getType()); + } + + /* Tests the false case. The true case is tested in {@link ClassProbeCompilerTest}. */ + @Test + public void isRecord() { + assertFalse(pointProbe.isRecord()); + } + + /* Tests the false case. The true case is tested in {@link ClassProbeSealedTest}. */ + @Test + public void isSealed() { + assertFalse(pointProbe.isSealed()); + } + + @Test + public void declaresEquals() { + assertTrue(pointProbe.declaresEquals()); + assertTrue(abstractProbe.declaresEquals()); + } + + @Test + public void doesNotDeclareEquals() { + ClassProbe accessor = new ClassProbe<>(Empty.class); + assertFalse(accessor.declaresEquals()); + } + + @Test + public void declaresHashCode() { + assertTrue(pointProbe.declaresHashCode()); + assertTrue(abstractProbe.declaresHashCode()); + } + + @Test + public void doesNotDeclareHashCode() { + ClassProbe accessor = new ClassProbe<>(Empty.class); + assertFalse(accessor.declaresHashCode()); + } + + @Test + public void hasMethod() { + ClassProbe accessor = new ClassProbe<>(MethodContainer.class); + assertTrue(accessor.hasMethod("m")); + } + + @Test + public void hasProtectedMethod() { + ClassProbe accessor = new ClassProbe<>(MethodContainer.class); + assertTrue(accessor.hasMethod("m_protected")); + } + + @Test + public void hasMethodInSuper() { + ClassProbe accessor = new ClassProbe<>(ChildOfMethodContainer.class); + assertTrue(accessor.hasMethod("m")); + } + + @Test + public void hasProtectedMethodInSuper() { + ClassProbe accessor = new ClassProbe<>(ChildOfMethodContainer.class); + assertTrue(accessor.hasMethod("m_protected")); + } + + @Test + public void doesNotHaveMethod() { + ClassProbe accessor = new ClassProbe<>(MethodContainer.class); + assertFalse(accessor.hasMethod("doesNotExist")); + } + + @Test + public void equalsIsNotAbstract() { + assertFalse(pointProbe.isEqualsAbstract()); + } + + @Test + public void equalsIsAbstract() { + assertTrue(abstractProbe.isEqualsAbstract()); + } + + @Test + public void hashCodeIsNotAbstract() { + assertFalse(pointProbe.isHashCodeAbstract()); + } + + @Test + public void hashCodeIsAbstract() { + assertTrue(abstractProbe.isHashCodeAbstract()); + } + + @Test + public void equalsIsInheritedFromObject() { + ClassProbe accessor = new ClassProbe<>(NoFieldsSubWithFields.class); + assertTrue(accessor.isEqualsInheritedFromObject()); + } + + @Test + public void equalsIsNotInheritedFromObject() { + assertFalse(pointProbe.isEqualsInheritedFromObject()); + } + + @Test + public void getSuperAccessorForPojo() { + ClassProbe superAccessor = pointProbe.getSuperProbe(); + assertEquals(Object.class, superAccessor.getType()); + } + + @Test + public void getSuperAccessorInHierarchy() { + ClassProbe accessor = new ClassProbe<>(ColorPoint3D.class); + ClassProbe superAccessor = accessor.getSuperProbe(); + assertEquals(Point3D.class, superAccessor.getType()); + } + + static class MethodContainer { + + public void m() {} + + protected void m_protected() {} + } + + static class ChildOfMethodContainer extends MethodContainer {} +} diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java new file mode 100644 index 000000000..1016d46f8 --- /dev/null +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java @@ -0,0 +1,128 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import static org.junit.jupiter.api.Assertions.*; + +import java.lang.reflect.Field; +import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.ConfigurationHelper; +import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.*; +import org.junit.jupiter.api.Test; + +public class FieldProbeTest { + + private static final String FIELD_NAME = "field"; + + @Test + public void getField() throws NoSuchFieldException { + ObjectContainer foo = new ObjectContainer(); + Field field = foo.getClass().getDeclaredField(FIELD_NAME); + FieldProbe probe = FieldProbe.of( + field, + ConfigurationHelper.emptyConfiguration(ObjectContainer.class) + ); + assertSame(field, probe.getField()); + } + + @Test + public void getType() { + ObjectContainer foo = new ObjectContainer(); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertEquals(Object.class, probe.getType()); + } + + @Test + public void getName() { + ObjectContainer foo = new ObjectContainer(); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertEquals(FIELD_NAME, probe.getName()); + } + + @Test + public void isNotPrimitive() { + ObjectContainer foo = new ObjectContainer(); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertFalse(probe.fieldIsPrimitive()); + } + + @Test + public void isPrimitive() { + PrimitiveContainer foo = new PrimitiveContainer(); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertTrue(probe.fieldIsPrimitive()); + } + + @Test + public void isNotStatic() { + ObjectContainer foo = new ObjectContainer(); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertFalse(probe.fieldIsStatic()); + } + + @Test + public void isStatic() { + StaticContainer foo = new StaticContainer(); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertTrue(probe.fieldIsStatic()); + } + + @Test + public void canBeDefault_forObject() { + ObjectContainer foo = new ObjectContainer(); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertTrue(probe.canBeDefault()); + } + + @Test + public void canBeDefault_primitive() { + PrimitiveContainer foo = new PrimitiveContainer(); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertTrue(probe.canBeDefault()); + } + + @Test + public void canBeDefault_primitiveWithWarningSuppressed() { + PrimitiveContainer foo = new PrimitiveContainer(); + Configuration config = ConfigurationHelper.emptyConfiguration( + foo.getClass(), + Warning.ZERO_FIELDS + ); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME, config); + assertFalse(probe.canBeDefault()); + } + + @Test + public void canBeDefault_isMentionedExplicitly() { + ObjectContainer foo = new ObjectContainer(); + Configuration config = ConfigurationHelper.emptyConfigurationWithNonnullFields( + foo.getClass(), + FIELD_NAME + ); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME, config); + assertFalse(probe.canBeDefault()); + } + + @Test + public void canBeDefault_annotated() { + NonNullContainer foo = new NonNullContainer(); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertFalse(probe.canBeDefault()); + } + + private FieldProbe getAccessorFor(Object object, String fieldName) { + return getAccessorFor( + object, + fieldName, + ConfigurationHelper.emptyConfiguration(object.getClass()) + ); + } + + private FieldProbe getAccessorFor(Object object, String fieldName, Configuration config) { + try { + Field field = object.getClass().getDeclaredField(fieldName); + return FieldProbe.of(field, config); + } catch (NoSuchFieldException e) { + throw new IllegalArgumentException("fieldName: " + fieldName); + } + } +} diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java new file mode 100644 index 000000000..c8ad85b9d --- /dev/null +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java @@ -0,0 +1,58 @@ +package nl.jqno.equalsverifier.internal.util; + +import java.util.*; +import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; + +public final class ConfigurationHelper { + + private ConfigurationHelper() {} + + public static final Configuration emptyConfiguration( + Class type, + Warning... warnings + ) { + return Configuration.build( + type, + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + null, + false, + null, + false, + warnings.length == 0 + ? EnumSet.noneOf(Warning.class) + : EnumSet.copyOf(Arrays.asList(warnings)), + null, + new FactoryCache(), + Collections.emptySet(), + Collections.emptySet(), + Collections.emptyList(), + Collections.emptyList() + ); + } + + public static final Configuration emptyConfigurationWithNonnullFields( + Class type, + String... fieldNames + ) { + return Configuration.build( + type, + Collections.emptySet(), + Collections.emptySet(), + new HashSet<>(Arrays.asList(fieldNames)), + null, + false, + null, + false, + EnumSet.noneOf(Warning.class), + null, + new FactoryCache(), + Collections.emptySet(), + Collections.emptySet(), + Collections.emptyList(), + Collections.emptyList() + ); + } +} diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/TypeHelper.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/TypeHelper.java index 3a69c625e..d953a9294 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/TypeHelper.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/TypeHelper.java @@ -266,6 +266,12 @@ public static final class PrimitiveContainer { public int field; } + public static final class NonNullContainer { + + @NonNull + public Object field = new Object(); + } + public static final class StaticFinalContainer { public static final int CONST = 42; From a046ce4e104d7024aaa7b79247946d3b3ff0c798 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Wed, 11 Sep 2024 19:41:31 +0200 Subject: [PATCH 25/74] Folds NonnullAnnotationVerifier into FieldProbe --- .../NullPointerExceptionFieldCheck.java | 8 +- .../fieldchecks/ReflexivityFieldCheck.java | 3 +- .../internal/instantiation/FieldProbe.java | 7 +- .../internal/reflection/ClassAccessor.java | 57 ---------- .../reflection/ClassAccessorTest.java | 106 +----------------- .../NonnullAnnotationVerifierTest.java | 13 --- 6 files changed, 5 insertions(+), 189 deletions(-) delete mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/annotations/NonnullAnnotationVerifierTest.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java index d14243332..b363c37ba 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java @@ -9,7 +9,6 @@ import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldModifier; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; -import nl.jqno.equalsverifier.internal.reflection.annotations.NonnullAnnotationVerifier; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -36,12 +35,7 @@ public void execute(FieldProbe fieldProbe) { if (fieldProbe.fieldIsPrimitive()) { return; } - if ( - NonnullAnnotationVerifier.fieldIsNonnull( - fieldProbe.getField(), - config.getAnnotationCache() - ) - ) { + if (fieldProbe.isAnnotatedNonnull()) { return; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index 692bce427..6d4e5e610 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -12,7 +12,6 @@ import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; -import nl.jqno.equalsverifier.internal.reflection.annotations.NonnullAnnotationVerifier; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Context; @@ -96,7 +95,7 @@ private void checkNullReflexivity(FieldProbe fieldProbe) { } boolean nullWarningIsSuppressed = warningsToSuppress.contains(Warning.NULL_FIELDS); - boolean fieldIsNonNull = NonnullAnnotationVerifier.fieldIsNonnull(field, annotationCache); + boolean fieldIsNonNull = fieldProbe.isAnnotatedNonnull(); boolean fieldIsMentionedExplicitly = nonnullFields.contains(field.getName()); if (nullWarningIsSuppressed || fieldIsNonNull || fieldIsMentionedExplicitly) { return; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java index c379cfcea..8b56b201f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java @@ -91,7 +91,7 @@ public boolean canBeDefault() { return !isWarningZeroSuppressed; } - boolean isAnnotated = isNonnull(field, annotationCache); + boolean isAnnotated = isAnnotatedNonnull(); boolean isMentionedExplicitly = nonnullFields.contains(field.getName()); return !isWarningNullSuppressed && !isAnnotated && !isMentionedExplicitly; } @@ -100,12 +100,9 @@ public boolean canBeDefault() { * Checks whether the given field is marked with an Nonnull annotation, whether directly, or * through some default annotation mechanism. * - * @param field The field to be checked. - * @param annotationCache To provide access to the annotations on the field and the field's - * class * @return True if the field is to be treated as Nonnull. */ - public static boolean isNonnull(Field field, AnnotationCache annotationCache) { + public boolean isAnnotatedNonnull() { Class type = field.getDeclaringClass(); if (annotationCache.hasFieldAnnotation(type, field.getName(), NONNULL)) { return true; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java index 247645456..c3b0f3e69 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java @@ -5,12 +5,8 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.LinkedHashSet; -import java.util.Set; -import java.util.function.Predicate; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; -import nl.jqno.equalsverifier.internal.reflection.annotations.NonnullAnnotationVerifier; /** * Instantiates and populates objects of a given class. {@link ClassAccessor} can create two @@ -278,59 +274,6 @@ public ObjectAccessor getBlueAccessor( .scramble(prefabValues, enclosingType, typeStack); } - /** - * Returns an {@link ObjectAccessor} for an instance of T where all the fields are initialized - * to their default values. I.e., 0 for ints, and null for objects (except when the field is - * marked with a NonNull annotation). - * - * @param enclosingType Describes the type that contains this object as a field, to determine - * any generic parameters it may contain. - * @param isWarningNullSuppressed Whether reference fields must be non-null (a.k.a., whether - * Warnings.NULL_FIELDS is suppressed). - * @param isWarningZeroSuppressed Whether primitive fields must be non-0 (a.k.a., whether - * Warnings.ZERO_FIELDS is suppressed). - * @param nonnullFields Fields which are not allowed to be set to null. - * @param annotationCache To check for any NonNull annotations. - * @return An {@link ObjectAccessor} for an instance of T where all the fields are initialized - * to their default values. - */ - public ObjectAccessor getDefaultValuesAccessor( - TypeTag enclosingType, - boolean isWarningNullSuppressed, - boolean isWarningZeroSuppressed, - Set nonnullFields, - AnnotationCache annotationCache - ) { - Predicate canBeDefault = f -> - canBeDefault( - f, - enclosingType, - isWarningNullSuppressed, - isWarningZeroSuppressed, - nonnullFields, - annotationCache - ); - return buildObjectAccessor().clear(canBeDefault, prefabValues, enclosingType); - } - - private boolean canBeDefault( - Field f, - TypeTag enclosingType, - boolean isWarningNullSuppressed, - boolean isWarningZeroSuppressed, - Set nonnullFields, - AnnotationCache annotationCache - ) { - FieldAccessor accessor = FieldAccessor.of(f); - if (accessor.fieldIsPrimitive()) { - return !isWarningZeroSuppressed; - } - - boolean isAnnotated = NonnullAnnotationVerifier.fieldIsNonnull(f, annotationCache); - boolean isMentionedExplicitly = nonnullFields.contains(f.getName()); - return !isWarningNullSuppressed && !isAnnotated && !isMentionedExplicitly; - } - private ObjectAccessor buildObjectAccessor() { T object = Instantiator.of(type).instantiate(); return ObjectAccessor.of(object); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java index dd3d6e7da..249883112 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java @@ -4,16 +4,7 @@ import static org.junit.jupiter.api.Assertions.*; import java.lang.reflect.Field; -import java.util.HashSet; -import java.util.Set; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; -import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCacheBuilder; -import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; -import nl.jqno.equalsverifier.testhelpers.annotations.NonNull; +import nl.jqno.equalsverifier.internal.prefabvalues.*; import nl.jqno.equalsverifier.testhelpers.types.ColorPoint3D; import nl.jqno.equalsverifier.testhelpers.types.Point3D; import nl.jqno.equalsverifier.testhelpers.types.PointContainer; @@ -29,8 +20,6 @@ public class ClassAccessorTest { private PrefabValues prefabValues; private ClassAccessor pointContainerAccessor; private ClassAccessor abstractEqualsAndHashCodeAccessor; - private ClassAccessor defaultValuesClassAccessor; - private AnnotationCache defaultValuesAnnotationCache; @BeforeEach public void setup() { @@ -39,11 +28,6 @@ public void setup() { pointContainerAccessor = ClassAccessor.of(PointContainer.class, prefabValues); abstractEqualsAndHashCodeAccessor = ClassAccessor.of(AbstractEqualsAndHashCode.class, prefabValues); - defaultValuesClassAccessor = ClassAccessor.of(DefaultValues.class, prefabValues); - - defaultValuesAnnotationCache = new AnnotationCache(); - new AnnotationCacheBuilder(SupportedAnnotations.values(), new HashSet<>()) - .build(DefaultValues.class, defaultValuesAnnotationCache); } /* Tests the false case. The true case is tested in {@link ClassAccessorCompilerTest}. */ @@ -239,85 +223,6 @@ public void redAndBlueNotEqual() { assertFalse(red.equals(blue)); } - @Test - public void getDefaultValuesAccessor_withNoNonnullValues() { - ObjectAccessor objectAccessor = - defaultValuesClassAccessor.getDefaultValuesAccessor( - TypeTag.NULL, - false, - false, - new HashSet<>(), - defaultValuesAnnotationCache - ); - DefaultValues foo = objectAccessor.get(); - assertNull(foo.s); - // The rest is tested in getDefaultValuesObject - } - - @Test - public void getDefaultValuesAccessor_withOneNonnullValue() { - Set nonnullFields = new HashSet<>(); - nonnullFields.add("s"); - ObjectAccessor objectAccessor = - defaultValuesClassAccessor.getDefaultValuesAccessor( - TypeTag.NULL, - false, - false, - nonnullFields, - defaultValuesAnnotationCache - ); - DefaultValues foo = objectAccessor.get(); - assertNotNull(foo.s); - // The rest is tested in getDefaultValuesObject - } - - @Test - public void getDefaultValuesAccessor_whenNullWarningIsSuppressed() { - ObjectAccessor objectAccessor = - defaultValuesClassAccessor.getDefaultValuesAccessor( - TypeTag.NULL, - true, - false, - new HashSet<>(), - defaultValuesAnnotationCache - ); - DefaultValues foo = objectAccessor.get(); - assertNotNull(foo.s); - // The rest is tested in getDefaultValuesObject - } - - @Test - public void getDefaultValuesAccessor_whenZeroWarningIsSuppressed() { - ObjectAccessor objectAccessor = - defaultValuesClassAccessor.getDefaultValuesAccessor( - TypeTag.NULL, - false, - true, - new HashSet<>(), - defaultValuesAnnotationCache - ); - DefaultValues foo = objectAccessor.get(); - assertNotEquals(0, foo.i); - // The rest is tested in getDefaultValuesObject - } - - @Test - public void getDefaultValuesAccessor_objectContent() { - ClassAccessor accessor = ClassAccessor.of(DefaultValues.class, prefabValues); - DefaultValues foo = accessor - .getDefaultValuesAccessor( - TypeTag.NULL, - false, - false, - new HashSet<>(), - defaultValuesAnnotationCache - ) - .get(); - assertEquals(0, foo.i); - assertNull(foo.s); - assertNotNull(foo.t); - } - @Test public void instantiateAllTypes() { ClassAccessor.of(AllTypesContainer.class, prefabValues).getRedObject(TypeTag.NULL); @@ -358,15 +263,6 @@ private void assertObjectHasNoNullFields(PointContainer foo) { assertNotNull(foo.getPoint()); } - static class DefaultValues { - - int i; - String s; - - @NonNull - String t; - } - static class MethodContainer { public void m() {} diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/annotations/NonnullAnnotationVerifierTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/annotations/NonnullAnnotationVerifierTest.java deleted file mode 100644 index 90752a880..000000000 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/annotations/NonnullAnnotationVerifierTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.annotations; - -import static nl.jqno.equalsverifier.internal.testhelpers.Util.coverThePrivateConstructor; - -import org.junit.jupiter.api.Test; - -public class NonnullAnnotationVerifierTest { - - @Test - public void coverConstructor() { - coverThePrivateConstructor(NonnullAnnotationVerifier.class); - } -} From 4382c19ee6015ca06c61656082a7911d059a52bf Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Wed, 11 Sep 2024 19:50:27 +0200 Subject: [PATCH 26/74] Cleans up ClassAccessor --- .../reflection/ClassAccessorRecordTest.java | 28 ---- .../reflection/ClassProbeRecordTest.java | 17 +++ .../reflection/ClassAccessorSealedTest.java | 21 +-- .../internal/instantiation/ClassProbe.java | 3 +- .../internal/reflection/ClassAccessor.java | 136 ----------------- .../reflection/ClassAccessorTest.java | 142 +----------------- 6 files changed, 26 insertions(+), 321 deletions(-) delete mode 100644 equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorRecordTest.java create mode 100644 equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeRecordTest.java diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorRecordTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorRecordTest.java deleted file mode 100644 index 6d4f532bf..000000000 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorRecordTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class ClassAccessorRecordTest { - - private PrefabValues prefabValues; - - @BeforeEach - public void setup() { - FactoryCache factoryCache = JavaApiPrefabValues.build(); - prefabValues = new PrefabValues(factoryCache); - } - - @Test - public void isRecord() { - var accessor = ClassAccessor.of(SimpleRecord.class, prefabValues); - assertTrue(accessor.isRecord()); - } - - record SimpleRecord(int i) {} -} diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeRecordTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeRecordTest.java new file mode 100644 index 000000000..998914ad4 --- /dev/null +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeRecordTest.java @@ -0,0 +1,17 @@ +package nl.jqno.equalsverifier.internal.reflection; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; +import org.junit.jupiter.api.Test; + +public class ClassProbeRecordTest { + + @Test + public void isRecord() { + var probe = new ClassProbe<>(SimpleRecord.class); + assertTrue(probe.isRecord()); + } + + record SimpleRecord(int i) {} +} diff --git a/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorSealedTest.java b/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorSealedTest.java index c779c01d9..d53786010 100644 --- a/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorSealedTest.java +++ b/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorSealedTest.java @@ -3,32 +3,21 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import org.junit.jupiter.api.BeforeEach; +import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import org.junit.jupiter.api.Test; public class ClassAccessorSealedTest { - private PrefabValues prefabValues; - - @BeforeEach - public void setup() { - FactoryCache factoryCache = JavaApiPrefabValues.build(); - prefabValues = new PrefabValues(factoryCache); - } - @Test public void isNotSealed() { - var accessor = ClassAccessor.of(SealedChild.class, prefabValues); - assertFalse(accessor.isSealed()); + var probe = new ClassProbe<>(SealedChild.class); + assertFalse(probe.isSealed()); } @Test public void isSealed() { - var accessor = ClassAccessor.of(SealedParent.class, prefabValues); - assertTrue(accessor.isSealed()); + var probe = new ClassProbe<>(SealedParent.class); + assertTrue(probe.isSealed()); } public abstract static sealed class SealedParent {} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java index c8a239857..96e5bac47 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java @@ -3,7 +3,6 @@ import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; import java.lang.reflect.Modifier; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; import nl.jqno.equalsverifier.internal.reflection.SealedTypesHelper; @@ -18,7 +17,7 @@ public ClassProbe(Class type) { this.type = type; } - /** @return The class on which {@link ClassAccessor} operates. */ + /** @return The class on which {@link ClassProbe} operates. */ public Class getType() { return type; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java index c3b0f3e69..812d11f4f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java @@ -1,9 +1,5 @@ package nl.jqno.equalsverifier.internal.reflection; -import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; @@ -38,138 +34,6 @@ public static ClassAccessor of(Class type, PrefabValues prefabValues) return new ClassAccessor<>(type, prefabValues); } - /** @return The class on which {@link ClassAccessor} operates. */ - public Class getType() { - return type; - } - - /** - * Determines whether T is a Java Record. - * - * @return true if T is a Java Record. - */ - public boolean isRecord() { - return RecordsHelper.isRecord(type); - } - - /** - * Determines whether T is a sealed class. - * - * @return true if T is a sealed class - */ - public boolean isSealed() { - return SealedTypesHelper.isSealed(type); - } - - /** - * Determines whether T declares a field. This does not include inherited fields. - * - * @param field The field that we want to detect. - * @return True if T declares the field. - */ - public boolean declaresField(Field field) { - try { - type.getDeclaredField(field.getName()); - return true; - } catch (NoSuchFieldException e) { - return false; - } - } - - /** - * Determines whether T has an {@code equals} method. - * - * @return True if T has an {@code equals} method. - */ - public boolean declaresEquals() { - return declaresMethod(type, "equals", Object.class); - } - - /** - * Determines whether T has an {@code hashCode} method. - * - * @return True if T has an {@code hashCode} method. - */ - public boolean declaresHashCode() { - return declaresMethod(type, "hashCode"); - } - - /** - * Determines whether T has a method with the given name and parameters. - * - * @param name The name of the method we're looking for. - * @return True if T has a method with the given name and parameters. - */ - public boolean hasMethod(String name) { - Class t = type; - while (t != null) { - if (declaresMethod(t, name)) { - return true; - } - t = t.getSuperclass(); - } - return false; - } - - private static boolean declaresMethod(Class type, String name, Class... parameterTypes) { - try { - type.getDeclaredMethod(name, parameterTypes); - return true; - } catch (NoSuchMethodException e) { - return false; - } - } - - /** - * Determines whether T's {@code equals} method is abstract. - * - * @return True if T's {@code equals} method is abstract. - */ - public boolean isEqualsAbstract() { - return isMethodAbstract("equals", Object.class); - } - - /** - * Determines whether T's {@code hashCode} method is abstract. - * - * @return True if T's {@code hashCode} method is abstract. - */ - public boolean isHashCodeAbstract() { - return isMethodAbstract("hashCode"); - } - - private boolean isMethodAbstract(String name, Class... parameterTypes) { - return rethrow(() -> - Modifier.isAbstract(type.getMethod(name, parameterTypes).getModifiers()) - ); - } - - /** - * Determines whether T's {@code equals} method is inherited from {@link Object}. - * - * @return true if T's {@code equals} method is inherited from {@link Object}; false if it is - * overridden in T or in any of its superclasses (except {@link Object}). - */ - public boolean isEqualsInheritedFromObject() { - ClassAccessor i = this; - while (i.getType() != Object.class) { - if (i.declaresEquals() && !i.isEqualsAbstract()) { - return false; - } - i = i.getSuperAccessor(); - } - return true; - } - - /** - * Returns an accessor for T's superclass. - * - * @return An accessor for T's superclass. - */ - public ClassAccessor getSuperAccessor() { - return ClassAccessor.of(type.getSuperclass(), prefabValues); - } - /** * Returns an instance of T that is not equal to the instance of T returned by {@link * #getBlueObject(TypeTag)}. diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java index 249883112..762c6c274 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java @@ -1,12 +1,11 @@ package nl.jqno.equalsverifier.internal.reflection; import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; -import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.prefabvalues.*; -import nl.jqno.equalsverifier.testhelpers.types.ColorPoint3D; -import nl.jqno.equalsverifier.testhelpers.types.Point3D; import nl.jqno.equalsverifier.testhelpers.types.PointContainer; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.TwoStepNodeA; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.TwoStepNodeB; @@ -19,147 +18,12 @@ public class ClassAccessorTest { private FactoryCache factoryCache; private PrefabValues prefabValues; private ClassAccessor pointContainerAccessor; - private ClassAccessor abstractEqualsAndHashCodeAccessor; @BeforeEach public void setup() { factoryCache = JavaApiPrefabValues.build(); prefabValues = new PrefabValues(factoryCache); pointContainerAccessor = ClassAccessor.of(PointContainer.class, prefabValues); - abstractEqualsAndHashCodeAccessor = - ClassAccessor.of(AbstractEqualsAndHashCode.class, prefabValues); - } - - /* Tests the false case. The true case is tested in {@link ClassAccessorCompilerTest}. */ - @Test - public void isRecord() { - assertFalse(pointContainerAccessor.isRecord()); - } - - /* Tests the false case. The true case is tested in {@link ClassAccessorSealedTest}. */ - @Test - public void isSealed() { - assertFalse(pointContainerAccessor.isSealed()); - } - - @Test - public void getType() { - assertSame(PointContainer.class, pointContainerAccessor.getType()); - } - - @Test - public void declaresField() throws Exception { - Field field = PointContainer.class.getDeclaredField("point"); - assertTrue(pointContainerAccessor.declaresField(field)); - } - - @Test - public void doesNotDeclareField() throws Exception { - ClassAccessor accessor = ClassAccessor.of(ColorPoint3D.class, prefabValues); - Field field = Point3D.class.getDeclaredField("z"); - assertFalse(accessor.declaresField(field)); - } - - @Test - public void declaresEquals() { - assertTrue(pointContainerAccessor.declaresEquals()); - assertTrue(abstractEqualsAndHashCodeAccessor.declaresEquals()); - } - - @Test - public void doesNotDeclareEquals() { - ClassAccessor accessor = ClassAccessor.of(Empty.class, prefabValues); - assertFalse(accessor.declaresEquals()); - } - - @Test - public void declaresHashCode() { - assertTrue(pointContainerAccessor.declaresHashCode()); - assertTrue(abstractEqualsAndHashCodeAccessor.declaresHashCode()); - } - - @Test - public void doesNotDeclareHashCode() { - ClassAccessor accessor = ClassAccessor.of(Empty.class, prefabValues); - assertFalse(accessor.declaresHashCode()); - } - - @Test - public void hasMethod() { - ClassAccessor accessor = ClassAccessor.of(MethodContainer.class, prefabValues); - assertTrue(accessor.hasMethod("m")); - } - - @Test - public void hasProtectedMethod() { - ClassAccessor accessor = ClassAccessor.of(MethodContainer.class, prefabValues); - assertTrue(accessor.hasMethod("m_protected")); - } - - @Test - public void hasMethodInSuper() { - ClassAccessor accessor = ClassAccessor.of(ChildOfMethodContainer.class, prefabValues); - assertTrue(accessor.hasMethod("m")); - } - - @Test - public void hasProtectedMethodInSuper() { - ClassAccessor accessor = ClassAccessor.of(ChildOfMethodContainer.class, prefabValues); - assertTrue(accessor.hasMethod("m_protected")); - } - - @Test - public void doesNotHaveMethod() { - ClassAccessor accessor = ClassAccessor.of(MethodContainer.class, prefabValues); - assertFalse(accessor.hasMethod("doesNotExist")); - } - - @Test - public void equalsIsNotAbstract() { - assertFalse(pointContainerAccessor.isEqualsAbstract()); - } - - @Test - public void equalsIsAbstract() { - assertTrue(abstractEqualsAndHashCodeAccessor.isEqualsAbstract()); - } - - @Test - public void hashCodeIsNotAbstract() { - assertFalse(pointContainerAccessor.isHashCodeAbstract()); - } - - @Test - public void hashCodeIsAbstract() { - assertTrue(abstractEqualsAndHashCodeAccessor.isHashCodeAbstract()); - } - - @Test - public void equalsIsInheritedFromObject() { - ClassAccessor accessor = ClassAccessor.of( - NoFieldsSubWithFields.class, - prefabValues - ); - assertTrue(accessor.isEqualsInheritedFromObject()); - } - - @Test - public void equalsIsNotInheritedFromObject() { - assertFalse(pointContainerAccessor.isEqualsInheritedFromObject()); - } - - @Test - public void getSuperAccessorForPojo() { - ClassAccessor superAccessor = - pointContainerAccessor.getSuperAccessor(); - assertEquals(Object.class, superAccessor.getType()); - } - - @Test - public void getSuperAccessorInHierarchy() { - ClassAccessor accessor = ClassAccessor.of(ColorPoint3D.class, prefabValues); - ClassAccessor superAccessor = accessor.getSuperAccessor(); - assertEquals(Point3D.class, superAccessor.getType()); } @Test From b0c34ae15e3f93fb396bc6455874c21f8bbdcd55 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Wed, 11 Sep 2024 20:33:55 +0200 Subject: [PATCH 27/74] Removes PrefabValues from HierarchyChecker --- .../internal/checkers/HierarchyChecker.java | 23 ++++++++----------- .../instantiation/ModernSubjectCreator.java | 14 +++++++++++ .../instantiation/SubjectCreator.java | 1 + .../instantiation/VintageSubjectCreator.java | 17 +++++++++++++- .../internal/reflection/FieldIterable.java | 11 +++++++++ pom.xml | 2 +- 6 files changed, 53 insertions(+), 15 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java index 42463b12e..f752cc17a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java @@ -9,7 +9,6 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.*; @@ -18,7 +17,6 @@ public class HierarchyChecker implements Checker { private final Configuration config; private final Class type; - private final TypeTag typeTag; private final SubjectCreator subjectCreator; private final ClassProbe classProbe; private final Class redefinedSubclass; @@ -43,7 +41,6 @@ public HierarchyChecker(Context context) { } this.type = context.getType(); - this.typeTag = config.getTypeTag(); this.subjectCreator = context.getSubjectCreator(); this.classProbe = context.getClassProbe(); this.redefinedSubclass = config.getRedefinedSubclass(); @@ -88,8 +85,14 @@ private void checkSuperclass() { // instance. } } else { - safelyCheckSuperProperties(ObjectAccessor.of(subjectCreator.plain())); - safelyCheckSuperProperties(ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted())); + safelyCheckSuperProperties( + subjectCreator.plain(), + subjectCreator.withAllFieldsShallowlyChanged() + ); + safelyCheckSuperProperties( + subjectCreator.withAllFieldsDefaulted(), + subjectCreator.withAllFieldsShallowlyChanged() + ); } } @@ -97,21 +100,15 @@ private void checkSuperclass() { value = "DCN_NULLPOINTER_EXCEPTION", justification = "The equals method in a superclasses can throw an NPE, but it's a specific non-goal to do something with that here." ) - private void safelyCheckSuperProperties(ObjectAccessor referenceAccessor) { + private void safelyCheckSuperProperties(T reference, T shallowScrambled) { if (strictnessSuppressed) { return; } - T reference = referenceAccessor.get(); Object equalSuper = getEqualSuper(reference); - T shallowCopy = referenceAccessor.copy(); - ObjectAccessor scrambledAccessor = ObjectAccessor - .of(shallowCopy) - .shallowScramble(config.getPrefabValues(), typeTag); - try { - checkSuperProperties(reference, equalSuper, scrambledAccessor.get()); + checkSuperProperties(reference, equalSuper, shallowScrambled); } catch (AbstractMethodError | NullPointerException ignored) { // In these cases, we'll assume all super properties hold. // The problems we test for, can never occur anyway if you can't instantiate a super diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index a28be9df6..26c8b5ab1 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -83,6 +83,16 @@ public T withAllFieldsChanged() { return createInstance(values); } + @Override + public T withAllFieldsShallowlyChanged() { + Map values = empty(); + for (Field f : nonSuperFields()) { + Object value = instantiate(f).getBlue(); + values.put(f, value); + } + return createInstance(values); + } + private T createInstance(Map values) { for (Field f : fields()) { boolean fieldIsAbsent = !values.containsKey(f); @@ -137,6 +147,10 @@ private FieldIterable fields() { return FieldIterable.ofIgnoringStatic(typeTag.getType()); } + private FieldIterable nonSuperFields() { + return FieldIterable.ofIgnoringSuperAndStatic(typeTag.getType()); + } + private Tuple instantiate(Field f) { return instanceCreator.instantiate(TypeTag.of(f, typeTag)); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index 5c664cc56..a12c95498 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -10,4 +10,5 @@ public interface SubjectCreator { T withFieldSetTo(Field field, Object value); T withFieldChanged(Field field); T withAllFieldsChanged(); + T withAllFieldsShallowlyChanged(); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java index a425917b0..b7be2d776 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java @@ -67,9 +67,24 @@ public T withAllFieldsChanged() { return withAllFields((acc, f) -> acc.withChangedField(f, prefabValues, typeTag)); } + @Override + public T withAllFieldsShallowlyChanged() { + return withTheseFields( + FieldIterable.ofIgnoringSuper(typeTag.getType()), + (acc, f) -> acc.withChangedField(f, prefabValues, typeTag) + ); + } + private T withAllFields(BiFunction, Field, ObjectAccessor> modifier) { + return withTheseFields(FieldIterable.of(typeTag.getType()), modifier); + } + + private T withTheseFields( + FieldIterable fields, + BiFunction, Field, ObjectAccessor> modifier + ) { ObjectAccessor accessor = createSubject(); - for (Field f : FieldIterable.of(typeTag.getType())) { + for (Field f : fields) { accessor = modifier.apply(accessor, f); } return accessor.get(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldIterable.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldIterable.java index b50d3f57c..a4900cbe3 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldIterable.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldIterable.java @@ -56,6 +56,17 @@ public static FieldIterable ofIgnoringStatic(Class type) { return new FieldIterable(type, true, false); } + /** + * Factory method for a FieldIterable that iterates over all declared fields of {@code type}, + * but that ignores its the declared fields of its superclasses, as well as its static fields. + * + * @param type The class that contains the fields over which to iterate. + * @return A FieldIterable. + */ + public static FieldIterable ofIgnoringSuperAndStatic(Class type) { + return new FieldIterable(type, false, false); + } + /** * Returns an iterator over all declared fields of the class and all of its superclasses. * diff --git a/pom.xml b/pom.xml index 4a5a69a64..0c7631213 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ ${argline.module} ${argline.preview} ${argline.experimental} - 0.95 + 0.94 checkstyle-config.xml Max Low From a0f2abf357ef2a7c2f5c355fc66584d9a7694395 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Wed, 11 Sep 2024 20:46:42 +0200 Subject: [PATCH 28/74] Removes PrefabValues and ClassAccessor from Configuration --- .../api/SingleTypeEqualsVerifierApi.java | 35 +++++++------------ .../internal/util/Configuration.java | 29 +++------------ .../equalsverifier/internal/util/Context.java | 5 +-- .../internal/util/ConfigurationHelper.java | 11 +++--- 4 files changed, 26 insertions(+), 54 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index 8da96b3b1..e84c7161b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -1,31 +1,19 @@ package nl.jqno.equalsverifier.api; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.function.Function; import nl.jqno.equalsverifier.EqualsVerifier; import nl.jqno.equalsverifier.EqualsVerifierReport; import nl.jqno.equalsverifier.Func.Func1; import nl.jqno.equalsverifier.Func.Func2; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.checkers.AbstractDelegationChecker; -import nl.jqno.equalsverifier.internal.checkers.CachedHashCodeChecker; -import nl.jqno.equalsverifier.internal.checkers.Checker; -import nl.jqno.equalsverifier.internal.checkers.ExamplesChecker; -import nl.jqno.equalsverifier.internal.checkers.FieldsChecker; -import nl.jqno.equalsverifier.internal.checkers.HierarchyChecker; -import nl.jqno.equalsverifier.internal.checkers.MapEntryHashCodeRequirementChecker; -import nl.jqno.equalsverifier.internal.checkers.NullChecker; -import nl.jqno.equalsverifier.internal.checkers.RecordChecker; -import nl.jqno.equalsverifier.internal.checkers.SignatureChecker; +import nl.jqno.equalsverifier.internal.checkers.*; import nl.jqno.equalsverifier.internal.exceptions.MessagingException; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.util.*; +import nl.jqno.equalsverifier.internal.util.Formatter; /** * Helps to construct an {@link EqualsVerifier} test with a fluent API. @@ -404,8 +392,11 @@ private void performVerification() { } Validations.validateClassCanBeVerified(type); - Configuration config = buildConfig(); - Context context = new Context<>(config); + FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); + PrefabValues prefabValues = new PrefabValues(cache); + + Configuration config = buildConfig(prefabValues); + Context context = new Context<>(config, prefabValues); Validations.validateProcessedAnnotations( type, config.getAnnotationCache(), @@ -418,7 +409,7 @@ private void performVerification() { verifyWithExamples(context); } - private Configuration buildConfig() { + private Configuration buildConfig(PrefabValues prefabValues) { return Configuration.build( type, allExcludedFields, @@ -430,11 +421,11 @@ private Configuration buildConfig() { usingGetClass, warningsToSuppress, fieldnameToGetter, - factoryCache, ignoredAnnotationClassNames, actualFields, equalExamples, - unequalExamples + unequalExamples, + prefabValues ); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index e07a750cb..a0ec1083b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -6,7 +6,8 @@ import java.util.function.Function; import java.util.stream.Collectors; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.prefabvalues.*; +import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.*; @@ -25,8 +26,6 @@ public final class Configuration { private final Function fieldnameToGetter; private final TypeTag typeTag; - private final PrefabValues prefabValues; - private final ClassAccessor classAccessor; private final AnnotationCache annotationCache; private final Set ignoredFields; @@ -37,8 +36,6 @@ public final class Configuration { private Configuration( Class type, TypeTag typeTag, - ClassAccessor classAccessor, - PrefabValues prefabValues, Set ignoredFields, Set nonnullFields, AnnotationCache annotationCache, @@ -53,8 +50,6 @@ private Configuration( ) { this.type = type; this.typeTag = typeTag; - this.classAccessor = classAccessor; - this.prefabValues = prefabValues; this.ignoredFields = ignoredFields; this.nonnullFields = nonnullFields; this.annotationCache = annotationCache; @@ -79,15 +74,13 @@ public static Configuration build( boolean usingGetClass, EnumSet warningsToSuppress, Function fieldnameToGetter, - FactoryCache factoryCache, Set ignoredAnnotationClassNames, Set actualFields, List equalExamples, - List unequalExamples + List unequalExamples, + PrefabValues prefabValues ) { TypeTag typeTag = new TypeTag(type); - FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); - PrefabValues prefabValues = new PrefabValues(cache); ClassAccessor classAccessor = ClassAccessor.of(type, prefabValues); AnnotationCache annotationCache = buildAnnotationCache(type, ignoredAnnotationClassNames); Set ignoredFields = determineIgnoredFields( @@ -106,8 +99,6 @@ public static Configuration build( return new Configuration<>( type, typeTag, - classAccessor, - prefabValues, ignoredFields, nonnullFields, annotationCache, @@ -255,18 +246,6 @@ public TypeTag getTypeTag() { return typeTag; } - @SuppressFBWarnings( - value = "EI_EXPOSE_REP", - justification = "PrefabValues is inherently mutable." - ) - public PrefabValues getPrefabValues() { - return prefabValues; - } - - public ClassAccessor getClassAccessor() { - return classAccessor; - } - @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "A cache is inherently mutable.") public AnnotationCache getAnnotationCache() { return annotationCache; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index e11ce831a..302688e10 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -1,6 +1,7 @@ package nl.jqno.equalsverifier.internal.util; import nl.jqno.equalsverifier.internal.instantiation.*; +import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; public final class Context { @@ -10,11 +11,11 @@ public final class Context { private final SubjectCreator subjectCreator; private final InstanceCreator instanceCreator; - public Context(Configuration configuration) { + public Context(Configuration configuration, PrefabValues prefabValues) { this.type = configuration.getType(); this.configuration = configuration; this.classProbe = new ClassProbe<>(configuration.getType()); - this.instanceCreator = new VintageInstanceCreator(configuration.getPrefabValues()); + this.instanceCreator = new VintageInstanceCreator(prefabValues); this.subjectCreator = new ModernSubjectCreator<>( configuration.getTypeTag(), diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java index c8ad85b9d..7716f7147 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java @@ -2,7 +2,8 @@ import java.util.*; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; public final class ConfigurationHelper { @@ -25,11 +26,11 @@ public static final Configuration emptyConfiguration( ? EnumSet.noneOf(Warning.class) : EnumSet.copyOf(Arrays.asList(warnings)), null, - new FactoryCache(), Collections.emptySet(), Collections.emptySet(), Collections.emptyList(), - Collections.emptyList() + Collections.emptyList(), + new PrefabValues(JavaApiPrefabValues.build()) ); } @@ -48,11 +49,11 @@ public static final Configuration emptyConfigurationWithNonnullFields( false, EnumSet.noneOf(Warning.class), null, - new FactoryCache(), Collections.emptySet(), Collections.emptySet(), Collections.emptyList(), - Collections.emptyList() + Collections.emptyList(), + new PrefabValues(JavaApiPrefabValues.build()) ); } } From 86d173e1b490910355e3d5a6d268e01edd64c82b Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 12 Sep 2024 19:19:06 +0200 Subject: [PATCH 29/74] Uses SubjectCreator for unequal examples --- .../api/SingleTypeEqualsVerifierApi.java | 17 +++------- .../internal/checkers/ExamplesChecker.java | 25 +++++++++++--- .../instantiation/VintageInstanceCreator.java | 15 +++++++- .../factories/FallbackFactory.java | 25 +++++++++++++- .../reflection/InPlaceObjectAccessor.java | 34 +------------------ .../internal/util/Configuration.java | 24 ++----------- .../equalsverifier/internal/util/Context.java | 8 ++++- .../extended_contract/ModulesTest.java | 8 ++++- .../InPlaceObjectAccessorScramblingTest.java | 11 +++--- .../internal/util/ConfigurationHelper.java | 8 ++--- 10 files changed, 88 insertions(+), 87 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index e84c7161b..430cbe205 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -10,8 +10,6 @@ import nl.jqno.equalsverifier.internal.checkers.*; import nl.jqno.equalsverifier.internal.exceptions.MessagingException; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.util.*; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -392,11 +390,8 @@ private void performVerification() { } Validations.validateClassCanBeVerified(type); - FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); - PrefabValues prefabValues = new PrefabValues(cache); - - Configuration config = buildConfig(prefabValues); - Context context = new Context<>(config, prefabValues); + Configuration config = buildConfig(); + Context context = new Context<>(config, factoryCache); Validations.validateProcessedAnnotations( type, config.getAnnotationCache(), @@ -409,7 +404,7 @@ private void performVerification() { verifyWithExamples(context); } - private Configuration buildConfig(PrefabValues prefabValues) { + private Configuration buildConfig() { return Configuration.build( type, allExcludedFields, @@ -424,8 +419,7 @@ private Configuration buildConfig(PrefabValues prefabValues) { ignoredAnnotationClassNames, actualFields, equalExamples, - unequalExamples, - prefabValues + unequalExamples ); } @@ -445,9 +439,8 @@ private void verifyWithoutExamples(Context context) { } private void verifyWithExamples(Context context) { - Configuration config = context.getConfiguration(); Checker[] checkers = { - new ExamplesChecker<>(config), + new ExamplesChecker<>(context), new HierarchyChecker<>(context), new FieldsChecker<>(context), new MapEntryHashCodeRequirementChecker<>(context) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java index 7057fbb4e..10119d878 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java @@ -5,26 +5,29 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import nl.jqno.equalsverifier.internal.exceptions.AssertionException; +import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; -import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; -import nl.jqno.equalsverifier.internal.util.Configuration; -import nl.jqno.equalsverifier.internal.util.Formatter; +import nl.jqno.equalsverifier.internal.util.*; public class ExamplesChecker implements Checker { private final Class type; private final List equalExamples; private final List unequalExamples; + private final SubjectCreator subjectCreator; private final CachedHashCodeInitializer cachedHashCodeInitializer; - public ExamplesChecker(Configuration config) { + public ExamplesChecker(Context context) { + Configuration config = context.getConfiguration(); this.type = config.getType(); this.equalExamples = config.getEqualExamples(); this.unequalExamples = config.getUnequalExamples(); + this.subjectCreator = context.getSubjectCreator(); this.cachedHashCodeInitializer = config.getCachedHashCodeInitializer(); } @@ -43,11 +46,23 @@ public void check() { } } - for (T reference : unequalExamples) { + List unequals = ensureEnoughExamples(unequalExamples); + for (T reference : unequals) { checkSingle(reference); } } + private List ensureEnoughExamples(List examples) { + if (examples.size() > 0) { + return examples; + } + + List result = new ArrayList<>(); + result.add(subjectCreator.plain()); + result.add(subjectCreator.withAllFieldsChanged()); + return result; + } + private void checkPreconditions() { for (T example : equalExamples) { assertTrue( diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java index a950028f6..70e530339 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java @@ -1,6 +1,7 @@ package nl.jqno.equalsverifier.internal.instantiation; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; @@ -19,6 +20,18 @@ public VintageInstanceCreator(PrefabValues prefabValues) { @Override public Tuple instantiate(TypeTag tag) { - return prefabValues.giveTuple(tag); + try { + return prefabValues.giveTuple(tag); + } catch (RuntimeException e) { + // InaccessibleObjectException is not yet available in Java 8 + if (e.getClass().getName().endsWith("InaccessibleObjectException")) { + throw new ModuleException( + "The class is not accessible via the Java Module system. Consider opening the module that contains it.", + e + ); + } else { + throw e; + } + } } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java index 5ee82eed2..44355f350 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java @@ -4,6 +4,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.LinkedHashSet; +import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; @@ -85,7 +86,16 @@ private void traverseFields( int modifiers = field.getModifiers(); boolean isStaticAndFinal = Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers); if (!isStaticAndFinal) { - prefabValues.realizeCacheFor(TypeTag.of(field, tag), typeStack); + try { + prefabValues.realizeCacheFor(TypeTag.of(field, tag), typeStack); + } catch (RuntimeException e) { + // InaccessibleObjectException is not yet available in Java 8 + if (e.getClass().getName().endsWith("InaccessibleObjectException")) { + handleInaccessibleObjectException(e, type, field); + } else { + throw e; + } + } } } } @@ -101,4 +111,17 @@ private Tuple giveInstances( T redCopy = accessor.getRedObject(tag, typeStack); return new Tuple<>(red, blue, redCopy); } + + private void handleInaccessibleObjectException(Throwable e, Class type, Field field) { + throw new ModuleException( + "Field " + + field.getName() + + " of type " + + field.getType().getName() + + " is not accessible via the Java Module System.\nConsider opening the module that contains it, or add prefab values for type " + + field.getType().getName() + + ".", + e + ); + } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessor.java index 63ce34a7e..a3e97d0b9 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessor.java @@ -4,7 +4,6 @@ import java.util.LinkedHashSet; import java.util.function.Function; import java.util.function.Predicate; -import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; @@ -76,42 +75,11 @@ private ObjectAccessor scrambleInternal( Function, FieldIterable> it ) { for (Field field : it.apply(type())) { - try { - fieldModifierFor(field).changeField(prefabValues, enclosingType, typeStack); - } catch (ModuleException e) { - handleInaccessibleObjectException(e.getCause(), field); - } catch (RuntimeException e) { - // InaccessibleObjectException is not yet available in Java 8 - if (e.getClass().getName().endsWith("InaccessibleObjectException")) { - handleInaccessibleObjectException(e, field); - } else { - throw e; - } - } + fieldModifierFor(field).changeField(prefabValues, enclosingType, typeStack); } return this; } - private void handleInaccessibleObjectException(Throwable e, Field field) { - if (e.getMessage() != null && e.getMessage().contains(type().getCanonicalName())) { - throw new ModuleException( - "The class is not accessible via the Java Module system. Consider opening the module that contains it.", - e - ); - } else { - throw new ModuleException( - "Field " + - field.getName() + - " of type " + - field.getType().getName() + - " is not accessible via the Java Module System.\nConsider opening the module that contains it, or add prefab values for type " + - field.getType().getName() + - ".", - e - ); - } - } - /** {@inheritDoc} */ @Override public ObjectAccessor clear( diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index a0ec1083b..51e7f1161 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -6,9 +6,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.*; public final class Configuration { @@ -77,11 +75,9 @@ public static Configuration build( Set ignoredAnnotationClassNames, Set actualFields, List equalExamples, - List unequalExamples, - PrefabValues prefabValues + List unequalExamples ) { TypeTag typeTag = new TypeTag(type); - ClassAccessor classAccessor = ClassAccessor.of(type, prefabValues); AnnotationCache annotationCache = buildAnnotationCache(type, ignoredAnnotationClassNames); Set ignoredFields = determineIgnoredFields( type, @@ -94,7 +90,6 @@ public static Configuration build( Function converter = fieldnameToGetter != null ? fieldnameToGetter : DEFAULT_FIELDNAME_TO_GETTER_CONVERTER; - List unequals = ensureUnequalExamples(typeTag, classAccessor, unequalExamples); return new Configuration<>( type, @@ -109,7 +104,7 @@ public static Configuration build( warningsToSuppress, converter, equalExamples, - unequals + unequalExamples ); } @@ -187,21 +182,6 @@ private static Set determineAnnotationlessIgnoredFields( return excludedFields; } - private static List ensureUnequalExamples( - TypeTag typeTag, - ClassAccessor classAccessor, - List examples - ) { - if (examples.size() > 0) { - return examples; - } - - List result = new ArrayList<>(); - result.add(classAccessor.getRedObject(typeTag)); - result.add(classAccessor.getBlueObject(typeTag)); - return result; - } - public Class getType() { return type; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index 302688e10..07796a827 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -1,6 +1,8 @@ package nl.jqno.equalsverifier.internal.util; import nl.jqno.equalsverifier.internal.instantiation.*; +import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; public final class Context { @@ -11,10 +13,14 @@ public final class Context { private final SubjectCreator subjectCreator; private final InstanceCreator instanceCreator; - public Context(Configuration configuration, PrefabValues prefabValues) { + public Context(Configuration configuration, FactoryCache factoryCache) { this.type = configuration.getType(); this.configuration = configuration; this.classProbe = new ClassProbe<>(configuration.getType()); + + FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); + PrefabValues prefabValues = new PrefabValues(cache); + this.instanceCreator = new VintageInstanceCreator(prefabValues); this.subjectCreator = new ModernSubjectCreator<>( diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/ModulesTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/ModulesTest.java index 274da8af9..b58a876a6 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/ModulesTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/ModulesTest.java @@ -3,6 +3,7 @@ import java.text.AttributedString; import java.util.Objects; import nl.jqno.equalsverifier.EqualsVerifier; +import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledForJreRange; @@ -19,7 +20,12 @@ public class ModulesTest { @DisabledForJreRange(max = JRE.JAVA_11) public void giveProperErrorMessage_whenClassUnderTestIsInaccessible() { ExpectedException - .when(() -> EqualsVerifier.forClass(AttributedString.class).verify()) + .when(() -> + EqualsVerifier + .forClass(AttributedString.class) + .suppress(Warning.INHERITED_DIRECTLY_FROM_OBJECT) + .verify() + ) .assertFailure() .assertMessageContains("The class", "Consider opening"); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorScramblingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorScramblingTest.java index 67a3487f4..6fba95fc7 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorScramblingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorScramblingTest.java @@ -7,7 +7,6 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; -import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.prefabvalues.*; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.types.Point; @@ -136,8 +135,9 @@ public void scrambleSutInaccessible() { ExpectedException .when(() -> doScramble(as)) - .assertThrows(ModuleException.class) - .assertDescriptionContains("The class", "Consider opening"); + // InaccessibleObjectException, but it's not available in Java 8 + .assertThrows(RuntimeException.class) + .assertMessageContains("accessible: module", "does not \"opens"); } @Test @@ -147,8 +147,9 @@ public void scrambleFieldInaccessible() { ExpectedException .when(() -> doScramble(ic)) - .assertThrows(ModuleException.class) - .assertDescriptionContains("Field as", "Consider opening"); + // InaccessibleObjectException, but it's not available in Java 8 + .assertThrows(RuntimeException.class) + .assertMessageContains("accessible: module", "does not \"opens"); } @SuppressWarnings("unchecked") diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java index 7716f7147..d23c139c2 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java @@ -2,8 +2,6 @@ import java.util.*; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; public final class ConfigurationHelper { @@ -29,8 +27,7 @@ public static final Configuration emptyConfiguration( Collections.emptySet(), Collections.emptySet(), Collections.emptyList(), - Collections.emptyList(), - new PrefabValues(JavaApiPrefabValues.build()) + Collections.emptyList() ); } @@ -52,8 +49,7 @@ public static final Configuration emptyConfigurationWithNonnullFields( Collections.emptySet(), Collections.emptySet(), Collections.emptyList(), - Collections.emptyList(), - new PrefabValues(JavaApiPrefabValues.build()) + Collections.emptyList() ); } } From f0fc5bc82ebf27cd9ecb3c190db6e21e68bc64e9 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 12 Sep 2024 19:46:13 +0200 Subject: [PATCH 30/74] Removes FieldAccessor from checkers --- .../internal/checkers/FieldsChecker.java | 6 +- .../checkers/fieldchecks/ArrayFieldCheck.java | 4 +- .../fieldchecks/MutableStateFieldCheck.java | 10 +-- .../NullPointerExceptionFieldCheck.java | 5 +- .../fieldchecks/ReflexivityFieldCheck.java | 14 ++-- .../fieldchecks/SignificantFieldCheck.java | 41 ++++----- .../fieldchecks/StringFieldCheck.java | 6 +- .../fieldchecks/TransientFieldsCheck.java | 4 +- .../internal/instantiation/FieldProbe.java | 37 +++++++- .../instantiation/ModernSubjectCreator.java | 2 +- .../architecture/ArchitectureTest.java | 4 + .../instantiation/FieldProbeTest.java | 84 +++++++++++++++---- 12 files changed, 145 insertions(+), 72 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index dd0ea1b21..821f777cc 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -3,9 +3,9 @@ import java.util.function.Predicate; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.*; +import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -37,8 +37,8 @@ public FieldsChecker(Context context) { final String cachedHashCodeFieldName = config .getCachedHashCodeInitializer() .getCachedHashCodeFieldName(); - final Predicate isCachedHashCodeField = a -> - a.getFieldName().equals(cachedHashCodeFieldName); + final Predicate isCachedHashCodeField = p -> + p.getName().equals(cachedHashCodeFieldName); this.arrayFieldCheck = new ArrayFieldCheck<>(subjectCreator, config.getCachedHashCodeInitializer()); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java index 7e3c9bd6e..69f81672e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java @@ -6,7 +6,6 @@ import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -30,8 +29,7 @@ public void execute(FieldProbe fieldProbe) { if (!arrayType.isArray()) { return; } - FieldAccessor fieldAccessor = FieldAccessor.of(fieldProbe.getField()); - if (!fieldAccessor.canBeModifiedReflectively()) { + if (!fieldProbe.canBeModifiedReflectively()) { return; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java index b179bf5e4..7f5c43d1d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java @@ -6,13 +6,12 @@ import java.util.function.Predicate; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.util.Formatter; public class MutableStateFieldCheck implements FieldCheck { private final SubjectCreator subjectCreator; - private final Predicate isCachedHashCodeField; + private final Predicate isCachedHashCodeField; @SuppressFBWarnings( value = "EI_EXPOSE_REP2", @@ -20,7 +19,7 @@ public class MutableStateFieldCheck implements FieldCheck { ) public MutableStateFieldCheck( SubjectCreator subjectCreator, - Predicate isCachedHashCodeField + Predicate isCachedHashCodeField ) { this.subjectCreator = subjectCreator; this.isCachedHashCodeField = isCachedHashCodeField; @@ -28,8 +27,7 @@ public MutableStateFieldCheck( @Override public void execute(FieldProbe fieldProbe) { - FieldAccessor fieldAccessor = FieldAccessor.of(fieldProbe.getField()); - if (isCachedHashCodeField.test(fieldAccessor)) { + if (isCachedHashCodeField.test(fieldProbe)) { return; } @@ -40,7 +38,7 @@ public void execute(FieldProbe fieldProbe) { T changed = subjectCreator.withFieldChanged(fieldProbe.getField()); boolean equalAfter = reference.equals(changed); - if (equalBefore && !equalAfter && !fieldAccessor.fieldIsFinal()) { + if (equalBefore && !equalAfter && !fieldProbe.isFinal()) { String message = "Mutability: equals depends on mutable field %%.\n" + "Make the field final, suppress Warning.NONFINAL_FIELDS or use" + diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java index b363c37ba..12ea086fe 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java @@ -6,7 +6,6 @@ import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldModifier; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -32,14 +31,14 @@ public void execute(FieldProbe fieldProbe) { if (config.getNonnullFields().contains(fieldProbe.getName())) { return; } - if (fieldProbe.fieldIsPrimitive()) { + if (fieldProbe.isPrimitive()) { return; } if (fieldProbe.isAnnotatedNonnull()) { return; } - if (FieldAccessor.of(fieldProbe.getField()).fieldIsStatic()) { + if (fieldProbe.isStatic()) { T reference = subjectCreator.plain(); FieldModifier fieldModifier = FieldModifier.of(fieldProbe.getField(), reference); Object saved = ObjectAccessor.of(reference).getField(fieldProbe.getField()); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index 6d4e5e610..527c4b176 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -10,7 +10,6 @@ import nl.jqno.equalsverifier.internal.instantiation.*; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Configuration; @@ -44,7 +43,7 @@ public void execute(FieldProbe fieldProbe) { } checkReferenceReflexivity(); - checkValueReflexivity(fieldProbe.getField()); + checkValueReflexivity(fieldProbe); checkNullReflexivity(fieldProbe); } @@ -54,15 +53,15 @@ private void checkReferenceReflexivity() { checkReflexivityFor(left, right); } - private void checkValueReflexivity(Field field) { - Class fieldType = field.getType(); + private void checkValueReflexivity(FieldProbe probe) { + Class fieldType = probe.getType(); if (warningsToSuppress.contains(Warning.REFERENCE_EQUALITY)) { return; } if (fieldType.equals(Object.class) || fieldType.isInterface()) { return; } - if (FieldAccessor.of(field).fieldIsStatic()) { + if (probe.isStatic()) { return; } ClassProbe fieldTypeProbe = new ClassProbe<>(fieldType); @@ -74,6 +73,7 @@ private void checkValueReflexivity(Field field) { return; } + Field field = probe.getField(); TypeTag tag = TypeTag.of(field, typeTag); Tuple tuple = instanceCreator.instantiate(tag); Object left = subjectCreator.withFieldSetTo(field, tuple.getRed()); @@ -82,7 +82,7 @@ private void checkValueReflexivity(Field field) { Formatter f = Formatter.of( "Reflexivity: == used instead of .equals() on field: %%" + "\nIf this is intentional, consider suppressing Warning.%%", - field.getName(), + probe.getName(), Warning.REFERENCE_EQUALITY.toString() ); assertEquals(f, left, right); @@ -90,7 +90,7 @@ private void checkValueReflexivity(Field field) { private void checkNullReflexivity(FieldProbe fieldProbe) { Field field = fieldProbe.getField(); - if (fieldProbe.fieldIsPrimitive() && warningsToSuppress.contains(Warning.ZERO_FIELDS)) { + if (fieldProbe.isPrimitive() && warningsToSuppress.contains(Warning.ZERO_FIELDS)) { return; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java index a5e465b8c..6aca90c71 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java @@ -3,14 +3,12 @@ import static nl.jqno.equalsverifier.internal.util.Assert.assertFalse; import static nl.jqno.equalsverifier.internal.util.Assert.assertTrue; -import java.lang.reflect.Field; import java.util.EnumSet; import java.util.Set; import java.util.function.Predicate; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.*; @@ -23,12 +21,9 @@ public class SignificantFieldCheck implements FieldCheck { private final Set ignoredFields; private final CachedHashCodeInitializer cachedHashCodeInitializer; private final AnnotationCache annotationCache; - private final Predicate isCachedHashCodeField; + private final Predicate isCachedHashCodeField; - public SignificantFieldCheck( - Context context, - Predicate isCachedHashCodeField - ) { + public SignificantFieldCheck(Context context, Predicate isCachedHashCodeField) { this.subjectCreator = context.getSubjectCreator(); Configuration config = context.getConfiguration(); this.type = config.getType(); @@ -41,9 +36,7 @@ public SignificantFieldCheck( @Override public void execute(FieldProbe fieldProbe) { - Field changedField = fieldProbe.getField(); - FieldAccessor fieldAccessor = FieldAccessor.of(changedField); - if (isCachedHashCodeField.test(fieldAccessor)) { + if (isCachedHashCodeField.test(fieldProbe)) { return; } @@ -92,7 +85,7 @@ private void checkValues( equalToItself, equalsChanged, reference, - FieldAccessor.of(probe.getField()), + probe, fieldName, testWithNull ); @@ -136,11 +129,11 @@ private void assertFieldShouldBeIgnored( boolean equalToItself, boolean equalsChanged, T object, - FieldAccessor fieldAccessor, + FieldProbe fieldProbe, String fieldName, boolean testWithNull ) { - if (!shouldAllFieldsBeUsed(fieldAccessor) || !isFieldEligible(fieldAccessor)) { + if (!shouldAllFieldsBeUsed(fieldProbe) || !isFieldEligible(fieldProbe)) { return; } @@ -154,7 +147,7 @@ private void assertFieldShouldBeIgnored( !thisFieldIsMarkedAsId && annotationCache.hasClassAnnotation(type, SupportedAnnotations.ID); - if (!fieldIsEmptyAndItsOk(thisFieldIsMarkedAsId, fieldAccessor, object)) { + if (!fieldIsEmptyAndItsOk(thisFieldIsMarkedAsId, fieldProbe, object)) { if (!fieldShouldBeIgnored) { assertTrue( Formatter.of("Significant fields: equals does not use %%.", fieldName), @@ -179,22 +172,22 @@ private void assertFieldShouldBeIgnored( ); } - private boolean shouldAllFieldsBeUsed(FieldAccessor fieldAccessor) { + private boolean shouldAllFieldsBeUsed(FieldProbe fieldProbe) { return ( !warningsToSuppress.contains(Warning.ALL_FIELDS_SHOULD_BE_USED) && !(warningsToSuppress.contains(Warning.ALL_NONFINAL_FIELDS_SHOULD_BE_USED) && - !fieldAccessor.fieldIsFinal()) + !fieldProbe.isFinal()) ); } - private boolean isFieldEligible(FieldAccessor fieldAccessor) { + private boolean isFieldEligible(FieldProbe fieldProbe) { return ( - !fieldAccessor.fieldIsStatic() && - !fieldAccessor.fieldIsTransient() && - !fieldAccessor.fieldIsEmptyOrSingleValueEnum() && + !fieldProbe.isStatic() && + !fieldProbe.isTransient() && + !fieldProbe.isEmptyOrSingleValueEnum() && !annotationCache.hasFieldAnnotation( type, - fieldAccessor.getField().getName(), + fieldProbe.getField().getName(), SupportedAnnotations.TRANSIENT ) ); @@ -202,11 +195,11 @@ private boolean isFieldEligible(FieldAccessor fieldAccessor) { private boolean fieldIsEmptyAndItsOk( boolean thisFieldIsMarkedAsId, - FieldAccessor fieldAccessor, + FieldProbe fieldProbe, T object ) { - Object value = fieldAccessor.get(object); - Class fieldType = fieldAccessor.getFieldType(); + Object value = fieldProbe.getValue(object); + Class fieldType = fieldProbe.getType(); Object zero = PrimitiveMappers.DEFAULT_WRAPPED_VALUE_MAPPER.get(fieldType); boolean fieldIsEmpty = value == null || value.equals(zero); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java index 6c46c4b6d..667786f23 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java @@ -8,7 +8,6 @@ import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -40,10 +39,7 @@ public StringFieldCheck( justification = "String prefab values are probably not localized." ) public void execute(FieldProbe fieldProbe) { - if ( - String.class.equals(fieldProbe.getType()) && - !FieldAccessor.of(fieldProbe.getField()).fieldIsStatic() - ) { + if (String.class.equals(fieldProbe.getType()) && !fieldProbe.isStatic()) { String red = instanceCreator.instantiate(new TypeTag(String.class)).getRed(); final T reference; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java index 1b03c7343..d28d039fe 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java @@ -6,7 +6,6 @@ import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -39,8 +38,7 @@ public void execute(FieldProbe fieldProbe) { fieldProbe.getName(), SupportedAnnotations.TRANSIENT ); - boolean fieldIsTransient = - FieldAccessor.of(fieldProbe.getField()).fieldIsTransient() || hasAnnotation; + boolean fieldIsTransient = fieldProbe.isTransient() || hasAnnotation; if (equalsChanged && fieldIsTransient) { fail( Formatter.of( diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java index 8b56b201f..ca92488c0 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java @@ -76,18 +76,34 @@ public String getName() { } /** @return Whether the field is of a primitive type. */ - public boolean fieldIsPrimitive() { + public boolean isPrimitive() { return getType().isPrimitive(); } + /** @return Whether the field is marked with the final modifier. */ + public boolean isFinal() { + return Modifier.isFinal(field.getModifiers()); + } + /** @return Whether the field is marked with the static modifier. */ - public boolean fieldIsStatic() { + public boolean isStatic() { return Modifier.isStatic(field.getModifiers()); } + /** @return Whether the field is marked with the transient modifier. */ + public boolean isTransient() { + return Modifier.isTransient(field.getModifiers()); + } + + /** @return Whether the field is an enum with a single value. */ + public boolean isEmptyOrSingleValueEnum() { + Class type = field.getType(); + return type.isEnum() && type.getEnumConstants().length <= 1; + } + /** @return Whether the field can be set to the default value for its type. */ public boolean canBeDefault() { - if (fieldIsPrimitive()) { + if (isPrimitive()) { return !isWarningZeroSuppressed; } @@ -124,4 +140,19 @@ public boolean isAnnotatedNonnull() { ); return hasFindbugsAnnotation || hasJsr305Annotation || hasDefaultAnnotation; } + + /** + * Determines whether the field can be modified using reflection. + * + * @return Whether or not the field can be modified reflectively. + */ + public boolean canBeModifiedReflectively() { + if (field.isSynthetic()) { + return false; + } + if (isFinal() && isStatic()) { + return false; + } + return true; + } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index 26c8b5ab1..520a854a8 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -66,7 +66,7 @@ public T withFieldSetTo(Field field, Object value) { @Override public T withFieldChanged(Field field) { - if (FieldProbe.of(field, config).fieldIsStatic()) { + if (FieldProbe.of(field, config).isStatic()) { return plain(); } Object value = instantiate(field).getBlue(); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index 6f9b31600..f49908d17 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -7,6 +7,7 @@ import com.tngtech.archunit.lang.ArchRule; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; +import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; @AnalyzeClasses(packages = "nl.jqno.equalsverifier") public final class ArchitectureTest { @@ -20,6 +21,9 @@ public final class ArchitectureTest { .areAssignableTo(ClassAccessor.class) .orShould() .accessClassesThat() + .areAssignableTo(FieldAccessor.class) + .orShould() + .accessClassesThat() .areAssignableTo(PrefabValues.class); @ArchTest diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java index 1016d46f8..67959a115 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java @@ -27,56 +27,112 @@ public void getField() throws NoSuchFieldException { @Test public void getType() { ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); assertEquals(Object.class, probe.getType()); } @Test public void getName() { ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); assertEquals(FIELD_NAME, probe.getName()); } @Test public void isNotPrimitive() { ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); - assertFalse(probe.fieldIsPrimitive()); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); + assertFalse(probe.isPrimitive()); } @Test public void isPrimitive() { PrimitiveContainer foo = new PrimitiveContainer(); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); - assertTrue(probe.fieldIsPrimitive()); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); + assertTrue(probe.isPrimitive()); + } + + @Test + public void isNotFinal() { + ObjectContainer foo = new ObjectContainer(); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); + assertFalse(probe.isFinal()); + } + + @Test + public void isFinal() { + FinalContainer foo = new FinalContainer(); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); + assertTrue(probe.isFinal()); } @Test public void isNotStatic() { ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); - assertFalse(probe.fieldIsStatic()); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); + assertFalse(probe.isStatic()); } @Test public void isStatic() { StaticContainer foo = new StaticContainer(); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); - assertTrue(probe.fieldIsStatic()); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); + assertTrue(probe.isStatic()); + } + + @Test + public void isNotTransient() { + ObjectContainer foo = new ObjectContainer(); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); + assertFalse(probe.isTransient()); + } + + @Test + public void isTransient() { + TransientContainer foo = new TransientContainer(); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); + assertTrue(probe.isTransient()); + } + + @Test + public void isNotEnum() { + PrimitiveContainer foo = new PrimitiveContainer(); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); + assertFalse(probe.isEmptyOrSingleValueEnum()); + } + + @Test + public void isEnumButNotSingleValue() { + EnumContainer foo = new EnumContainer(); + FieldProbe probe = getProbeFor(foo, "twoElementEnum"); + assertFalse(probe.isEmptyOrSingleValueEnum()); + } + + @Test + public void isSingleValueEnum() { + EnumContainer foo = new EnumContainer(); + FieldProbe probe = getProbeFor(foo, "oneElementEnum"); + assertTrue(probe.isEmptyOrSingleValueEnum()); + } + + @Test + public void isEmptyEnum() { + EnumContainer foo = new EnumContainer(); + FieldProbe probe = getProbeFor(foo, "emptyEnum"); + assertTrue(probe.isEmptyOrSingleValueEnum()); } @Test public void canBeDefault_forObject() { ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); assertTrue(probe.canBeDefault()); } @Test public void canBeDefault_primitive() { PrimitiveContainer foo = new PrimitiveContainer(); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); assertTrue(probe.canBeDefault()); } @@ -105,11 +161,11 @@ public void canBeDefault_isMentionedExplicitly() { @Test public void canBeDefault_annotated() { NonNullContainer foo = new NonNullContainer(); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(foo, FIELD_NAME); assertFalse(probe.canBeDefault()); } - private FieldProbe getAccessorFor(Object object, String fieldName) { + private FieldProbe getProbeFor(Object object, String fieldName) { return getAccessorFor( object, fieldName, From 5f24804af60e0fa30e2ef843a3852736d78cefad Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 13 Sep 2024 10:43:59 +0200 Subject: [PATCH 31/74] Cleans up ModernSubjectCreator --- .../instantiation/ModernSubjectCreator.java | 58 +++++++++++-------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index 520a854a8..8074db77f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -93,7 +93,13 @@ public T withAllFieldsShallowlyChanged() { return createInstance(values); } - private T createInstance(Map values) { + private T createInstance(Map givens) { + Map values = determineValues(givens); + return classProbe.isRecord() ? createRecordInstance(values) : createClassInstance(values); + } + + private Map determineValues(Map givens) { + Map values = new HashMap<>(givens); for (Field f : fields()) { boolean fieldIsAbsent = !values.containsKey(f); boolean fieldCannotBeNull = @@ -103,34 +109,36 @@ private T createInstance(Map values) { values.put(f, value); } } + return values; + } - Class type = typeTag.getType(); - if (classProbe.isRecord()) { - List params = new ArrayList<>(); - for (Field f : fields()) { - Object value = values.get(f); - if (value == null) { - Object def = PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(f.getType()); - params.add(def); - } else { - params.add(value); - } + private T createRecordInstance(Map values) { + List params = new ArrayList<>(); + for (Field f : fields()) { + Object value = values.get(f); + if (value == null) { + Object def = PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(f.getType()); + params.add(def); + } else { + params.add(value); } - RecordProbe recordProbe = new RecordProbe<>(type); - return recordProbe.callRecordConstructor(params); - } else { - T instance = Instantiator.of(type).instantiate(); - ObjectAccessor accessor = ObjectAccessor.of(instance); - for (Field f : fields()) { - Object value = values.get(f); - if (value == null) { - accessor.withDefaultedField(f); - } else { - accessor.withFieldSetTo(f, value); - } + } + RecordProbe recordProbe = new RecordProbe<>(typeTag.getType()); + return recordProbe.callRecordConstructor(params); + } + + private T createClassInstance(Map values) { + T instance = Instantiator.of(typeTag.getType()).instantiate(); + ObjectAccessor accessor = ObjectAccessor.of(instance); + for (Field f : fields()) { + Object value = values.get(f); + if (value == null) { + accessor.withDefaultedField(f); + } else { + accessor.withFieldSetTo(f, value); } - return instance; } + return instance; } private Map empty() { From 65f50bff33f8d688d92724e7e3cc2ed17910dd38 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 13 Sep 2024 12:18:48 +0200 Subject: [PATCH 32/74] Adds copy() and copyIntoSuperclass() methods to SubjectCreator --- .../internal/checkers/ExamplesChecker.java | 3 +- .../internal/checkers/HierarchyChecker.java | 2 +- .../internal/checkers/RecordChecker.java | 13 +++--- .../instantiation/ModernSubjectCreator.java | 43 ++++++++++++++++--- .../instantiation/SubjectCreator.java | 2 + .../instantiation/VintageSubjectCreator.java | 18 ++++++-- .../equalsverifier/internal/util/Context.java | 7 +-- 7 files changed, 62 insertions(+), 26 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java index 10119d878..025abc879 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java @@ -11,7 +11,6 @@ import nl.jqno.equalsverifier.internal.exceptions.AssertionException; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.*; public class ExamplesChecker implements Checker { @@ -96,7 +95,7 @@ private void checkEqualButNotIdentical(T reference, T other) { } private void checkSingle(T reference) { - final T copy = ObjectAccessor.of(reference, type).copy(); + final T copy = subjectCreator.copy(reference); checkReflexivity(reference); checkNonNullity(reference); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java index f752cc17a..c06bcb9e8 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java @@ -149,7 +149,7 @@ private void checkSuperProperties(T reference, Object equalSuper, T shallow) { } private Object getEqualSuper(T reference) { - return ObjectAccessor.of(reference, type.getSuperclass()).copy(); + return subjectCreator.copyIntoSuperclass(reference); } private void checkSubclass() { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java index 8dc3e012e..bf5af10da 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java @@ -12,16 +12,17 @@ import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; public class RecordChecker implements Checker { private final Context context; + private final SubjectCreator subjectCreator; public RecordChecker(Context context) { this.context = context; + this.subjectCreator = context.getSubjectCreator(); } @Override @@ -31,15 +32,13 @@ public void check() { return; } - SubjectCreator subjectCreator = context.getSubjectCreator(); - verifyRecordPrecondition(ObjectAccessor.of(subjectCreator.plain())); - verifyRecordPrecondition(ObjectAccessor.of(subjectCreator.withAllFieldsDefaulted())); + verifyRecordPrecondition(subjectCreator.plain()); + verifyRecordPrecondition(subjectCreator.withAllFieldsDefaulted()); } - private void verifyRecordPrecondition(ObjectAccessor originalAccessor) { + private void verifyRecordPrecondition(T original) { Class type = context.getType(); - T original = originalAccessor.get(); - T copy = originalAccessor.copy(); + T copy = subjectCreator.copy(original); if (original.equals(copy)) { return; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index 8074db77f..db9563584 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -13,6 +13,7 @@ public class ModernSubjectCreator implements SubjectCreator { private final TypeTag typeTag; + private final Class type; private final Configuration config; private final InstanceCreator instanceCreator; private final ClassProbe classProbe; @@ -20,13 +21,13 @@ public class ModernSubjectCreator implements SubjectCreator { public ModernSubjectCreator( TypeTag typeTag, Configuration config, - InstanceCreator instanceCreator, - ClassProbe classProbe + InstanceCreator instanceCreator ) { this.typeTag = typeTag; + this.type = typeTag.getType(); this.config = config; this.instanceCreator = instanceCreator; - this.classProbe = classProbe; + this.classProbe = new ClassProbe<>(type); } @Override @@ -93,6 +94,34 @@ public T withAllFieldsShallowlyChanged() { return createInstance(values); } + @Override + public T copy(T original) { + Map values = empty(); + for (Field f : fields()) { + Object value = FieldProbe.of(f, config).getValue(original); + values.put(f, value); + } + return createInstance(values); + } + + @Override + public Object copyIntoSuperclass(T original) { + TypeTag superTag = new TypeTag(type.getSuperclass()); + ModernSubjectCreator superCreator = new ModernSubjectCreator( + superTag, + config, + instanceCreator + ); + + Map values = empty(); + for (Field f : superCreator.fields()) { + Object value = FieldProbe.of(f, config).getValue(original); + values.put(f, value); + } + + return superCreator.createInstance(values); + } + private T createInstance(Map givens) { Map values = determineValues(givens); return classProbe.isRecord() ? createRecordInstance(values) : createClassInstance(values); @@ -123,12 +152,12 @@ private T createRecordInstance(Map values) { params.add(value); } } - RecordProbe recordProbe = new RecordProbe<>(typeTag.getType()); + RecordProbe recordProbe = new RecordProbe<>(type); return recordProbe.callRecordConstructor(params); } private T createClassInstance(Map values) { - T instance = Instantiator.of(typeTag.getType()).instantiate(); + T instance = Instantiator.of(type).instantiate(); ObjectAccessor accessor = ObjectAccessor.of(instance); for (Field f : fields()) { Object value = values.get(f); @@ -152,11 +181,11 @@ private Map with(Field f, Object v) { } private FieldIterable fields() { - return FieldIterable.ofIgnoringStatic(typeTag.getType()); + return FieldIterable.ofIgnoringStatic(type); } private FieldIterable nonSuperFields() { - return FieldIterable.ofIgnoringSuperAndStatic(typeTag.getType()); + return FieldIterable.ofIgnoringSuperAndStatic(type); } private Tuple instantiate(Field f) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index a12c95498..b60ace974 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -11,4 +11,6 @@ public interface SubjectCreator { T withFieldChanged(Field field); T withAllFieldsChanged(); T withAllFieldsShallowlyChanged(); + T copy(T original); + Object copyIntoSuperclass(T original); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java index b7be2d776..2deee1cd4 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java @@ -13,6 +13,7 @@ public class VintageSubjectCreator implements SubjectCreator { private final TypeTag typeTag; + private final Class type; private final Configuration config; private final PrefabValues prefabValues; @@ -26,6 +27,7 @@ public VintageSubjectCreator( PrefabValues prefabValues ) { this.typeTag = typeTag; + this.type = typeTag.getType(); this.config = config; this.prefabValues = prefabValues; } @@ -70,13 +72,23 @@ public T withAllFieldsChanged() { @Override public T withAllFieldsShallowlyChanged() { return withTheseFields( - FieldIterable.ofIgnoringSuper(typeTag.getType()), + FieldIterable.ofIgnoringSuper(type), (acc, f) -> acc.withChangedField(f, prefabValues, typeTag) ); } + @Override + public T copy(T original) { + return ObjectAccessor.of(original).copy(); + } + + @Override + public Object copyIntoSuperclass(T original) { + return ObjectAccessor.of(original, type.getSuperclass()).copy(); + } + private T withAllFields(BiFunction, Field, ObjectAccessor> modifier) { - return withTheseFields(FieldIterable.of(typeTag.getType()), modifier); + return withTheseFields(FieldIterable.of(type), modifier); } private T withTheseFields( @@ -91,7 +103,7 @@ private T withTheseFields( } private ObjectAccessor createSubject() { - ClassAccessor accessor = ClassAccessor.of(typeTag.getType(), prefabValues); + ClassAccessor accessor = ClassAccessor.of(type, prefabValues); return accessor.getRedAccessor(TypeTag.NULL); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index 07796a827..6d1d53a72 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -23,12 +23,7 @@ public Context(Configuration configuration, FactoryCache factoryCache) { this.instanceCreator = new VintageInstanceCreator(prefabValues); this.subjectCreator = - new ModernSubjectCreator<>( - configuration.getTypeTag(), - configuration, - instanceCreator, - classProbe - ); + new ModernSubjectCreator<>(configuration.getTypeTag(), configuration, instanceCreator); } public Class getType() { From e9901ebc76ee3d5cf3b241f16f16eb357a0886ca Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 13 Sep 2024 12:33:39 +0200 Subject: [PATCH 33/74] Renames InstanceCreator to ValueProvider --- .../internal/checkers/AbstractDelegationChecker.java | 10 +++++----- .../internal/checkers/FieldsChecker.java | 2 +- .../checkers/MapEntryHashCodeRequirementChecker.java | 10 +++++----- .../checkers/fieldchecks/JpaLazyGetterFieldCheck.java | 6 +++--- .../checkers/fieldchecks/ReflexivityFieldCheck.java | 6 +++--- .../checkers/fieldchecks/StringFieldCheck.java | 10 +++++----- .../internal/instantiation/ModernSubjectCreator.java | 10 +++++----- .../{InstanceCreator.java => ValueProvider.java} | 4 ++-- ...eInstanceCreator.java => VintageValueProvider.java} | 6 +++--- .../nl/jqno/equalsverifier/internal/util/Context.java | 10 +++++----- 10 files changed, 37 insertions(+), 37 deletions(-) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/{InstanceCreator.java => ValueProvider.java} (69%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/{VintageInstanceCreator.java => VintageValueProvider.java} (86%) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java index 1bf718960..73d8e8549 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java @@ -5,7 +5,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; -import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; +import nl.jqno.equalsverifier.internal.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; @@ -15,7 +15,7 @@ public class AbstractDelegationChecker implements Checker { private final Class type; private final TypeTag typeTag; - private final InstanceCreator instanceCreator; + private final ValueProvider valueProvider; private final ClassProbe classProbe; private final CachedHashCodeInitializer cachedHashCodeInitializer; @@ -23,7 +23,7 @@ public AbstractDelegationChecker(Context context) { Configuration config = context.getConfiguration(); this.type = context.getType(); this.typeTag = config.getTypeTag(); - this.instanceCreator = context.getInstanceCreator(); + this.valueProvider = context.getValueProvider(); this.classProbe = context.getClassProbe(); this.cachedHashCodeInitializer = config.getCachedHashCodeInitializer(); } @@ -34,7 +34,7 @@ public void check() { checkAbstractDelegationInFields(); - Tuple tuple = instanceCreator.instantiate(typeTag); + Tuple tuple = valueProvider.provide(typeTag); T instance = tuple.getRed(); T copy = tuple.getBlue(); checkAbstractDelegation(instance, copy); @@ -72,7 +72,7 @@ private void checkAbstractDelegationInFields() { private Tuple safelyGetTuple(TypeTag tag) { try { - return instanceCreator.instantiate(tag); + return valueProvider.provide(tag); } catch (Exception ignored) { // If it fails for some reason, any reason, just return null so we can skip the test. return null; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index 821f777cc..a163e86d5 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -54,7 +54,7 @@ public FieldsChecker(Context context) { this.stringFieldCheck = new StringFieldCheck<>( subjectCreator, - context.getInstanceCreator(), + context.getValueProvider(), config.getCachedHashCodeInitializer() ); this.bigDecimalFieldCheck = diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java index 3bcd11d16..7dd930b6b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java @@ -4,7 +4,7 @@ import java.util.Map; import java.util.Objects; -import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; +import nl.jqno.equalsverifier.internal.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -12,18 +12,18 @@ public class MapEntryHashCodeRequirementChecker implements Checker { private final Configuration config; - private final InstanceCreator instanceCreator; + private final ValueProvider valueProvider; public MapEntryHashCodeRequirementChecker(Context context) { this.config = context.getConfiguration(); - this.instanceCreator = context.getInstanceCreator(); + this.valueProvider = context.getValueProvider(); } @Override public void check() { if (Map.Entry.class.isAssignableFrom(config.getType())) { - Map.Entry e = instanceCreator - .>instantiate(config.getTypeTag()) + Map.Entry e = valueProvider + .>provide(config.getTypeTag()) .getRed(); int expectedHashCode = Objects.hashCode(e.getKey()) ^ Objects.hashCode(e.getValue()); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index 7d4813e61..22309f121 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -22,7 +22,7 @@ public class JpaLazyGetterFieldCheck implements FieldCheck { private final SubjectCreator subjectCreator; - private final InstanceCreator instanceCreator; + private final ValueProvider valueProvider; private final Class type; private final ClassProbe classProbe; private final AnnotationCache annotationCache; @@ -31,7 +31,7 @@ public class JpaLazyGetterFieldCheck implements FieldCheck { public JpaLazyGetterFieldCheck(Context context) { this.subjectCreator = context.getSubjectCreator(); - this.instanceCreator = context.getInstanceCreator(); + this.valueProvider = context.getValueProvider(); this.type = context.getType(); this.classProbe = context.getClassProbe(); @@ -57,7 +57,7 @@ public void execute(FieldProbe fieldProbe) { assertEntity(fieldName, "equals", getterName, classProbe.hasMethod(getterName)); Class sub = throwingGetterCreator(getterName); - Tuple tuple = instanceCreator.instantiate(new TypeTag(sub)); + Tuple tuple = valueProvider.provide(new TypeTag(sub)); T red1 = tuple.getRed(); T red2 = tuple.getRedCopy(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index 527c4b176..b5fbe250b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -20,14 +20,14 @@ public class ReflexivityFieldCheck implements FieldCheck { private final TypeTag typeTag; private final SubjectCreator subjectCreator; - private final InstanceCreator instanceCreator; + private final ValueProvider valueProvider; private final EnumSet warningsToSuppress; private final Set nonnullFields; private final AnnotationCache annotationCache; public ReflexivityFieldCheck(Context context) { this.subjectCreator = context.getSubjectCreator(); - this.instanceCreator = context.getInstanceCreator(); + this.valueProvider = context.getValueProvider(); Configuration config = context.getConfiguration(); this.typeTag = config.getTypeTag(); @@ -75,7 +75,7 @@ private void checkValueReflexivity(FieldProbe probe) { Field field = probe.getField(); TypeTag tag = TypeTag.of(field, typeTag); - Tuple tuple = instanceCreator.instantiate(tag); + Tuple tuple = valueProvider.provide(tag); Object left = subjectCreator.withFieldSetTo(field, tuple.getRed()); Object right = subjectCreator.withFieldSetTo(field, tuple.getRedCopy()); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java index 667786f23..2a12cc5a0 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java @@ -5,8 +5,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.InstanceCreator; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -16,7 +16,7 @@ public class StringFieldCheck implements FieldCheck { public static final String ERROR_DOC_TITLE = "String equality"; private final SubjectCreator subjectCreator; - private final InstanceCreator instanceCreator; + private final ValueProvider valueProvider; private final CachedHashCodeInitializer cachedHashCodeInitializer; @SuppressFBWarnings( @@ -25,11 +25,11 @@ public class StringFieldCheck implements FieldCheck { ) public StringFieldCheck( SubjectCreator subjectCreator, - InstanceCreator instanceCreator, + ValueProvider instanceCreator, CachedHashCodeInitializer cachedHashCodeInitializer ) { this.subjectCreator = subjectCreator; - this.instanceCreator = instanceCreator; + this.valueProvider = instanceCreator; this.cachedHashCodeInitializer = cachedHashCodeInitializer; } @@ -40,7 +40,7 @@ public StringFieldCheck( ) public void execute(FieldProbe fieldProbe) { if (String.class.equals(fieldProbe.getType()) && !fieldProbe.isStatic()) { - String red = instanceCreator.instantiate(new TypeTag(String.class)).getRed(); + String red = valueProvider.provide(new TypeTag(String.class)).getRed(); final T reference; final T copy; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index db9563584..4a19b7b3d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -15,18 +15,18 @@ public class ModernSubjectCreator implements SubjectCreator { private final TypeTag typeTag; private final Class type; private final Configuration config; - private final InstanceCreator instanceCreator; + private final ValueProvider valueProvider; private final ClassProbe classProbe; public ModernSubjectCreator( TypeTag typeTag, Configuration config, - InstanceCreator instanceCreator + ValueProvider valueProvider ) { this.typeTag = typeTag; this.type = typeTag.getType(); this.config = config; - this.instanceCreator = instanceCreator; + this.valueProvider = valueProvider; this.classProbe = new ClassProbe<>(type); } @@ -110,7 +110,7 @@ public Object copyIntoSuperclass(T original) { ModernSubjectCreator superCreator = new ModernSubjectCreator( superTag, config, - instanceCreator + valueProvider ); Map values = empty(); @@ -189,6 +189,6 @@ private FieldIterable nonSuperFields() { } private Tuple instantiate(Field f) { - return instanceCreator.instantiate(TypeTag.of(f, typeTag)); + return valueProvider.provide(TypeTag.of(f, typeTag)); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ValueProvider.java similarity index 69% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ValueProvider.java index a6ccea506..7dcf5c9f2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ValueProvider.java @@ -3,6 +3,6 @@ import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -public interface InstanceCreator { - Tuple instantiate(TypeTag tag); +public interface ValueProvider { + Tuple provide(TypeTag tag); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageValueProvider.java similarity index 86% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageValueProvider.java index 70e530339..358b9fc5a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageInstanceCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageValueProvider.java @@ -6,7 +6,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -public class VintageInstanceCreator implements InstanceCreator { +public class VintageValueProvider implements ValueProvider { private final PrefabValues prefabValues; @@ -14,12 +14,12 @@ public class VintageInstanceCreator implements InstanceCreator { value = "EI_EXPOSE_REP2", justification = "PrefabValues is inherently mutable." ) - public VintageInstanceCreator(PrefabValues prefabValues) { + public VintageValueProvider(PrefabValues prefabValues) { this.prefabValues = prefabValues; } @Override - public Tuple instantiate(TypeTag tag) { + public Tuple provide(TypeTag tag) { try { return prefabValues.giveTuple(tag); } catch (RuntimeException e) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index 6d1d53a72..4c41801ea 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -11,7 +11,7 @@ public final class Context { private final Configuration configuration; private final ClassProbe classProbe; private final SubjectCreator subjectCreator; - private final InstanceCreator instanceCreator; + private final ValueProvider valueProvider; public Context(Configuration configuration, FactoryCache factoryCache) { this.type = configuration.getType(); @@ -21,9 +21,9 @@ public Context(Configuration configuration, FactoryCache factoryCache) { FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); PrefabValues prefabValues = new PrefabValues(cache); - this.instanceCreator = new VintageInstanceCreator(prefabValues); + this.valueProvider = new VintageValueProvider(prefabValues); this.subjectCreator = - new ModernSubjectCreator<>(configuration.getTypeTag(), configuration, instanceCreator); + new ModernSubjectCreator<>(configuration.getTypeTag(), configuration, valueProvider); } public Class getType() { @@ -38,8 +38,8 @@ public ClassProbe getClassProbe() { return classProbe; } - public InstanceCreator getInstanceCreator() { - return instanceCreator; + public ValueProvider getValueProvider() { + return valueProvider; } public SubjectCreator getSubjectCreator() { From 61304f64d0479133758f3b78f57885d7447eaff0 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 13 Sep 2024 12:53:01 +0200 Subject: [PATCH 34/74] Adds copyIntoSubclass() method to SubjectCreator --- .../internal/checkers/HierarchyChecker.java | 3 +- .../instantiation/InstanceCreator.java | 58 +++++++++++++++ .../instantiation/ModernSubjectCreator.java | 74 +++++++------------ .../instantiation/SubjectCreator.java | 1 + .../instantiation/VintageSubjectCreator.java | 5 ++ 5 files changed, 93 insertions(+), 48 deletions(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java index c06bcb9e8..aa4506e85 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java @@ -195,8 +195,7 @@ private void checkRedefinedSubclass() { } T reference = subjectCreator.plain(); - ObjectAccessor referenceAccessor = ObjectAccessor.of(reference); - T redefinedSub = referenceAccessor.copyIntoSubclass(redefinedSubclass); + T redefinedSub = subjectCreator.copyIntoSubclass(reference, redefinedSubclass); assertFalse( Formatter.of( "Subclass:\n %%\nequals subclass instance\n %%", diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java new file mode 100644 index 000000000..2565ca747 --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java @@ -0,0 +1,58 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.Instantiator; +import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; + +class InstanceCreator { + + private final Class type; + private final ClassProbe probe; + + public InstanceCreator(ClassProbe probe) { + this.type = probe.getType(); + this.probe = probe; + } + + public T instantiate(Map values) { + return probe.isRecord() ? createRecordInstance(values) : createClassInstance(values); + } + + private T createRecordInstance(Map values) { + List params = new ArrayList<>(); + for (Field f : fields()) { + Object value = values.get(f); + if (value == null) { + Object def = PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(f.getType()); + params.add(def); + } else { + params.add(value); + } + } + RecordProbe recordProbe = new RecordProbe<>(type); + return recordProbe.callRecordConstructor(params); + } + + private T createClassInstance(Map values) { + T instance = Instantiator.of(type).instantiate(); + ObjectAccessor accessor = ObjectAccessor.of(instance); + for (Field f : fields()) { + Object value = values.get(f); + if (value == null) { + accessor.withDefaultedField(f); + } else { + accessor.withFieldSetTo(f, value); + } + } + return instance; + } + + private FieldIterable fields() { + return FieldIterable.ofIgnoringStatic(type); + } +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index 4a19b7b3d..a82b0953d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -1,14 +1,12 @@ package nl.jqno.equalsverifier.internal.instantiation; import java.lang.reflect.Field; -import java.util.*; +import java.util.HashMap; +import java.util.Map; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.Instantiator; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; -import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; public class ModernSubjectCreator implements SubjectCreator { @@ -70,7 +68,7 @@ public T withFieldChanged(Field field) { if (FieldProbe.of(field, config).isStatic()) { return plain(); } - Object value = instantiate(field).getBlue(); + Object value = valuesFor(field).getBlue(); return createInstance(with(field, value)); } @@ -78,7 +76,7 @@ public T withFieldChanged(Field field) { public T withAllFieldsChanged() { Map values = empty(); for (Field f : fields()) { - Object value = instantiate(f).getBlue(); + Object value = valuesFor(f).getBlue(); values.put(f, value); } return createInstance(values); @@ -88,7 +86,7 @@ public T withAllFieldsChanged() { public T withAllFieldsShallowlyChanged() { Map values = empty(); for (Field f : nonSuperFields()) { - Object value = instantiate(f).getBlue(); + Object value = valuesFor(f).getBlue(); values.put(f, value); } return createInstance(values); @@ -106,25 +104,34 @@ public T copy(T original) { @Override public Object copyIntoSuperclass(T original) { - TypeTag superTag = new TypeTag(type.getSuperclass()); - ModernSubjectCreator superCreator = new ModernSubjectCreator( - superTag, - config, - valueProvider + Map values = empty(); + for (Field f : superFields()) { + Object value = FieldProbe.of(f, config).getValue(original); + values.put(f, value); + } + + InstanceCreator superCreator = new InstanceCreator<>( + new ClassProbe<>(type.getSuperclass()) ); + return superCreator.instantiate(values); + } + @Override + public S copyIntoSubclass(T original, Class subType) { Map values = empty(); - for (Field f : superCreator.fields()) { + for (Field f : fields()) { Object value = FieldProbe.of(f, config).getValue(original); values.put(f, value); } - return superCreator.createInstance(values); + InstanceCreator subCreator = new InstanceCreator<>(new ClassProbe<>(subType)); + return subCreator.instantiate(values); } private T createInstance(Map givens) { Map values = determineValues(givens); - return classProbe.isRecord() ? createRecordInstance(values) : createClassInstance(values); + InstanceCreator instaceCreator = new InstanceCreator<>(classProbe); + return instaceCreator.instantiate(values); } private Map determineValues(Map givens) { @@ -134,42 +141,13 @@ private Map determineValues(Map givens) { boolean fieldCannotBeNull = values.get(f) == null && !FieldProbe.of(f, config).canBeDefault(); if (fieldIsAbsent || fieldCannotBeNull) { - Object value = instantiate(f).getRed(); + Object value = valuesFor(f).getRed(); values.put(f, value); } } return values; } - private T createRecordInstance(Map values) { - List params = new ArrayList<>(); - for (Field f : fields()) { - Object value = values.get(f); - if (value == null) { - Object def = PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(f.getType()); - params.add(def); - } else { - params.add(value); - } - } - RecordProbe recordProbe = new RecordProbe<>(type); - return recordProbe.callRecordConstructor(params); - } - - private T createClassInstance(Map values) { - T instance = Instantiator.of(type).instantiate(); - ObjectAccessor accessor = ObjectAccessor.of(instance); - for (Field f : fields()) { - Object value = values.get(f); - if (value == null) { - accessor.withDefaultedField(f); - } else { - accessor.withFieldSetTo(f, value); - } - } - return instance; - } - private Map empty() { return new HashMap<>(); } @@ -184,11 +162,15 @@ private FieldIterable fields() { return FieldIterable.ofIgnoringStatic(type); } + private FieldIterable superFields() { + return FieldIterable.ofIgnoringStatic(type.getSuperclass()); + } + private FieldIterable nonSuperFields() { return FieldIterable.ofIgnoringSuperAndStatic(type); } - private Tuple instantiate(Field f) { + private Tuple valuesFor(Field f) { return valueProvider.provide(TypeTag.of(f, typeTag)); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java index b60ace974..9dc239f02 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java @@ -13,4 +13,5 @@ public interface SubjectCreator { T withAllFieldsShallowlyChanged(); T copy(T original); Object copyIntoSuperclass(T original); + S copyIntoSubclass(T original, Class subType); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java index 2deee1cd4..1a14131c6 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java @@ -87,6 +87,11 @@ public Object copyIntoSuperclass(T original) { return ObjectAccessor.of(original, type.getSuperclass()).copy(); } + @Override + public S copyIntoSubclass(T original, Class subType) { + return ObjectAccessor.of(original).copyIntoSubclass(subType); + } + private T withAllFields(BiFunction, Field, ObjectAccessor> modifier) { return withTheseFields(FieldIterable.of(type), modifier); } From 52722be7c416870cf7b79c9a823c5d7757438538 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 13 Sep 2024 13:31:27 +0200 Subject: [PATCH 35/74] Replaces call to copyIntoAnonymousSubclass() with call to SubjectCreator.copyIntoSubclass() --- .../internal/checkers/HierarchyChecker.java | 10 +++++++--- .../internal/reflection/Instantiator.java | 6 +++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java index aa4506e85..13052541c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java @@ -9,7 +9,7 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.util.*; @@ -158,8 +158,12 @@ private void checkSubclass() { } T reference = subjectCreator.plain(); - ObjectAccessor referenceAccessor = ObjectAccessor.of(reference); - T equalSub = referenceAccessor.copyIntoAnonymousSubclass(); + + @SuppressWarnings("unchecked") + Class anonymousSubclass = (Class) Instantiator.giveDynamicSubclass( + reference.getClass() // don't use type directly, as reference may already be a subclass if type was abstract + ); + T equalSub = subjectCreator.copyIntoSubclass(reference, anonymousSubclass); if (config.isUsingGetClass()) { Formatter formatter = Formatter.of( diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Instantiator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Instantiator.java index f9d2472ee..bd89aa77d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Instantiator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Instantiator.java @@ -75,10 +75,14 @@ public T instantiate() { * @return An instance of an anonymous subclass of T. */ public T instantiateAnonymousSubclass() { - Class proxyClass = giveDynamicSubclass(type, "", b -> b); + Class proxyClass = giveDynamicSubclass(type); return ObjenesisWrapper.getObjenesis().newInstance(proxyClass); } + public static Class giveDynamicSubclass(Class superclass) { + return giveDynamicSubclass(superclass, "", b -> b); + } + @SuppressWarnings("unchecked") public static synchronized Class giveDynamicSubclass( Class superclass, From 7fea41c7f354cb1ba7efa46b75b2746abeeb54d9 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 13 Sep 2024 13:40:20 +0200 Subject: [PATCH 36/74] Replaces last calls to ObjectAccessor with FieldProbes --- .../checkers/fieldchecks/ArrayFieldCheck.java | 11 ++++------- .../fieldchecks/NullPointerExceptionFieldCheck.java | 3 +-- .../internal/architecture/ArchitectureTest.java | 4 ++++ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java index 69f81672e..94336388a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java @@ -3,10 +3,8 @@ import static nl.jqno.equalsverifier.internal.util.Assert.assertEquals; import java.lang.reflect.Array; -import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -34,7 +32,7 @@ public void execute(FieldProbe fieldProbe) { } T reference = subjectCreator.plain(); - T changed = replaceInnermostArrayValue(reference, fieldProbe.getField()); + T changed = replaceInnermostArrayValue(reference, fieldProbe); if (arrayType.getComponentType().isArray()) { assertDeep(fieldProbe.getName(), reference, changed); @@ -43,10 +41,9 @@ public void execute(FieldProbe fieldProbe) { } } - private T replaceInnermostArrayValue(T reference, Field field) { - ObjectAccessor objectAccessor = ObjectAccessor.of(reference); - Object newArray = arrayCopy(objectAccessor.getField(field)); - return subjectCreator.withFieldSetTo(field, newArray); + private T replaceInnermostArrayValue(T reference, FieldProbe fieldProbe) { + Object newArray = arrayCopy(fieldProbe.getValue(reference)); + return subjectCreator.withFieldSetTo(fieldProbe.getField(), newArray); } private Object arrayCopy(Object array) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java index 12ea086fe..e66f3f53b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java @@ -7,7 +7,6 @@ import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldModifier; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -41,7 +40,7 @@ public void execute(FieldProbe fieldProbe) { if (fieldProbe.isStatic()) { T reference = subjectCreator.plain(); FieldModifier fieldModifier = FieldModifier.of(fieldProbe.getField(), reference); - Object saved = ObjectAccessor.of(reference).getField(fieldProbe.getField()); + Object saved = fieldProbe.getValue(reference); fieldModifier.defaultStaticField(); performTests(fieldProbe.getField(), subjectCreator.plain(), subjectCreator.plain()); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index f49908d17..72fc93de8 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -8,6 +8,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; +import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; @AnalyzeClasses(packages = "nl.jqno.equalsverifier") public final class ArchitectureTest { @@ -21,6 +22,9 @@ public final class ArchitectureTest { .areAssignableTo(ClassAccessor.class) .orShould() .accessClassesThat() + .areAssignableTo(ObjectAccessor.class) + .orShould() + .accessClassesThat() .areAssignableTo(FieldAccessor.class) .orShould() .accessClassesThat() From be4c600e76ec37ffc6bc20de0790671201bc7c6a Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 13 Sep 2024 19:32:29 +0200 Subject: [PATCH 37/74] Simplifies InstanceCreator --- .../instantiation/InstanceCreator.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java index 2565ca747..06ad7dd30 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.function.BiConsumer; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; @@ -25,15 +26,7 @@ public T instantiate(Map values) { private T createRecordInstance(Map values) { List params = new ArrayList<>(); - for (Field f : fields()) { - Object value = values.get(f); - if (value == null) { - Object def = PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(f.getType()); - params.add(def); - } else { - params.add(value); - } - } + traverseFields(values, (f, v) -> params.add(v)); RecordProbe recordProbe = new RecordProbe<>(type); return recordProbe.callRecordConstructor(params); } @@ -41,15 +34,18 @@ private T createRecordInstance(Map values) { private T createClassInstance(Map values) { T instance = Instantiator.of(type).instantiate(); ObjectAccessor accessor = ObjectAccessor.of(instance); + traverseFields(values, (f, v) -> accessor.withFieldSetTo(f, v)); + return instance; + } + + private void traverseFields(Map values, BiConsumer setValue) { for (Field f : fields()) { Object value = values.get(f); if (value == null) { - accessor.withDefaultedField(f); - } else { - accessor.withFieldSetTo(f, value); + value = PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(f.getType()); } + setValue.accept(f, value); } - return instance; } private FieldIterable fields() { From 5791fd0d87b7e640e4c0b71eace3ff3412193815 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 13 Sep 2024 20:07:53 +0200 Subject: [PATCH 38/74] Removes Configuration from FieldProbe constructor and puts it in the one method that uses it --- .../internal/checkers/FieldInspector.java | 7 +-- .../internal/checkers/FieldsChecker.java | 2 +- .../internal/checkers/NullChecker.java | 5 +-- .../NullPointerExceptionFieldCheck.java | 2 +- .../fieldchecks/ReflexivityFieldCheck.java | 2 +- .../fieldchecks/SignificantFieldCheck.java | 5 ++- .../internal/instantiation/FieldProbe.java | 40 ++++++++--------- .../instantiation/ModernSubjectCreator.java | 10 ++--- .../instantiation/VintageSubjectCreator.java | 2 +- .../instantiation/FieldProbeTest.java | 43 ++++++++----------- 10 files changed, 51 insertions(+), 67 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java index f90e91961..5e019f2d7 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java @@ -4,21 +4,18 @@ import nl.jqno.equalsverifier.internal.checkers.fieldchecks.FieldCheck; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.util.Configuration; public class FieldInspector { private final Class type; - private final Configuration config; - public FieldInspector(Class type, Configuration config) { + public FieldInspector(Class type) { this.type = type; - this.config = config; } public void check(FieldCheck check) { for (Field field : FieldIterable.of(type)) { - FieldProbe fieldProbe = FieldProbe.of(field, config); + FieldProbe fieldProbe = FieldProbe.of(field); check.execute(fieldProbe); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index a163e86d5..e8aa4811a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -64,7 +64,7 @@ public FieldsChecker(Context context) { @Override public void check() { - FieldInspector inspector = new FieldInspector<>(context.getType(), config); + FieldInspector inspector = new FieldInspector<>(context.getType()); if (!context.getClassProbe().isEqualsInheritedFromObject()) { inspector.check(arrayFieldCheck); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java index f02c44c61..736a06c6a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/NullChecker.java @@ -18,10 +18,7 @@ public void check() { return; } - FieldInspector inspector = new FieldInspector<>( - context.getType(), - context.getConfiguration() - ); + FieldInspector inspector = new FieldInspector<>(context.getType()); inspector.check(new NullPointerExceptionFieldCheck<>(context)); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java index e66f3f53b..9763b7f6c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java @@ -33,7 +33,7 @@ public void execute(FieldProbe fieldProbe) { if (fieldProbe.isPrimitive()) { return; } - if (fieldProbe.isAnnotatedNonnull()) { + if (fieldProbe.isAnnotatedNonnull(config.getAnnotationCache())) { return; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index b5fbe250b..d48126989 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -95,7 +95,7 @@ private void checkNullReflexivity(FieldProbe fieldProbe) { } boolean nullWarningIsSuppressed = warningsToSuppress.contains(Warning.NULL_FIELDS); - boolean fieldIsNonNull = fieldProbe.isAnnotatedNonnull(); + boolean fieldIsNonNull = fieldProbe.isAnnotatedNonnull(annotationCache); boolean fieldIsMentionedExplicitly = nonnullFields.contains(field.getName()); if (nullWarningIsSuppressed || fieldIsNonNull || fieldIsMentionedExplicitly) { return; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java index 6aca90c71..aaf048159 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java @@ -16,6 +16,7 @@ public class SignificantFieldCheck implements FieldCheck { private final SubjectCreator subjectCreator; + private final Configuration config; private final Class type; private final EnumSet warningsToSuppress; private final Set ignoredFields; @@ -25,7 +26,7 @@ public class SignificantFieldCheck implements FieldCheck { public SignificantFieldCheck(Context context, Predicate isCachedHashCodeField) { this.subjectCreator = context.getSubjectCreator(); - Configuration config = context.getConfiguration(); + this.config = context.getConfiguration(); this.type = config.getType(); this.warningsToSuppress = config.getWarningsToSuppress(); this.ignoredFields = config.getIgnoredFields(); @@ -47,7 +48,7 @@ public void execute(FieldProbe fieldProbe) { fieldProbe, false ); - if (fieldProbe.canBeDefault()) { + if (fieldProbe.canBeDefault(config)) { checkValues( subjectCreator.withAllFieldsDefaulted(), subjectCreator.withAllFieldsDefaulted(), diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java index ca92488c0..8682e4baa 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java @@ -6,7 +6,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.Set; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; @@ -18,29 +17,20 @@ public final class FieldProbe { private final Field field; - private final boolean isWarningZeroSuppressed; - private final boolean isWarningNullSuppressed; - private final Set nonnullFields; - private final AnnotationCache annotationCache; - /** Private constructor. Call {@link #of(Field, Configuration)} to instantiate. */ - private FieldProbe(Field field, Configuration config) { + /** Private constructor. Call {@link #of(Field)} to instantiate. */ + private FieldProbe(Field field) { this.field = field; - this.isWarningZeroSuppressed = config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS); - this.isWarningNullSuppressed = config.getWarningsToSuppress().contains(Warning.NULL_FIELDS); - this.nonnullFields = config.getNonnullFields(); - this.annotationCache = config.getAnnotationCache(); } /** * Factory method. * * @param field The field to access. - * @param config A configuration object; cannot be null. * @return A {@link FieldProbe} for {@link #field}. */ - public static FieldProbe of(Field field, Configuration config) { - return new FieldProbe(field, config); + public static FieldProbe of(Field field) { + return new FieldProbe(field); } /** @return The field itself. */ @@ -101,24 +91,32 @@ public boolean isEmptyOrSingleValueEnum() { return type.isEnum() && type.getEnumConstants().length <= 1; } - /** @return Whether the field can be set to the default value for its type. */ - public boolean canBeDefault() { + /** + * @param config The configuration affects whether a given field van be default. + * @return Whether the field can be set to the default value for its type. + */ + public boolean canBeDefault(Configuration config) { if (isPrimitive()) { - return !isWarningZeroSuppressed; + return !config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS); } - boolean isAnnotated = isAnnotatedNonnull(); - boolean isMentionedExplicitly = nonnullFields.contains(field.getName()); - return !isWarningNullSuppressed && !isAnnotated && !isMentionedExplicitly; + boolean isAnnotated = isAnnotatedNonnull(config.getAnnotationCache()); + boolean isMentionedExplicitly = config.getNonnullFields().contains(field.getName()); + return ( + !config.getWarningsToSuppress().contains(Warning.NULL_FIELDS) && + !isAnnotated && + !isMentionedExplicitly + ); } /** * Checks whether the given field is marked with an Nonnull annotation, whether directly, or * through some default annotation mechanism. * + * @param annotationCache To retrieve annotations from. * @return True if the field is to be treated as Nonnull. */ - public boolean isAnnotatedNonnull() { + public boolean isAnnotatedNonnull(AnnotationCache annotationCache) { Class type = field.getDeclaringClass(); if (annotationCache.hasFieldAnnotation(type, field.getName(), NONNULL)) { return true; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java index a82b0953d..a2f84e58f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java @@ -65,7 +65,7 @@ public T withFieldSetTo(Field field, Object value) { @Override public T withFieldChanged(Field field) { - if (FieldProbe.of(field, config).isStatic()) { + if (FieldProbe.of(field).isStatic()) { return plain(); } Object value = valuesFor(field).getBlue(); @@ -96,7 +96,7 @@ public T withAllFieldsShallowlyChanged() { public T copy(T original) { Map values = empty(); for (Field f : fields()) { - Object value = FieldProbe.of(f, config).getValue(original); + Object value = FieldProbe.of(f).getValue(original); values.put(f, value); } return createInstance(values); @@ -106,7 +106,7 @@ public T copy(T original) { public Object copyIntoSuperclass(T original) { Map values = empty(); for (Field f : superFields()) { - Object value = FieldProbe.of(f, config).getValue(original); + Object value = FieldProbe.of(f).getValue(original); values.put(f, value); } @@ -120,7 +120,7 @@ public Object copyIntoSuperclass(T original) { public S copyIntoSubclass(T original, Class subType) { Map values = empty(); for (Field f : fields()) { - Object value = FieldProbe.of(f, config).getValue(original); + Object value = FieldProbe.of(f).getValue(original); values.put(f, value); } @@ -139,7 +139,7 @@ private Map determineValues(Map givens) { for (Field f : fields()) { boolean fieldIsAbsent = !values.containsKey(f); boolean fieldCannotBeNull = - values.get(f) == null && !FieldProbe.of(f, config).canBeDefault(); + values.get(f) == null && !FieldProbe.of(f).canBeDefault(config); if (fieldIsAbsent || fieldCannotBeNull) { Object value = valuesFor(f).getRed(); values.put(f, value); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java index 1a14131c6..e9b0ee743 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java @@ -45,7 +45,7 @@ public T withFieldDefaulted(Field field) { @Override public T withAllFieldsDefaulted() { return withAllFields((acc, f) -> - FieldProbe.of(f, config).canBeDefault() ? acc.withDefaultedField(f) : acc + FieldProbe.of(f).canBeDefault(config) ? acc.withDefaultedField(f) : acc ); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java index 67959a115..44754bbe5 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java @@ -12,15 +12,13 @@ public class FieldProbeTest { private static final String FIELD_NAME = "field"; + private Configuration config = ConfigurationHelper.emptyConfiguration(ObjectContainer.class); @Test public void getField() throws NoSuchFieldException { ObjectContainer foo = new ObjectContainer(); Field field = foo.getClass().getDeclaredField(FIELD_NAME); - FieldProbe probe = FieldProbe.of( - field, - ConfigurationHelper.emptyConfiguration(ObjectContainer.class) - ); + FieldProbe probe = FieldProbe.of(field); assertSame(field, probe.getField()); } @@ -126,57 +124,50 @@ public void isEmptyEnum() { public void canBeDefault_forObject() { ObjectContainer foo = new ObjectContainer(); FieldProbe probe = getProbeFor(foo, FIELD_NAME); - assertTrue(probe.canBeDefault()); + assertTrue(probe.canBeDefault(config)); } @Test public void canBeDefault_primitive() { PrimitiveContainer foo = new PrimitiveContainer(); FieldProbe probe = getProbeFor(foo, FIELD_NAME); - assertTrue(probe.canBeDefault()); + assertTrue(probe.canBeDefault(config)); } @Test public void canBeDefault_primitiveWithWarningSuppressed() { PrimitiveContainer foo = new PrimitiveContainer(); - Configuration config = ConfigurationHelper.emptyConfiguration( - foo.getClass(), - Warning.ZERO_FIELDS - ); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME, config); - assertFalse(probe.canBeDefault()); + config = ConfigurationHelper.emptyConfiguration(foo.getClass(), Warning.ZERO_FIELDS); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertFalse(probe.canBeDefault(config)); } @Test public void canBeDefault_isMentionedExplicitly() { ObjectContainer foo = new ObjectContainer(); - Configuration config = ConfigurationHelper.emptyConfigurationWithNonnullFields( - foo.getClass(), - FIELD_NAME - ); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME, config); - assertFalse(probe.canBeDefault()); + config = + ConfigurationHelper.emptyConfigurationWithNonnullFields(foo.getClass(), FIELD_NAME); + FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + assertFalse(probe.canBeDefault(config)); } @Test public void canBeDefault_annotated() { NonNullContainer foo = new NonNullContainer(); + config = + ConfigurationHelper.emptyConfigurationWithNonnullFields(foo.getClass(), FIELD_NAME); FieldProbe probe = getProbeFor(foo, FIELD_NAME); - assertFalse(probe.canBeDefault()); + assertFalse(probe.canBeDefault(config)); } private FieldProbe getProbeFor(Object object, String fieldName) { - return getAccessorFor( - object, - fieldName, - ConfigurationHelper.emptyConfiguration(object.getClass()) - ); + return getAccessorFor(object, fieldName); } - private FieldProbe getAccessorFor(Object object, String fieldName, Configuration config) { + private FieldProbe getAccessorFor(Object object, String fieldName) { try { Field field = object.getClass().getDeclaredField(fieldName); - return FieldProbe.of(field, config); + return FieldProbe.of(field); } catch (NoSuchFieldException e) { throw new IllegalArgumentException("fieldName: " + fieldName); } From 36565410fe61b446bffc8552d7648aceeca83b5c Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 13 Sep 2024 20:09:19 +0200 Subject: [PATCH 39/74] Replaces ObjectAccessor with new FieldMutator in InstanceCreator --- .../internal/instantiation/FieldMutator.java | 25 +++++++++++++++++++ .../instantiation/InstanceCreator.java | 7 +++--- 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java new file mode 100644 index 000000000..e0dad6d59 --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java @@ -0,0 +1,25 @@ +package nl.jqno.equalsverifier.internal.instantiation; + +import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; + +import java.lang.reflect.Field; + +class FieldMutator { + + private final FieldProbe probe; + private final Field field; + + FieldMutator(FieldProbe probe) { + this.probe = probe; + this.field = probe.getField(); + } + + public void setNewValue(Object object, Object newValue) { + rethrow(() -> { + if (probe.canBeModifiedReflectively()) { + field.setAccessible(true); + field.set(object, newValue); + } + }); + } +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java index 06ad7dd30..45e3fe480 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java @@ -7,7 +7,6 @@ import java.util.function.BiConsumer; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; class InstanceCreator { @@ -33,8 +32,10 @@ private T createRecordInstance(Map values) { private T createClassInstance(Map values) { T instance = Instantiator.of(type).instantiate(); - ObjectAccessor accessor = ObjectAccessor.of(instance); - traverseFields(values, (f, v) -> accessor.withFieldSetTo(f, v)); + traverseFields( + values, + (f, v) -> new FieldMutator(FieldProbe.of(f)).setNewValue(instance, v) + ); return instance; } From 9a83734d4e0ac516d534b9f7cc925365fffe039e Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sat, 14 Sep 2024 09:46:40 +0200 Subject: [PATCH 40/74] Replaces FieldModifier with FieldMutator --- .../NullPointerExceptionFieldCheck.java | 15 ++++++++------- .../internal/instantiation/FieldMutator.java | 4 ++-- .../internal/architecture/ArchitectureTest.java | 7 ++++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java index 9763b7f6c..de32ac5cb 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java @@ -4,12 +4,10 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.instantiation.FieldMutator; import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.reflection.FieldModifier; -import nl.jqno.equalsverifier.internal.util.Configuration; -import nl.jqno.equalsverifier.internal.util.Context; -import nl.jqno.equalsverifier.internal.util.Formatter; +import nl.jqno.equalsverifier.internal.util.*; @SuppressFBWarnings( value = "RV_RETURN_VALUE_IGNORED", @@ -39,12 +37,15 @@ public void execute(FieldProbe fieldProbe) { if (fieldProbe.isStatic()) { T reference = subjectCreator.plain(); - FieldModifier fieldModifier = FieldModifier.of(fieldProbe.getField(), reference); + FieldMutator fieldMutator = new FieldMutator(fieldProbe); Object saved = fieldProbe.getValue(reference); - fieldModifier.defaultStaticField(); + fieldMutator.setNewValue( + reference, + PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(fieldProbe.getType()) + ); performTests(fieldProbe.getField(), subjectCreator.plain(), subjectCreator.plain()); - fieldModifier.set(saved); + fieldMutator.setNewValue(reference, saved); } else { T changed = subjectCreator.withFieldDefaulted(fieldProbe.getField()); performTests(fieldProbe.getField(), subjectCreator.plain(), changed); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java index e0dad6d59..af3d6ca92 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java @@ -4,12 +4,12 @@ import java.lang.reflect.Field; -class FieldMutator { +public class FieldMutator { private final FieldProbe probe; private final Field field; - FieldMutator(FieldProbe probe) { + public FieldMutator(FieldProbe probe) { this.probe = probe; this.field = probe.getField(); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index 72fc93de8..b0878797d 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -6,9 +6,7 @@ import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchRule; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.*; @AnalyzeClasses(packages = "nl.jqno.equalsverifier") public final class ArchitectureTest { @@ -28,6 +26,9 @@ public final class ArchitectureTest { .areAssignableTo(FieldAccessor.class) .orShould() .accessClassesThat() + .areAssignableTo(FieldModifier.class) + .orShould() + .accessClassesThat() .areAssignableTo(PrefabValues.class); @ArchTest From 5a3ee1ff1eeed799abe18785a3987ae8e010b784 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sat, 14 Sep 2024 10:03:00 +0200 Subject: [PATCH 41/74] Introduces vintage package for old-style reflection code --- .../{ => vintage}/RecordObjectAccessorCopyingTest.java | 5 +++-- .../{ => vintage}/RecordObjectAccessorModificationTest.java | 2 +- .../{ => vintage}/RecordObjectAccessorScramblingTest.java | 3 ++- .../reflection/{ => vintage}/RecordObjectAccessorTest.java | 3 ++- .../internal/instantiation/VintageSubjectCreator.java | 4 ++-- .../internal/prefabvalues/factories/FallbackFactory.java | 2 +- .../internal/reflection/{ => vintage}/ClassAccessor.java | 3 ++- .../internal/reflection/{ => vintage}/FieldAccessor.java | 2 +- .../internal/reflection/{ => vintage}/FieldModifier.java | 2 +- .../reflection/{ => vintage}/InPlaceObjectAccessor.java | 4 +++- .../internal/reflection/{ => vintage}/ObjectAccessor.java | 3 ++- .../reflection/{ => vintage}/RecordObjectAccessor.java | 2 +- .../nl/jqno/equalsverifier/internal/testhelpers/Util.java | 2 +- .../java/nl/jqno/equalsverifier/internal/util/Formatter.java | 2 +- .../jqno/equalsverifier/internal/util/PrefabValuesApi.java | 2 +- .../internal/architecture/ArchitectureTest.java | 5 ++++- .../internal/reflection/{ => vintage}/ClassAccessorTest.java | 2 +- .../internal/reflection/{ => vintage}/FieldAccessorTest.java | 2 +- .../internal/reflection/{ => vintage}/FieldModifierTest.java | 3 ++- .../{ => vintage}/InPlaceObjectAccessorCopyingTest.java | 3 ++- .../{ => vintage}/InPlaceObjectAccessorModificationTest.java | 2 +- .../{ => vintage}/InPlaceObjectAccessorScramblingTest.java | 2 +- .../reflection/{ => vintage}/InPlaceObjectAccessorTest.java | 2 +- .../verify_release/jar/helper/JarAsserter.java | 2 +- 24 files changed, 38 insertions(+), 26 deletions(-) rename equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/RecordObjectAccessorCopyingTest.java (92%) rename equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/RecordObjectAccessorModificationTest.java (98%) rename equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/RecordObjectAccessorScramblingTest.java (98%) rename equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/RecordObjectAccessorTest.java (96%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/ClassAccessor.java (97%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/FieldAccessor.java (98%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/FieldModifier.java (98%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/InPlaceObjectAccessor.java (95%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/ObjectAccessor.java (98%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/RecordObjectAccessor.java (98%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/ClassAccessorTest.java (98%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/FieldAccessorTest.java (98%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/FieldModifierTest.java (99%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/InPlaceObjectAccessorCopyingTest.java (96%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/InPlaceObjectAccessorModificationTest.java (98%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/InPlaceObjectAccessorScramblingTest.java (99%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{ => vintage}/InPlaceObjectAccessorTest.java (95%) diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorCopyingTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java similarity index 92% rename from equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorCopyingTest.java rename to equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java index 0c6ed35b8..6098c8dac 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorCopyingTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java @@ -1,9 +1,11 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static org.junit.jupiter.api.Assertions.*; import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.Test; @@ -56,7 +58,6 @@ private RecordObjectAccessor create(T object) { return new RecordObjectAccessor(object, (Class) object.getClass()); } - @SuppressWarnings("unchecked") private T instantiate(Class type) { return Instantiator.of(type).instantiate(); } diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorModificationTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java similarity index 98% rename from equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorModificationTest.java rename to equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java index decfa4e0a..6f66b40c4 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorModificationTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotSame; diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorScramblingTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java similarity index 98% rename from equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorScramblingTest.java rename to equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java index ce1af09c6..2caee1792 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorScramblingTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.*; @@ -10,6 +10,7 @@ import java.util.List; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; import nl.jqno.equalsverifier.internal.prefabvalues.*; +import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java similarity index 96% rename from equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorTest.java rename to equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java index beb9eb68e..a43b024cb 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessorTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; @@ -12,6 +12,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java index e9b0ee743..bf5af4e2d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java @@ -5,9 +5,9 @@ import java.util.function.BiFunction; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; public class VintageSubjectCreator implements SubjectCreator { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java index 44355f350..4e6d99e3a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java @@ -8,8 +8,8 @@ import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; /** * Implementation of {@link PrefabValueFactory} that instantiates types "by force". diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java similarity index 97% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java index 812d11f4f..6f3be922e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java @@ -1,8 +1,9 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.Instantiator; /** * Instantiates and populates objects of a given class. {@link ClassAccessor} can create two diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessor.java similarity index 98% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldAccessor.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessor.java index 49a3ab1a7..6ee95b3b4 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessor.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldModifier.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java similarity index 98% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldModifier.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java index 8dd428481..2fe0596c2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldModifier.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java similarity index 95% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessor.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java index a3e97d0b9..8341862a1 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import java.lang.reflect.Field; import java.util.LinkedHashSet; @@ -6,6 +6,8 @@ import java.util.function.Predicate; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.Instantiator; /** * Implementation of ObjectAccessor that modifies its wrapped object in-place through reflection. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java similarity index 98% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ObjectAccessor.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java index e3ec543fa..24f0c7c08 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java @@ -1,10 +1,11 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import java.lang.reflect.Field; import java.util.LinkedHashSet; import java.util.function.Predicate; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; /** * Wraps an object to provide access to it. ObjectAccessor can copy and scramble the wrapped object. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java similarity index 98% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessor.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java index 7fd4a142d..2fc53461d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import java.lang.reflect.Field; import java.util.LinkedHashSet; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/testhelpers/Util.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/testhelpers/Util.java index 5a99ae69b..fb21349fd 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/testhelpers/Util.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/testhelpers/Util.java @@ -4,8 +4,8 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.Objects; -import nl.jqno.equalsverifier.internal.reflection.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.vintage.FieldAccessor; public final class Util { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Formatter.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Formatter.java index ca1ad1d81..7a38e2b8e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Formatter.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Formatter.java @@ -3,7 +3,7 @@ import java.lang.reflect.Field; import java.util.regex.Matcher; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; /** * Formats a string with the contents of one or more objects. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java index a8ddc3ab4..30940e367 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java @@ -7,7 +7,7 @@ import nl.jqno.equalsverifier.Func.Func2; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; -import nl.jqno.equalsverifier.internal.reflection.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; public final class PrefabValuesApi { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index b0878797d..8f8843692 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -6,7 +6,10 @@ import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchRule; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.reflection.*; +import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.FieldAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.FieldModifier; +import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; @AnalyzeClasses(packages = "nl.jqno.equalsverifier") public final class ArchitectureTest { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java similarity index 98% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java index 762c6c274..fbac5530d 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessorTest.java similarity index 98% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldAccessorTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessorTest.java index 0eaa74b37..e3157c23c 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessorTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static org.junit.jupiter.api.Assertions.*; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldModifierTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java similarity index 99% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldModifierTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java index 544b73ad3..cc452c507 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldModifierTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -14,6 +14,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.testhelpers.types.Point; import nl.jqno.equalsverifier.testhelpers.types.PointContainer; import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.AbstractAndInterfaceArrayContainer; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorCopyingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java similarity index 96% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorCopyingTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java index 072d2cba1..ddd239ed7 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorCopyingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java @@ -1,8 +1,9 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static org.junit.jupiter.api.Assertions.*; import java.lang.reflect.Field; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.testhelpers.types.ColorPoint3D; import nl.jqno.equalsverifier.testhelpers.types.Point; import nl.jqno.equalsverifier.testhelpers.types.Point3D; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorModificationTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorModificationTest.java similarity index 98% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorModificationTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorModificationTest.java index 90a6ca690..bb9ab9fcc 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorModificationTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorModificationTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorScramblingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java similarity index 99% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorScramblingTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java index 6fba95fc7..93bba8b56 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorScramblingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.*; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorTest.java similarity index 95% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorTest.java index 9b3d8fce0..1a6bd4251 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InPlaceObjectAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; diff --git a/equalsverifier-release-verify/src/test/java/nl/jqno/equalsverifier/verify_release/jar/helper/JarAsserter.java b/equalsverifier-release-verify/src/test/java/nl/jqno/equalsverifier/verify_release/jar/helper/JarAsserter.java index 6ad902ab4..47554af74 100644 --- a/equalsverifier-release-verify/src/test/java/nl/jqno/equalsverifier/verify_release/jar/helper/JarAsserter.java +++ b/equalsverifier-release-verify/src/test/java/nl/jqno/equalsverifier/verify_release/jar/helper/JarAsserter.java @@ -23,7 +23,7 @@ public JarAsserter(JarReader reader) { public void assertPresenceOfCoreClasses() { assertPresenceOf( EV + "/EqualsVerifier.class", - EV + "/internal/reflection/ClassAccessor.class", + EV + "/internal/reflection/vintage/ClassAccessor.class", EV + "/internal/prefabvalues/PrefabValues.class" ); } From 011e1b480e943cadc43458524e1e28db6cd10063 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sat, 14 Sep 2024 10:09:09 +0200 Subject: [PATCH 42/74] Moves instantiation package into reflection package --- .../internal/reflection/ClassProbeRecordTest.java | 1 - .../internal/reflection/ClassAccessorSealedTest.java | 1 - .../internal/checkers/AbstractDelegationChecker.java | 4 ++-- .../equalsverifier/internal/checkers/ExamplesChecker.java | 2 +- .../equalsverifier/internal/checkers/FieldInspector.java | 2 +- .../equalsverifier/internal/checkers/FieldsChecker.java | 4 ++-- .../equalsverifier/internal/checkers/HierarchyChecker.java | 4 ++-- .../checkers/MapEntryHashCodeRequirementChecker.java | 2 +- .../equalsverifier/internal/checkers/RecordChecker.java | 4 ++-- .../equalsverifier/internal/checkers/SignatureChecker.java | 2 +- .../internal/checkers/fieldchecks/ArrayFieldCheck.java | 4 ++-- .../internal/checkers/fieldchecks/BigDecimalFieldCheck.java | 4 ++-- .../internal/checkers/fieldchecks/FieldCheck.java | 2 +- .../checkers/fieldchecks/FloatAndDoubleFieldCheck.java | 4 ++-- .../checkers/fieldchecks/JpaLazyGetterFieldCheck.java | 5 ++++- .../checkers/fieldchecks/MutableStateFieldCheck.java | 4 ++-- .../fieldchecks/NullPointerExceptionFieldCheck.java | 6 +++--- .../checkers/fieldchecks/ReflexivityFieldCheck.java | 5 ++++- .../checkers/fieldchecks/SignificantFieldCheck.java | 4 ++-- .../internal/checkers/fieldchecks/StringFieldCheck.java | 6 +++--- .../internal/checkers/fieldchecks/SymmetryFieldCheck.java | 4 ++-- .../internal/checkers/fieldchecks/TransientFieldsCheck.java | 4 ++-- .../checkers/fieldchecks/TransitivityFieldCheck.java | 4 ++-- .../internal/{instantiation => reflection}/ClassProbe.java | 4 +--- .../{instantiation => reflection}/FieldMutator.java | 2 +- .../internal/{instantiation => reflection}/FieldProbe.java | 2 +- .../internal/{instantiation => reflection}/RecordProbe.java | 3 +-- .../{ => reflection}/instantiation/InstanceCreator.java | 5 ++--- .../instantiation/ModernSubjectCreator.java | 4 +++- .../{ => reflection}/instantiation/SubjectCreator.java | 2 +- .../{ => reflection}/instantiation/ValueProvider.java | 2 +- .../instantiation/VintageSubjectCreator.java | 3 ++- .../instantiation/VintageValueProvider.java | 2 +- .../internal/reflection/vintage/RecordObjectAccessor.java | 2 +- .../java/nl/jqno/equalsverifier/internal/util/Context.java | 6 +++++- .../{instantiation => reflection}/ClassProbeTest.java | 2 +- .../{instantiation => reflection}/FieldProbeTest.java | 2 +- 37 files changed, 65 insertions(+), 58 deletions(-) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{instantiation => reflection}/ClassProbe.java (95%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{instantiation => reflection}/FieldMutator.java (91%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{instantiation => reflection}/FieldProbe.java (98%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{instantiation => reflection}/RecordProbe.java (95%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection}/instantiation/InstanceCreator.java (89%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection}/instantiation/ModernSubjectCreator.java (96%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection}/instantiation/SubjectCreator.java (88%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection}/instantiation/ValueProvider.java (74%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection}/instantiation/VintageSubjectCreator.java (96%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection}/instantiation/VintageValueProvider.java (95%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{instantiation => reflection}/ClassProbeTest.java (98%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{instantiation => reflection}/FieldProbeTest.java (99%) diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeRecordTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeRecordTest.java index 998914ad4..327141776 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeRecordTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeRecordTest.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; -import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import org.junit.jupiter.api.Test; public class ClassProbeRecordTest { diff --git a/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorSealedTest.java b/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorSealedTest.java index d53786010..2b7ad0633 100644 --- a/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorSealedTest.java +++ b/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassAccessorSealedTest.java @@ -3,7 +3,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; import org.junit.jupiter.api.Test; public class ClassAccessorSealedTest { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java index 73d8e8549..a92f890e4 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java @@ -4,11 +4,11 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; -import nl.jqno.equalsverifier.internal.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.util.*; public class AbstractDelegationChecker implements Checker { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java index 025abc879..fd53331b1 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/ExamplesChecker.java @@ -9,8 +9,8 @@ import java.util.List; import java.util.Objects; import nl.jqno.equalsverifier.internal.exceptions.AssertionException; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.*; public class ExamplesChecker implements Checker { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java index 5e019f2d7..9905082c6 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldInspector.java @@ -2,8 +2,8 @@ import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.FieldCheck; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; public class FieldInspector { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index e8aa4811a..dbb276d3c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -3,11 +3,11 @@ import java.util.function.Predicate; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.*; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Context; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java index 13052541c..815370e31 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/HierarchyChecker.java @@ -7,10 +7,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.*; public class HierarchyChecker implements Checker { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java index 7dd930b6b..3ae750f99 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/MapEntryHashCodeRequirementChecker.java @@ -4,7 +4,7 @@ import java.util.Map; import java.util.Objects; -import nl.jqno.equalsverifier.internal.instantiation.ValueProvider; +import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java index bf5af10da..30cd67409 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/RecordChecker.java @@ -9,9 +9,9 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java index 0da257cc4..15ae77d89 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/SignatureChecker.java @@ -8,7 +8,7 @@ import java.util.List; import java.util.Set; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.instantiation.ClassProbe; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java index 94336388a..506c37a19 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ArrayFieldCheck.java @@ -3,8 +3,8 @@ import static nl.jqno.equalsverifier.internal.util.Assert.assertEquals; import java.lang.reflect.Array; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java index 92902567a..d766321d8 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/BigDecimalFieldCheck.java @@ -6,8 +6,8 @@ import java.math.BigDecimal; import java.math.RoundingMode; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java index 0a5b060f8..34eca081b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FieldCheck.java @@ -1,6 +1,6 @@ package nl.jqno.equalsverifier.internal.checkers.fieldchecks; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; @FunctionalInterface public interface FieldCheck { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java index 3caba6eeb..64841b5f5 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/FloatAndDoubleFieldCheck.java @@ -2,8 +2,8 @@ import static nl.jqno.equalsverifier.internal.util.Assert.assertEquals; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; public class FloatAndDoubleFieldCheck implements FieldCheck { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index 22309f121..2ea3d1d78 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -9,12 +9,15 @@ import java.util.function.Function; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; -import nl.jqno.equalsverifier.internal.instantiation.*; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java index 7f5c43d1d..c8f952a28 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java @@ -4,8 +4,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.function.Predicate; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; public class MutableStateFieldCheck implements FieldCheck { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java index de32ac5cb..0ad2fd058 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/NullPointerExceptionFieldCheck.java @@ -4,9 +4,9 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.instantiation.FieldMutator; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.FieldMutator; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.*; @SuppressFBWarnings( diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index d48126989..21b63e8a4 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -7,11 +7,14 @@ import java.util.EnumSet; import java.util.Set; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.instantiation.*; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.Formatter; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java index aaf048159..c459965c7 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SignificantFieldCheck.java @@ -7,10 +7,10 @@ import java.util.Set; import java.util.function.Predicate; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.*; public class SignificantFieldCheck implements FieldCheck { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java index 2a12cc5a0..da6cb5cc3 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java @@ -4,10 +4,10 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; -import nl.jqno.equalsverifier.internal.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; import nl.jqno.equalsverifier.internal.util.Formatter; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java index dabfaf02f..5e15749b9 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java @@ -3,8 +3,8 @@ import static nl.jqno.equalsverifier.internal.util.Assert.assertTrue; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; public class SymmetryFieldCheck implements FieldCheck { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java index d28d039fe..bc0acf689 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java @@ -3,11 +3,11 @@ import static nl.jqno.equalsverifier.internal.util.Assert.fail; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; public class TransientFieldsCheck implements FieldCheck { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java index 6b01d3970..6e20d3991 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransitivityFieldCheck.java @@ -3,8 +3,8 @@ import static nl.jqno.equalsverifier.internal.util.Assert.fail; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import nl.jqno.equalsverifier.internal.instantiation.FieldProbe; -import nl.jqno.equalsverifier.internal.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.util.Formatter; public class TransitivityFieldCheck implements FieldCheck { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassProbe.java similarity index 95% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassProbe.java index 96e5bac47..18eb2b208 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/ClassProbe.java @@ -1,10 +1,8 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection; import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; import java.lang.reflect.Modifier; -import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; -import nl.jqno.equalsverifier.internal.reflection.SealedTypesHelper; /** * Provides read-only reflective access to a class. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldMutator.java similarity index 91% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldMutator.java index af3d6ca92..9086fb305 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldMutator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldMutator.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection; import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java similarity index 98% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java index 8682e4baa..27f1c512e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection; import static nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations.*; import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordProbe.java similarity index 95% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordProbe.java index 65acbfc4d..4cbaecbf7 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/RecordProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/RecordProbe.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection; import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; @@ -8,7 +8,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; public class RecordProbe { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java similarity index 89% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java index 45e3fe480..b56f38d90 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/InstanceCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java @@ -1,12 +1,11 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection.instantiation; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; -import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.Instantiator; +import nl.jqno.equalsverifier.internal.reflection.*; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; class InstanceCreator { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ModernSubjectCreator.java similarity index 96% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ModernSubjectCreator.java index a2f84e58f..279bb025c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ModernSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ModernSubjectCreator.java @@ -1,11 +1,13 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection.instantiation; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.util.Configuration; public class ModernSubjectCreator implements SubjectCreator { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java similarity index 88% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java index 9dc239f02..d3a4e3724 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection.instantiation; import java.lang.reflect.Field; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java similarity index 74% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ValueProvider.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java index 7dcf5c9f2..c1ac95f27 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/ValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection.instantiation; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java similarity index 96% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java index bf5af4e2d..dd27dc0bd 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection.instantiation; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; @@ -6,6 +6,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; import nl.jqno.equalsverifier.internal.util.Configuration; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java similarity index 95% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageValueProvider.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java index 358b9fc5a..e903a6fa0 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/instantiation/VintageValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection.instantiation; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import nl.jqno.equalsverifier.internal.exceptions.ModuleException; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java index 2fc53461d..6bb5ed575 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java @@ -7,9 +7,9 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; -import nl.jqno.equalsverifier.internal.instantiation.RecordProbe; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.RecordProbe; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; /** diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index 4c41801ea..41fe2847e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -1,9 +1,13 @@ package nl.jqno.equalsverifier.internal.util; -import nl.jqno.equalsverifier.internal.instantiation.*; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; +import nl.jqno.equalsverifier.internal.reflection.instantiation.ModernSubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; public final class Context { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbeTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeTest.java similarity index 98% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbeTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeTest.java index 012956bc5..4c5ed75db 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/ClassProbeTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/ClassProbeTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection; import static org.junit.jupiter.api.Assertions.*; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java similarity index 99% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java index 44754bbe5..8ba1caa77 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/instantiation/FieldProbeTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.instantiation; +package nl.jqno.equalsverifier.internal.reflection; import static org.junit.jupiter.api.Assertions.*; From a4b4cf0edb1ad1d550ea512e6d99a9e339a759e8 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 10:43:50 +0200 Subject: [PATCH 43/74] Picks a different file to check in the jar verifier --- .../equalsverifier/verify_release/jar/helper/JarAsserter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/equalsverifier-release-verify/src/test/java/nl/jqno/equalsverifier/verify_release/jar/helper/JarAsserter.java b/equalsverifier-release-verify/src/test/java/nl/jqno/equalsverifier/verify_release/jar/helper/JarAsserter.java index 47554af74..2da2a26f3 100644 --- a/equalsverifier-release-verify/src/test/java/nl/jqno/equalsverifier/verify_release/jar/helper/JarAsserter.java +++ b/equalsverifier-release-verify/src/test/java/nl/jqno/equalsverifier/verify_release/jar/helper/JarAsserter.java @@ -24,7 +24,7 @@ public void assertPresenceOfCoreClasses() { assertPresenceOf( EV + "/EqualsVerifier.class", EV + "/internal/reflection/vintage/ClassAccessor.class", - EV + "/internal/prefabvalues/PrefabValues.class" + EV + "/internal/checkers/HierarchyChecker.class" ); } From 6efc37fdf595c6d931485d7f579cad84116023f8 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 10:44:58 +0200 Subject: [PATCH 44/74] Moves PrefabValues class to vintage package --- .../RecordObjectAccessorModificationTest.java | 1 - .../vintage/RecordObjectAccessorTest.java | 1 - .../internal/prefabvalues/Cache.java | 3 +- .../internal/prefabvalues/FactoryCache.java | 1 + .../prefabvalues/JavaApiPrefabValues.java | 1 + .../factories/AbstractGenericFactory.java | 2 +- .../prefabvalues/factories/CopyFactory.java | 2 +- .../factories/EnumMapFactory.java | 2 +- .../factories/EnumSetFactory.java | 2 +- .../factories/ExternalFactory.java | 2 +- .../factories/FallbackFactory.java | 2 +- .../prefabvalues/factories/MapFactory.java | 2 +- .../factories/PrefabValueFactory.java | 2 +- .../prefabvalues/factories/SimpleFactory.java | 2 +- .../factories/SimpleGenericFactory.java | 2 +- .../GuavaFactoryProvider.java | 2 +- .../JavaFxFactoryProvider.java | 2 +- .../instantiation/VintageSubjectCreator.java | 2 +- .../instantiation/VintageValueProvider.java | 2 +- .../reflection/vintage/ClassAccessor.java | 1 - .../reflection/vintage/FieldModifier.java | 1 - .../vintage/InPlaceObjectAccessor.java | 1 - .../reflection/vintage/ObjectAccessor.java | 1 - .../vintage}/PrefabValues.java | 6 +++- .../vintage/RecordObjectAccessor.java | 1 - .../equalsverifier/internal/util/Context.java | 2 +- .../architecture/ArchitectureTest.java | 2 +- .../factories/AbstractGenericFactoryTest.java | 2 +- .../factories/FallbackFactoryTest.java | 2 +- .../factories/MapFactoryTest.java | 2 +- .../factories/SimpleGenericFactoryTest.java | 2 +- .../JavaFxFactoryProviderTest.java | 2 +- .../reflection/vintage/FieldModifierTest.java | 1 - ...InPlaceObjectAccessorModificationTest.java | 1 - .../vintage}/PrefabValuesCreatorTest.java | 4 ++- .../vintage}/PrefabValuesTest.java | 28 +++++++------------ .../types/ThrowingInitializer.java | 15 ++++++++++ 37 files changed, 58 insertions(+), 51 deletions(-) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection/vintage}/PrefabValues.java (96%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection/vintage}/PrefabValuesCreatorTest.java (96%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection/vintage}/PrefabValuesTest.java (93%) create mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/ThrowingInitializer.java diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java index 6f66b40c4..33a02039c 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java @@ -7,7 +7,6 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java index a43b024cb..9774608c7 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java @@ -10,7 +10,6 @@ import java.util.Objects; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Cache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Cache.java index 8a48145c8..582d02032 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Cache.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Cache.java @@ -2,9 +2,10 @@ import java.util.HashMap; import java.util.Map; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; /** Contains a cache of prefabricated values, for {@link PrefabValues}. */ -class Cache { +public class Cache { @SuppressWarnings("rawtypes") private final Map cache = new HashMap<>(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCache.java index 3cc2e74a5..7ba5b0b53 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCache.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCache.java @@ -4,6 +4,7 @@ import java.util.Iterator; import java.util.Map; import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; /** Contains a cache of factories, for {@link PrefabValues}. */ public class FactoryCache implements Iterable>> { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/JavaApiPrefabValues.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/JavaApiPrefabValues.java index abfe63efc..466a4eac2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/JavaApiPrefabValues.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/JavaApiPrefabValues.java @@ -33,6 +33,7 @@ import nl.jqno.equalsverifier.internal.prefabvalues.factories.ExternalFactory; import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.reflection.ConditionalInstantiator; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; /** * Creates instances of classes for use in a {@link PrefabValues} object. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactory.java index abf2c24bc..a669e8376 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactory.java @@ -7,8 +7,8 @@ import java.util.LinkedHashSet; import java.util.List; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; /** * Abstract implementation of {@link PrefabValueFactory} that provides helper functions for dealing diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java index 9190cb482..15042dfd7 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java @@ -2,9 +2,9 @@ import java.util.LinkedHashSet; import java.util.function.Function; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; public class CopyFactory extends AbstractGenericFactory { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumMapFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumMapFactory.java index 0ed28a257..f04da56f5 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumMapFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumMapFactory.java @@ -4,9 +4,9 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.function.Function; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; @SuppressWarnings({ "unchecked", "rawtypes" }) public final class EnumMapFactory extends AbstractGenericFactory { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumSetFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumSetFactory.java index 58abd7fe7..c5a00935a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumSetFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumSetFactory.java @@ -4,9 +4,9 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.function.Function; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; /** * Implementation of {@link PrefabValueFactory} that instantiates EnumSets using reflection, while diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/ExternalFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/ExternalFactory.java index d09076162..671051d77 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/ExternalFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/ExternalFactory.java @@ -5,11 +5,11 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders.FactoryProvider; import nl.jqno.equalsverifier.internal.reflection.ConditionalInstantiator; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; public class ExternalFactory implements PrefabValueFactory { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java index 4e6d99e3a..ceeeab7ee 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java @@ -5,11 +5,11 @@ import java.lang.reflect.Modifier; import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.ModuleException; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; /** * Implementation of {@link PrefabValueFactory} that instantiates types "by force". diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactory.java index d402e4d71..a7fae5007 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactory.java @@ -3,9 +3,9 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.function.Supplier; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; /** * Implementation of {@link PrefabValueFactory} that specializes in creating implementations of diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/PrefabValueFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/PrefabValueFactory.java index 2ee983e1e..7da083fba 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/PrefabValueFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/PrefabValueFactory.java @@ -1,9 +1,9 @@ package nl.jqno.equalsverifier.internal.prefabvalues.factories; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; /** * Creates instances of generic types for use as prefab value. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactory.java index b764cf67d..76f3241ab 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactory.java @@ -1,9 +1,9 @@ package nl.jqno.equalsverifier.internal.prefabvalues.factories; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; /** * Implementation of {@link PrefabValueFactory} that holds on to two instances that have already diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactory.java index baf0223b4..63dc2e761 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactory.java @@ -5,9 +5,9 @@ import java.util.List; import java.util.function.Supplier; import nl.jqno.equalsverifier.Func; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; public class SimpleGenericFactory extends AbstractGenericFactory { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/GuavaFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/GuavaFactoryProvider.java index f955aadab..dfc89fd46 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/GuavaFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/GuavaFactoryProvider.java @@ -7,13 +7,13 @@ import java.util.*; import java.util.function.Supplier; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.prefabvalues.factories.AbstractGenericFactory; import nl.jqno.equalsverifier.internal.prefabvalues.factories.EnumMapFactory; import nl.jqno.equalsverifier.internal.prefabvalues.factories.EnumSetFactory; import nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; public final class GuavaFactoryProvider implements FactoryProvider { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProvider.java index d23466674..4c0db5d2f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProvider.java @@ -9,12 +9,12 @@ import java.util.Set; import java.util.function.Function; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.prefabvalues.factories.AbstractGenericFactory; import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.reflection.ConditionalInstantiator; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; public final class JavaFxFactoryProvider implements FactoryProvider { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java index dd27dc0bd..e0d70f1bb 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java @@ -3,12 +3,12 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; import java.util.function.BiFunction; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; import nl.jqno.equalsverifier.internal.util.Configuration; public class VintageSubjectCreator implements SubjectCreator { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java index e903a6fa0..ce0beb9cb 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java @@ -2,9 +2,9 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import nl.jqno.equalsverifier.internal.exceptions.ModuleException; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; public class VintageValueProvider implements ValueProvider { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java index 6f3be922e..1fcc6dbc2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java @@ -1,7 +1,6 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.Instantiator; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java index 2fe0596c2..343dc7edf 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java @@ -5,7 +5,6 @@ import java.lang.reflect.Field; import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java index 8341862a1..05f375849 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java @@ -4,7 +4,6 @@ import java.util.LinkedHashSet; import java.util.function.Function; import java.util.function.Predicate; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java index 24f0c7c08..2445b1c70 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java @@ -3,7 +3,6 @@ import java.lang.reflect.Field; import java.util.LinkedHashSet; import java.util.function.Predicate; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/PrefabValues.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java similarity index 96% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/PrefabValues.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java index dde09c903..b35f0389b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/PrefabValues.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java @@ -1,10 +1,14 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection.vintage; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.Arrays; import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.RecursionException; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; +import nl.jqno.equalsverifier.internal.prefabvalues.Cache; +import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory; import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java index 6bb5ed575..324887674 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java @@ -7,7 +7,6 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.RecordProbe; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index 41fe2847e..84c77a1c5 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -2,12 +2,12 @@ import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.instantiation.ModernSubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; public final class Context { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index 8f8843692..f79ecbf8f 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -5,11 +5,11 @@ import com.tngtech.archunit.junit.AnalyzeClasses; import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchRule; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.FieldModifier; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; @AnalyzeClasses(packages = "nl.jqno.equalsverifier") public final class ArchitectureTest { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactoryTest.java index 31c06361a..a0714fed4 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactoryTest.java @@ -6,9 +6,9 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactoryTest.java index 85731d91b..d019e34d2 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactoryTest.java @@ -9,9 +9,9 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.RecursionException; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.Node; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.NodeArray; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactoryTest.java index 2076e9082..2f868316d 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactoryTest.java @@ -6,9 +6,9 @@ import java.util.LinkedHashSet; import java.util.Map; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.OneElementEnum; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactoryTest.java index be6a1b7d9..9a79f22ba 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactoryTest.java @@ -5,9 +5,9 @@ import java.util.LinkedHashSet; import java.util.Optional; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; import nl.jqno.equalsverifier.testhelpers.types.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java index 5e8e89474..787a62105 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java @@ -6,11 +6,11 @@ import java.util.List; import java.util.Map; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders.JavaFxFactoryProvider.PropertyFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; import nl.jqno.equalsverifier.testhelpers.types.Point; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java index cc452c507..135cd67e3 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java @@ -12,7 +12,6 @@ import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.testhelpers.types.Point; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorModificationTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorModificationTest.java index bb9ab9fcc..e5a1ea5e0 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorModificationTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorModificationTest.java @@ -6,7 +6,6 @@ import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/PrefabValuesCreatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java similarity index 96% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/PrefabValuesCreatorTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java index 21c8f317b..894d4ab62 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/PrefabValuesCreatorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java @@ -1,9 +1,11 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.*; import nl.jqno.equalsverifier.internal.exceptions.RecursionException; +import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.FactoryCacheFactory; import nl.jqno.equalsverifier.testhelpers.types.Point; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/PrefabValuesTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java similarity index 93% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/PrefabValuesTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java index 1602dc32b..7c138d16d 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/PrefabValuesTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection.vintage; import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; import static nl.jqno.equalsverifier.internal.testhelpers.Util.defaultEquals; @@ -9,9 +9,13 @@ import java.util.LinkedHashSet; import java.util.List; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; +import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.types.Point; +import nl.jqno.equalsverifier.testhelpers.types.ThrowingInitializer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -225,18 +229,19 @@ public void addLazyFactoryWorks() { @Test public void addLazyFactoryIsLazy() { - TypeTag throwingLazyTag = new TypeTag(ThrowingLazy.class); + TypeTag throwingInitializerTag = new TypeTag(ThrowingInitializer.class); // Shouldn't throw, because constructing PrefabValues doesn't instantiate objects: factoryCache.put( - ThrowingLazy.class.getName(), - (t, p, ts) -> Tuple.of(ThrowingLazy.X, ThrowingLazy.Y, ThrowingLazy.X) + ThrowingInitializer.class.getName(), + (t, p, ts) -> + Tuple.of(ThrowingInitializer.X, ThrowingInitializer.Y, ThrowingInitializer.X) ); pv = new PrefabValues(factoryCache); // Should throw, because `giveRed` does instantiate objects: try { - pv.giveRed(throwingLazyTag); + pv.giveRed(throwingInitializerTag); fail("Expected an exception"); } catch (Error e) { // succeed @@ -348,17 +353,4 @@ public String toString() { return "Lazy: " + i; } } - - @SuppressWarnings("unused") - public static class ThrowingLazy { - { - // Throwing something that will immediately be thrown when the class is constructed. - if (true) { - throw new IllegalStateException("initializing"); - } - } - - public static final ThrowingLazy X = new ThrowingLazy(); - public static final ThrowingLazy Y = new ThrowingLazy(); - } } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/ThrowingInitializer.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/ThrowingInitializer.java new file mode 100644 index 000000000..87946f4e8 --- /dev/null +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/ThrowingInitializer.java @@ -0,0 +1,15 @@ +package nl.jqno.equalsverifier.testhelpers.types; + +public final class ThrowingInitializer { + { + // Throwing something that will immediately be thrown when the class is constructed. + if (true) { + throw new IllegalStateException("initializing"); + } + } + + private ThrowingInitializer() {} + + public static final ThrowingInitializer X = new ThrowingInitializer(); + public static final ThrowingInitializer Y = new ThrowingInitializer(); +} From e7fc34e04af258f47725ef42d8e7acffbdea4126 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 11:44:13 +0200 Subject: [PATCH 45/74] Restricts access to vintage reflection classes --- .../internal/testhelpers/Util.java | 4 ++-- .../internal/util/Formatter.java | 8 +++---- .../architecture/ArchitectureTest.java | 21 +++++++++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/testhelpers/Util.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/testhelpers/Util.java index fb21349fd..9b67fd1e1 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/testhelpers/Util.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/testhelpers/Util.java @@ -5,7 +5,7 @@ import java.lang.reflect.Field; import java.util.Objects; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.vintage.FieldAccessor; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; public final class Util { @@ -57,7 +57,7 @@ public static int defaultHashCode(Object x) { } private static boolean isRelevant(Field f) { - return FieldAccessor.of(f).canBeModifiedReflectively(); + return FieldProbe.of(f).canBeModifiedReflectively(); } public static void coverThePrivateConstructor(Class type) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Formatter.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Formatter.java index 7a38e2b8e..a94bf4582 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Formatter.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Formatter.java @@ -3,7 +3,7 @@ import java.lang.reflect.Field; import java.util.regex.Matcher; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; /** * Formats a string with the contents of one or more objects. @@ -83,9 +83,7 @@ private String stringify(Object obj) { private String stringifyByReflection(Object obj) { StringBuilder result = new StringBuilder(); - Class type = obj.getClass(); - ObjectAccessor accessor = ObjectAccessor.of(obj); result.append("["); String typeName = type.getSimpleName().replaceAll("\\$\\$DynamicSubclass.*", ""); @@ -98,7 +96,9 @@ private String stringifyByReflection(Object obj) { result.append(" "); result.append(fieldName); result.append("="); - Object value = accessor.getField(field); + + FieldProbe probe = FieldProbe.of(field); + Object value = probe.getValue(obj); result.append(stringify(value)); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index f79ecbf8f..19656f580 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -5,15 +5,36 @@ import com.tngtech.archunit.junit.AnalyzeClasses; import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchRule; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageSubjectCreator; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.FieldModifier; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.util.Context; +import nl.jqno.equalsverifier.internal.util.PrefabValuesApi; @AnalyzeClasses(packages = "nl.jqno.equalsverifier") public final class ArchitectureTest { + @ArchTest + public static final ArchRule ONLY_VINTAGE_INSTANTIATORS_CAN_USE_VINTAGE_REFLECTION = noClasses() + .that() + .doNotBelongToAnyOf( + VintageSubjectCreator.class, + VintageValueProvider.class, + Context.class, + PrefabValuesApi.class + ) + .and() + .resideOutsideOfPackage("nl.jqno.equalsverifier.internal.reflection.vintage..") + .and() + .resideOutsideOfPackage("nl.jqno.equalsverifier.internal.prefabvalues..") + .should() + .accessClassesThat() + .resideInAPackage("nl.jqno.equalsverifier.internal.reflection.vintage.."); + @ArchTest public static final ArchRule DONT_USE_VINTAGE_REFLECTION_DIRECTLY = noClasses() .that() From 8c5fbcbc2b52e5e82a99172b1d1fd5e59d6781ad Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 12:55:49 +0200 Subject: [PATCH 46/74] Removes FieldAccessor --- .../reflection/vintage/FieldAccessor.java | 103 ------------ .../reflection/vintage/FieldModifier.java | 7 +- .../reflection/vintage/ObjectAccessor.java | 3 +- .../architecture/ArchitectureTest.java | 4 - .../reflection/vintage/FieldAccessorTest.java | 154 ------------------ 5 files changed, 6 insertions(+), 265 deletions(-) delete mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessor.java delete mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessorTest.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessor.java deleted file mode 100644 index 6ee95b3b4..000000000 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessor.java +++ /dev/null @@ -1,103 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage; - -import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; - -/** Provides reflective access to one field of an object. */ -public final class FieldAccessor { - - private final Field field; - - /** Private constructor. Call {@link #of(Field)} to instantiate. */ - private FieldAccessor(Field field) { - this.field = field; - } - - /** - * Factory method. - * - * @param field The field to access. - * @return A {@link FieldAccessor} for {@link #field}. - */ - public static FieldAccessor of(Field field) { - return new FieldAccessor(field); - } - - /** @return The field itself. */ - @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "Can't defensively copy a Field.") - public Field getField() { - return field; - } - - /** @return The field's type. */ - public Class getFieldType() { - return field.getType(); - } - - /** @return The field's name. */ - public String getFieldName() { - return field.getName(); - } - - /** @return Whether the field is of a primitive type. */ - public boolean fieldIsPrimitive() { - return getFieldType().isPrimitive(); - } - - /** @return Whether the field is marked with the final modifier. */ - public boolean fieldIsFinal() { - return Modifier.isFinal(field.getModifiers()); - } - - /** @return Whether the field is marked with the static modifier. */ - public boolean fieldIsStatic() { - return Modifier.isStatic(field.getModifiers()); - } - - /** @return Whether the field is marked with the transient modifier. */ - public boolean fieldIsTransient() { - return Modifier.isTransient(field.getModifiers()); - } - - /** @return Whether the field is an enum with a single value. */ - public boolean fieldIsEmptyOrSingleValueEnum() { - Class type = field.getType(); - return type.isEnum() && type.getEnumConstants().length <= 1; - } - - /** - * Tries to get the field's value. - * - * @param object The object that contains the field whose value we want to get. - * @return The field's value. - * @throws ReflectionException If the operation fails. - */ - @SuppressFBWarnings( - value = "DP_DO_INSIDE_DO_PRIVILEGED", - justification = "Only called in test code, not production." - ) - public Object get(Object object) { - field.setAccessible(true); - return rethrow(() -> field.get(object)); - } - - /** - * Determines whether the field can be modified using reflection. - * - * @return Whether or not the field can be modified reflectively. - */ - public boolean canBeModifiedReflectively() { - if (field.isSynthetic()) { - return false; - } - int modifiers = field.getModifiers(); - if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) { - return false; - } - return true; - } -} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java index 343dc7edf..d2c632732 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java @@ -6,6 +6,7 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; public final class FieldModifier { @@ -122,11 +123,11 @@ public void changeField( } private void change(FieldChanger changer, boolean includeStatic) { - FieldAccessor accessor = FieldAccessor.of(field); - if (!accessor.canBeModifiedReflectively()) { + FieldProbe probe = FieldProbe.of(field); + if (!probe.canBeModifiedReflectively()) { return; } - if (!includeStatic && accessor.fieldIsStatic()) { + if (!includeStatic && probe.isStatic()) { return; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java index 2445b1c70..aafe272e5 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java @@ -4,6 +4,7 @@ import java.util.LinkedHashSet; import java.util.function.Predicate; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; /** @@ -77,7 +78,7 @@ public Class type() { */ @SuppressWarnings("unchecked") public T getField(Field field) { - return (T) FieldAccessor.of(field).get(object); + return (T) FieldProbe.of(field).getValue(object); } /** diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index 19656f580..c4f12e785 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -8,7 +8,6 @@ import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageSubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.vintage.FieldAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.FieldModifier; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; @@ -47,9 +46,6 @@ public final class ArchitectureTest { .areAssignableTo(ObjectAccessor.class) .orShould() .accessClassesThat() - .areAssignableTo(FieldAccessor.class) - .orShould() - .accessClassesThat() .areAssignableTo(FieldModifier.class) .orShould() .accessClassesThat() diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessorTest.java deleted file mode 100644 index e3157c23c..000000000 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldAccessorTest.java +++ /dev/null @@ -1,154 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage; - -import static org.junit.jupiter.api.Assertions.*; - -import java.lang.reflect.Field; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.*; -import org.junit.jupiter.api.Test; - -public class FieldAccessorTest { - - private static final String FIELD_NAME = "field"; - - @Test - public void getField() throws NoSuchFieldException { - ObjectContainer foo = new ObjectContainer(); - Field field = foo.getClass().getDeclaredField(FIELD_NAME); - FieldAccessor fieldAccessor = FieldAccessor.of(field); - assertSame(field, fieldAccessor.getField()); - } - - @Test - public void getFieldType() { - ObjectContainer foo = new ObjectContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertEquals(Object.class, fieldAccessor.getFieldType()); - } - - @Test - public void getFieldName() { - ObjectContainer foo = new ObjectContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertEquals(FIELD_NAME, fieldAccessor.getFieldName()); - } - - @Test - public void isNotPrimitive() { - ObjectContainer foo = new ObjectContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertFalse(fieldAccessor.fieldIsPrimitive()); - } - - @Test - public void isPrimitive() { - PrimitiveContainer foo = new PrimitiveContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertTrue(fieldAccessor.fieldIsPrimitive()); - } - - @Test - public void isNotFinal() { - ObjectContainer foo = new ObjectContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertFalse(fieldAccessor.fieldIsFinal()); - } - - @Test - public void isFinal() { - FinalContainer foo = new FinalContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertTrue(fieldAccessor.fieldIsFinal()); - } - - @Test - public void isNotStatic() { - ObjectContainer foo = new ObjectContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertFalse(fieldAccessor.fieldIsStatic()); - } - - @Test - public void isStatic() { - StaticContainer foo = new StaticContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertTrue(fieldAccessor.fieldIsStatic()); - } - - @Test - public void isNotTransient() { - ObjectContainer foo = new ObjectContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertFalse(fieldAccessor.fieldIsTransient()); - } - - @Test - public void isTransient() { - TransientContainer foo = new TransientContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertTrue(fieldAccessor.fieldIsTransient()); - } - - @Test - public void isNotEnum() { - PrimitiveContainer foo = new PrimitiveContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME); - assertFalse(fieldAccessor.fieldIsEmptyOrSingleValueEnum()); - } - - @Test - public void isEnumButNotSingleValue() { - EnumContainer foo = new EnumContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, "twoElementEnum"); - assertFalse(fieldAccessor.fieldIsEmptyOrSingleValueEnum()); - } - - @Test - public void isSingleValueEnum() { - EnumContainer foo = new EnumContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, "oneElementEnum"); - assertTrue(fieldAccessor.fieldIsEmptyOrSingleValueEnum()); - } - - @Test - public void isEmptyEnum() { - EnumContainer foo = new EnumContainer(); - FieldAccessor fieldAccessor = getAccessorFor(foo, "emptyEnum"); - assertTrue(fieldAccessor.fieldIsEmptyOrSingleValueEnum()); - } - - @Test - public void getValuePrimitive() { - PrimitiveContainer foo = new PrimitiveContainer(); - foo.field = 10; - Object value = getValue(foo, "field"); - assertEquals(10, value); - } - - @Test - public void getValueObject() { - Object object = new Object(); - ObjectContainer foo = new ObjectContainer(); - foo.field = object; - Object value = getValue(foo, FIELD_NAME); - assertEquals(object, value); - } - - @Test - public void getPrivateValue() { - PrivateObjectContainer foo = new PrivateObjectContainer(); - getValue(foo, FIELD_NAME); - } - - private Object getValue(Object object, String fieldName) { - return getAccessorFor(object, fieldName).get(object); - } - - private FieldAccessor getAccessorFor(Object object, String fieldName) { - try { - Field field = object.getClass().getDeclaredField(fieldName); - return FieldAccessor.of(field); - } catch (NoSuchFieldException e) { - throw new IllegalArgumentException("fieldName: " + fieldName); - } - } -} From 1c7847abd74b7933790fd985e4b17b5d34b2d003 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 13:30:35 +0200 Subject: [PATCH 47/74] Removes unused code --- .../RecordObjectAccessorCopyingTest.java | 28 +- .../RecordObjectAccessorModificationTest.java | 125 ------- .../RecordObjectAccessorScramblingTest.java | 107 +----- .../vintage/RecordObjectAccessorTest.java | 9 - .../instantiation/ModernSubjectCreator.java | 178 ---------- .../instantiation/SubjectCreator.java | 170 +++++++++- .../instantiation/VintageSubjectCreator.java | 115 ------- .../reflection/vintage/ClassAccessor.java | 58 +--- .../reflection/vintage/FieldModifier.java | 54 --- .../vintage/InPlaceObjectAccessor.java | 84 +---- .../reflection/vintage/ObjectAccessor.java | 137 -------- .../reflection/vintage/PrefabValues.java | 13 - .../vintage/RecordObjectAccessor.java | 74 +--- .../equalsverifier/internal/util/Context.java | 3 +- .../architecture/ArchitectureTest.java | 8 +- .../reflection/vintage/ClassAccessorTest.java | 41 ++- .../reflection/vintage/FieldModifierTest.java | 318 ------------------ .../InPlaceObjectAccessorCopyingTest.java | 54 +-- ...InPlaceObjectAccessorModificationTest.java | 123 ------- .../InPlaceObjectAccessorScramblingTest.java | 12 - .../vintage/InPlaceObjectAccessorTest.java | 10 - .../reflection/vintage/PrefabValuesTest.java | 88 +---- 22 files changed, 215 insertions(+), 1594 deletions(-) delete mode 100644 equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java delete mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ModernSubjectCreator.java delete mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java delete mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorModificationTest.java diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java index 6098c8dac..bec1a8f20 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java @@ -1,12 +1,12 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; -import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.Test; public class RecordObjectAccessorCopyingTest { @@ -24,8 +24,8 @@ public void copyHappyPath() { public void shallowCopy() { Object original = instantiate(RecordContainer.class); Object copy = copyOf(original); - ObjectAccessor originalAccessor = create(original); - ObjectAccessor copyAccessor = create(copy); + RecordObjectAccessor originalAccessor = create(original); + RecordObjectAccessor copyAccessor = create(copy); assertNotSame(original, copy); for (Field f : FieldIterable.of(original.getClass())) { @@ -35,24 +35,6 @@ public void shallowCopy() { } } - @Test - public void copyIntoSubclass() { - Object object = instantiate(SimpleRecord.class); - ExpectedException - .when(() -> create(object).copyIntoSubclass(null)) - .assertThrows(EqualsVerifierInternalBugException.class) - .assertMessageContains("Can't copy a record into a subclass of itself."); - } - - @Test - public void copyIntoAnonymousSubclass() { - Object object = instantiate(SimpleRecord.class); - ExpectedException - .when(() -> create(object).copyIntoAnonymousSubclass()) - .assertThrows(EqualsVerifierInternalBugException.class) - .assertMessageContains("Can't copy a record into an anonymous subclass of itself."); - } - @SuppressWarnings("unchecked") private RecordObjectAccessor create(T object) { return new RecordObjectAccessor(object, (Class) object.getClass()); diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java deleted file mode 100644 index 33a02039c..000000000 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorModificationTest.java +++ /dev/null @@ -1,125 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotSame; -import static org.junit.jupiter.api.Assertions.assertNull; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class RecordObjectAccessorModificationTest { - - private static final int INITIAL_INT = 42; - private static final boolean INITIAL_BOOLEAN = true; - private static final String INITIAL_STRING = "hello"; - private static final Object INITIAL_OBJECT = new Object(); - - private PrefabValues prefabValues; - private Class modifiable; - private Object m; - private ObjectAccessor accessor; - private Field stringField; - private ObjectAccessor modified; - - @BeforeEach - public void setUp() throws Exception { - prefabValues = new PrefabValues(JavaApiPrefabValues.build()); - - modifiable = ModifiableRecord.class; - Constructor c = modifiable.getDeclaredConstructor( - int.class, - boolean.class, - String.class, - Object.class - ); - m = c.newInstance(INITIAL_INT, INITIAL_BOOLEAN, INITIAL_STRING, INITIAL_OBJECT); - accessor = create(m); - stringField = modifiable.getDeclaredField("s"); - } - - @Test - public void clearClears() throws Exception { - modified = accessor.clear(f -> true, prefabValues, TypeTag.NULL); - assertEquals(0, fieldValue(modified, "i")); - assertEquals(false, fieldValue(modified, "b")); - assertNull(fieldValue(modified, "s")); - assertNull(fieldValue(modified, "o")); - } - - @Test - public void clearClearsExcept() throws Exception { - modified = accessor.clear(f -> !f.getName().equals("s"), prefabValues, TypeTag.NULL); - assertEquals(prefabValues.giveRed(new TypeTag(String.class)), fieldValue(modified, "s")); - assertEquals(0, fieldValue(modified, "i")); - assertEquals(false, fieldValue(modified, "b")); - assertNull(fieldValue(modified, "o")); - } - - @Test - public void clearLeavesOriginalUnaffected() { - modified = accessor.clear(f -> true, prefabValues, TypeTag.NULL); - assertNotSame(m, modified.get()); - } - - @Test - public void withDefaultedField() throws Exception { - modified = accessor.withDefaultedField(stringField); - assertNull(fieldValue(modified, "s")); - assertEquals(INITIAL_INT, fieldValue(modified, "i")); - assertEquals(INITIAL_BOOLEAN, fieldValue(modified, "b")); - assertEquals(INITIAL_OBJECT, fieldValue(modified, "o")); - } - - @Test - public void withDefaultedFieldLeavesOriginalUnaffected() { - modified = accessor.withDefaultedField(stringField); - assertNotSame(m, modified.get()); - } - - @Test - public void withChangedField() throws Exception { - modified = accessor.withChangedField(stringField, prefabValues, TypeTag.NULL); - assertEquals(prefabValues.giveRed(new TypeTag(String.class)), fieldValue(modified, "s")); - assertEquals(INITIAL_INT, fieldValue(modified, "i")); - assertEquals(INITIAL_BOOLEAN, fieldValue(modified, "b")); - assertEquals(INITIAL_OBJECT, fieldValue(modified, "o")); - } - - @Test - public void withChangedFieldLeavesOriginalUnaffected() { - modified = accessor.withChangedField(stringField, prefabValues, TypeTag.NULL); - assertNotSame(m, modified.get()); - } - - @Test - public void withFieldSetTo() throws Exception { - modified = accessor.withFieldSetTo(stringField, "something else"); - assertEquals("something else", fieldValue(modified, "s")); - assertEquals(INITIAL_INT, fieldValue(modified, "i")); - assertEquals(INITIAL_BOOLEAN, fieldValue(modified, "b")); - assertEquals(INITIAL_OBJECT, fieldValue(modified, "o")); - } - - @Test - public void withFieldSetToLeavesOriginalUnaffected() { - modified = accessor.withFieldSetTo(stringField, "something else"); - assertNotSame(m, modified.get()); - } - - @SuppressWarnings("unchecked") - private RecordObjectAccessor create(T object) { - return new RecordObjectAccessor(object, (Class) object.getClass()); - } - - private Object fieldValue(ObjectAccessor objectAccessor, String fieldName) - throws NoSuchFieldException { - Field field = objectAccessor.get().getClass().getDeclaredField(fieldName); - return objectAccessor.getField(field); - } - - record ModifiableRecord(int i, boolean b, String s, Object o) {} -} diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java index 2caee1792..3f7bad283 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java @@ -1,17 +1,14 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotSame; import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.ArrayList; import java.util.LinkedHashSet; -import java.util.List; -import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; -import nl.jqno.equalsverifier.internal.prefabvalues.*; -import nl.jqno.equalsverifier.internal.reflection.Instantiator; -import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; +import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -52,86 +49,11 @@ public void scramble() throws Exception { assertFalse(original.equals(scrambled)); } - @Test - public void scrambleAllFields() throws Exception { - Constructor constructor = - TypeContainerRecord.class.getDeclaredConstructor( - int.class, - boolean.class, - String.class, - Object.class - ); - Object someObject = new Object(); - Object original = constructor.newInstance(42, true, "hello", someObject); - - ObjectAccessor scrambled = doScramble(original); - - assertNotEquals(42, fieldValue(scrambled, "i")); - assertNotEquals(true, fieldValue(scrambled, "b")); - assertNotEquals("hello", fieldValue(scrambled, "s")); - assertNotEquals(someObject, fieldValue(scrambled, "o")); - } - - @Test - public void shallowScramble() throws Exception { - Constructor constructor = Point.class.getDeclaredConstructor(int.class, int.class); - Object original = constructor.newInstance(1, 2); - - ExpectedException - .when(() -> create(original).shallowScramble(prefabValues, TypeTag.NULL)) - .assertThrows(EqualsVerifierInternalBugException.class) - .assertMessageContains("Record:", "can't shallow-scramble a record."); - } - - @Test - public void dontScrambleStaticFinal() throws NoSuchFieldException { - Object instance = Instantiator.of(StaticFieldContainer.class).instantiate(); - - ObjectAccessor scrambled = doScramble(instance); - - Object scrambledStaticFinal = fieldValue(scrambled, "STATIC_FINAL"); - Object scrambledStaticNonfinal = fieldValue(scrambled, "staticNonfinal"); - assertEquals(ORIGINAL_VALUE, scrambledStaticFinal); - assertEquals(ORIGINAL_VALUE, scrambledStaticNonfinal); - } - - @Test - public void scrambleNestedGenerics() throws Exception { - Constructor constructor = - GenericContainerContainer.class.getDeclaredConstructor( - GenericContainer.class, - GenericContainer.class - ); - Object instance = constructor.newInstance( - new GenericContainer(new ArrayList()), - new GenericContainer(new ArrayList()) - ); - ObjectAccessor accessor = create(instance); - - assertTrue(GenericContainer.cast(fieldValue(accessor, "strings")).ts.isEmpty()); - assertTrue(GenericContainer.cast(fieldValue(accessor, "points")).ts.isEmpty()); - - ObjectAccessor scrambled = doScramble(instance); - - List strings = GenericContainer.cast(fieldValue(scrambled, "strings")).ts; - assertFalse(strings.isEmpty()); - assertEquals(String.class, strings.get(0).getClass()); - List points = GenericContainer.cast(fieldValue(scrambled, "points")).ts; - assertFalse(points.isEmpty()); - assertEquals(Point.class, points.get(0).getClass()); - } - @SuppressWarnings("unchecked") private RecordObjectAccessor create(T object) { return new RecordObjectAccessor(object, (Class) object.getClass()); } - private Object fieldValue(ObjectAccessor accessor, String fieldName) - throws NoSuchFieldException { - Field field = accessor.get().getClass().getDeclaredField(fieldName); - return accessor.getField(field); - } - private ObjectAccessor doScramble(Object object) { return create(object).scramble(prefabValues, TypeTag.NULL, EMPTY_TYPE_STACK); } @@ -146,23 +68,4 @@ record StaticFieldContainer(int nonstatic) { public static final String STATIC_FINAL = ORIGINAL_VALUE; public static String staticNonfinal = ORIGINAL_VALUE; } - - public static final class GenericContainer { - - private List ts; - - public GenericContainer(List ts) { - this.ts = ts; - } - - @SuppressWarnings("unchecked") - public static GenericContainer cast(Object object) { - return (GenericContainer) object; - } - } - - record GenericContainerContainer( - GenericContainer strings, - GenericContainer points - ) {} } diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java index 9774608c7..ca30c3f4f 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java @@ -1,11 +1,9 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.reflect.Constructor; -import java.lang.reflect.Field; import java.util.LinkedHashSet; import java.util.Objects; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; @@ -41,13 +39,6 @@ public void get() { assertSame(recordInstance, accessor.get()); } - @Test - public void getField() throws Exception { - Field f = SimpleRecord.class.getDeclaredField("i"); - RecordObjectAccessor accessor = accessorFor(recordInstance); - assertEquals(42, accessor.getField(f)); - } - @Test public void fail_whenConstructorThrowsNpe() { Object instance = Instantiator.of(NpeThrowingConstructorRecord.class).instantiate(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ModernSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ModernSubjectCreator.java deleted file mode 100644 index 279bb025c..000000000 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ModernSubjectCreator.java +++ /dev/null @@ -1,178 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.instantiation; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.ClassProbe; -import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.FieldProbe; -import nl.jqno.equalsverifier.internal.util.Configuration; - -public class ModernSubjectCreator implements SubjectCreator { - - private final TypeTag typeTag; - private final Class type; - private final Configuration config; - private final ValueProvider valueProvider; - private final ClassProbe classProbe; - - public ModernSubjectCreator( - TypeTag typeTag, - Configuration config, - ValueProvider valueProvider - ) { - this.typeTag = typeTag; - this.type = typeTag.getType(); - this.config = config; - this.valueProvider = valueProvider; - this.classProbe = new ClassProbe<>(type); - } - - @Override - public T plain() { - return createInstance(empty()); - } - - @Override - public T withFieldDefaulted(Field field) { - return createInstance(with(field, null)); - } - - @Override - public T withAllFieldsDefaulted() { - Map values = empty(); - for (Field f : fields()) { - values.put(f, null); - } - return createInstance(values); - } - - @Override - public T withAllFieldsDefaultedExcept(Field field) { - Map values = empty(); - for (Field f : fields()) { - if (!f.equals(field)) { - values.put(f, null); - } - } - return createInstance(values); - } - - @Override - public T withFieldSetTo(Field field, Object value) { - return createInstance(with(field, value)); - } - - @Override - public T withFieldChanged(Field field) { - if (FieldProbe.of(field).isStatic()) { - return plain(); - } - Object value = valuesFor(field).getBlue(); - return createInstance(with(field, value)); - } - - @Override - public T withAllFieldsChanged() { - Map values = empty(); - for (Field f : fields()) { - Object value = valuesFor(f).getBlue(); - values.put(f, value); - } - return createInstance(values); - } - - @Override - public T withAllFieldsShallowlyChanged() { - Map values = empty(); - for (Field f : nonSuperFields()) { - Object value = valuesFor(f).getBlue(); - values.put(f, value); - } - return createInstance(values); - } - - @Override - public T copy(T original) { - Map values = empty(); - for (Field f : fields()) { - Object value = FieldProbe.of(f).getValue(original); - values.put(f, value); - } - return createInstance(values); - } - - @Override - public Object copyIntoSuperclass(T original) { - Map values = empty(); - for (Field f : superFields()) { - Object value = FieldProbe.of(f).getValue(original); - values.put(f, value); - } - - InstanceCreator superCreator = new InstanceCreator<>( - new ClassProbe<>(type.getSuperclass()) - ); - return superCreator.instantiate(values); - } - - @Override - public S copyIntoSubclass(T original, Class subType) { - Map values = empty(); - for (Field f : fields()) { - Object value = FieldProbe.of(f).getValue(original); - values.put(f, value); - } - - InstanceCreator subCreator = new InstanceCreator<>(new ClassProbe<>(subType)); - return subCreator.instantiate(values); - } - - private T createInstance(Map givens) { - Map values = determineValues(givens); - InstanceCreator instaceCreator = new InstanceCreator<>(classProbe); - return instaceCreator.instantiate(values); - } - - private Map determineValues(Map givens) { - Map values = new HashMap<>(givens); - for (Field f : fields()) { - boolean fieldIsAbsent = !values.containsKey(f); - boolean fieldCannotBeNull = - values.get(f) == null && !FieldProbe.of(f).canBeDefault(config); - if (fieldIsAbsent || fieldCannotBeNull) { - Object value = valuesFor(f).getRed(); - values.put(f, value); - } - } - return values; - } - - private Map empty() { - return new HashMap<>(); - } - - private Map with(Field f, Object v) { - Map result = empty(); - result.put(f, v); - return result; - } - - private FieldIterable fields() { - return FieldIterable.ofIgnoringStatic(type); - } - - private FieldIterable superFields() { - return FieldIterable.ofIgnoringStatic(type.getSuperclass()); - } - - private FieldIterable nonSuperFields() { - return FieldIterable.ofIgnoringSuperAndStatic(type); - } - - private Tuple valuesFor(Field f) { - return valueProvider.provide(TypeTag.of(f, typeTag)); - } -} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java index d3a4e3724..d318f367e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java @@ -1,17 +1,163 @@ package nl.jqno.equalsverifier.internal.reflection.instantiation; import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; +import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; +import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.util.Configuration; -public interface SubjectCreator { - T plain(); - T withFieldDefaulted(Field field); - T withAllFieldsDefaulted(); - T withAllFieldsDefaultedExcept(Field field); - T withFieldSetTo(Field field, Object value); - T withFieldChanged(Field field); - T withAllFieldsChanged(); - T withAllFieldsShallowlyChanged(); - T copy(T original); - Object copyIntoSuperclass(T original); - S copyIntoSubclass(T original, Class subType); +public class SubjectCreator { + + private final TypeTag typeTag; + private final Class type; + private final Configuration config; + private final ValueProvider valueProvider; + private final ClassProbe classProbe; + + public SubjectCreator(TypeTag typeTag, Configuration config, ValueProvider valueProvider) { + this.typeTag = typeTag; + this.type = typeTag.getType(); + this.config = config; + this.valueProvider = valueProvider; + this.classProbe = new ClassProbe<>(type); + } + + public T plain() { + return createInstance(empty()); + } + + public T withFieldDefaulted(Field field) { + return createInstance(with(field, null)); + } + + public T withAllFieldsDefaulted() { + Map values = empty(); + for (Field f : fields()) { + values.put(f, null); + } + return createInstance(values); + } + + public T withAllFieldsDefaultedExcept(Field field) { + Map values = empty(); + for (Field f : fields()) { + if (!f.equals(field)) { + values.put(f, null); + } + } + return createInstance(values); + } + + public T withFieldSetTo(Field field, Object value) { + return createInstance(with(field, value)); + } + + public T withFieldChanged(Field field) { + if (FieldProbe.of(field).isStatic()) { + return plain(); + } + Object value = valuesFor(field).getBlue(); + return createInstance(with(field, value)); + } + + public T withAllFieldsChanged() { + Map values = empty(); + for (Field f : fields()) { + Object value = valuesFor(f).getBlue(); + values.put(f, value); + } + return createInstance(values); + } + + public T withAllFieldsShallowlyChanged() { + Map values = empty(); + for (Field f : nonSuperFields()) { + Object value = valuesFor(f).getBlue(); + values.put(f, value); + } + return createInstance(values); + } + + public T copy(T original) { + Map values = empty(); + for (Field f : fields()) { + Object value = FieldProbe.of(f).getValue(original); + values.put(f, value); + } + return createInstance(values); + } + + public Object copyIntoSuperclass(T original) { + Map values = empty(); + for (Field f : superFields()) { + Object value = FieldProbe.of(f).getValue(original); + values.put(f, value); + } + + InstanceCreator superCreator = new InstanceCreator<>( + new ClassProbe<>(type.getSuperclass()) + ); + return superCreator.instantiate(values); + } + + public S copyIntoSubclass(T original, Class subType) { + Map values = empty(); + for (Field f : fields()) { + Object value = FieldProbe.of(f).getValue(original); + values.put(f, value); + } + + InstanceCreator subCreator = new InstanceCreator<>(new ClassProbe<>(subType)); + return subCreator.instantiate(values); + } + + private T createInstance(Map givens) { + Map values = determineValues(givens); + InstanceCreator instaceCreator = new InstanceCreator<>(classProbe); + return instaceCreator.instantiate(values); + } + + private Map determineValues(Map givens) { + Map values = new HashMap<>(givens); + for (Field f : fields()) { + boolean fieldIsAbsent = !values.containsKey(f); + boolean fieldCannotBeNull = + values.get(f) == null && !FieldProbe.of(f).canBeDefault(config); + if (fieldIsAbsent || fieldCannotBeNull) { + Object value = valuesFor(f).getRed(); + values.put(f, value); + } + } + return values; + } + + private Map empty() { + return new HashMap<>(); + } + + private Map with(Field f, Object v) { + Map result = empty(); + result.put(f, v); + return result; + } + + private FieldIterable fields() { + return FieldIterable.ofIgnoringStatic(type); + } + + private FieldIterable superFields() { + return FieldIterable.ofIgnoringStatic(type.getSuperclass()); + } + + private FieldIterable nonSuperFields() { + return FieldIterable.ofIgnoringSuperAndStatic(type); + } + + private Tuple valuesFor(Field f) { + return valueProvider.provide(TypeTag.of(f, typeTag)); + } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java deleted file mode 100644 index e0d70f1bb..000000000 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageSubjectCreator.java +++ /dev/null @@ -1,115 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.instantiation; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.lang.reflect.Field; -import java.util.function.BiFunction; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.FieldProbe; -import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; -import nl.jqno.equalsverifier.internal.util.Configuration; - -public class VintageSubjectCreator implements SubjectCreator { - - private final TypeTag typeTag; - private final Class type; - private final Configuration config; - private final PrefabValues prefabValues; - - @SuppressFBWarnings( - value = "EI_EXPOSE_REP2", - justification = "PrefabValues is inherently mutable." - ) - public VintageSubjectCreator( - TypeTag typeTag, - Configuration config, - PrefabValues prefabValues - ) { - this.typeTag = typeTag; - this.type = typeTag.getType(); - this.config = config; - this.prefabValues = prefabValues; - } - - @Override - public T plain() { - return createSubject().get(); - } - - @Override - public T withFieldDefaulted(Field field) { - return createSubject().withDefaultedField(field).get(); - } - - @Override - public T withAllFieldsDefaulted() { - return withAllFields((acc, f) -> - FieldProbe.of(f).canBeDefault(config) ? acc.withDefaultedField(f) : acc - ); - } - - @Override - public T withAllFieldsDefaultedExcept(Field field) { - return withAllFields((acc, f) -> f.equals(field) ? acc : acc.withDefaultedField(f)); - } - - @Override - public T withFieldSetTo(Field field, Object value) { - return createSubject().withFieldSetTo(field, value).get(); - } - - @Override - public T withFieldChanged(Field field) { - return createSubject().withChangedField(field, prefabValues, typeTag).get(); - } - - @Override - public T withAllFieldsChanged() { - return withAllFields((acc, f) -> acc.withChangedField(f, prefabValues, typeTag)); - } - - @Override - public T withAllFieldsShallowlyChanged() { - return withTheseFields( - FieldIterable.ofIgnoringSuper(type), - (acc, f) -> acc.withChangedField(f, prefabValues, typeTag) - ); - } - - @Override - public T copy(T original) { - return ObjectAccessor.of(original).copy(); - } - - @Override - public Object copyIntoSuperclass(T original) { - return ObjectAccessor.of(original, type.getSuperclass()).copy(); - } - - @Override - public S copyIntoSubclass(T original, Class subType) { - return ObjectAccessor.of(original).copyIntoSubclass(subType); - } - - private T withAllFields(BiFunction, Field, ObjectAccessor> modifier) { - return withTheseFields(FieldIterable.of(type), modifier); - } - - private T withTheseFields( - FieldIterable fields, - BiFunction, Field, ObjectAccessor> modifier - ) { - ObjectAccessor accessor = createSubject(); - for (Field f : fields) { - accessor = modifier.apply(accessor, f); - } - return accessor.get(); - } - - private ObjectAccessor createSubject() { - ClassAccessor accessor = ClassAccessor.of(type, prefabValues); - return accessor.getRedAccessor(TypeTag.NULL); - } -} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java index 1fcc6dbc2..cff82e0e9 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java @@ -36,19 +36,7 @@ public static ClassAccessor of(Class type, PrefabValues prefabValues) /** * Returns an instance of T that is not equal to the instance of T returned by {@link - * #getBlueObject(TypeTag)}. - * - * @param enclosingType Describes the type that contains this object as a field, to determine - * any generic parameters it may contain. - * @return An instance of T. - */ - public T getRedObject(TypeTag enclosingType) { - return getRedAccessor(enclosingType).get(); - } - - /** - * Returns an instance of T that is not equal to the instance of T returned by {@link - * #getBlueObject(TypeTag)}. + * #getBlueObject(TypeTag, LinkedHashSet)}. * * @param enclosingType Describes the type that contains this object as a field, to determine * any generic parameters it may contain. @@ -60,23 +48,12 @@ public T getRedObject(TypeTag enclosingType, LinkedHashSet typeStack) { } /** - * Returns an {@link ObjectAccessor} for {@link #getRedObject(TypeTag)}. - * - * @param enclosingType Describes the type that contains this object as a field, to determine - * any generic parameters it may contain. - * @return An {@link ObjectAccessor} for {@link #getRedObject(TypeTag)}. - */ - public ObjectAccessor getRedAccessor(TypeTag enclosingType) { - return getRedAccessor(enclosingType, new LinkedHashSet<>()); - } - - /** - * Returns an {@link ObjectAccessor} for {@link #getRedObject(TypeTag)}. + * Returns an {@link ObjectAccessor} for {@link #getRedObject(TypeTag, LinkedHashSet)}. * * @param enclosingType Describes the type that contains this object as a field, to determine * any generic parameters it may contain. * @param typeStack Keeps track of recursion in the type. - * @return An {@link ObjectAccessor} for {@link #getRedObject(TypeTag)}. + * @return An {@link ObjectAccessor} for {@link #getRedObject}. */ public ObjectAccessor getRedAccessor( TypeTag enclosingType, @@ -87,19 +64,7 @@ public ObjectAccessor getRedAccessor( /** * Returns an instance of T that is not equal to the instance of T returned by {@link - * #getRedObject(TypeTag)}. - * - * @param enclosingType Describes the type that contains this object as a field, to determine - * any generic parameters it may contain. - * @return An instance of T. - */ - public T getBlueObject(TypeTag enclosingType) { - return getBlueAccessor(enclosingType).get(); - } - - /** - * Returns an instance of T that is not equal to the instance of T returned by {@link - * #getRedObject(TypeTag)}. + * #getRedObject(TypeTag, LinkedHashSet)}. * * @param enclosingType Describes the type that contains this object as a field, to determine * any generic parameters it may contain. @@ -111,23 +76,12 @@ public T getBlueObject(TypeTag enclosingType, LinkedHashSet typeStack) } /** - * Returns an {@link ObjectAccessor} for {@link #getBlueObject(TypeTag)}. - * - * @param enclosingType Describes the type that contains this object as a field, to determine - * any generic parameters it may contain. - * @return An {@link ObjectAccessor} for {@link #getBlueObject(TypeTag)}. - */ - public ObjectAccessor getBlueAccessor(TypeTag enclosingType) { - return getBlueAccessor(enclosingType, new LinkedHashSet<>()); - } - - /** - * Returns an {@link ObjectAccessor} for {@link #getBlueObject(TypeTag)}. + * Returns an {@link ObjectAccessor} for {@link #getBlueObject(TypeTag, LinkedHashSet)}. * * @param enclosingType Describes the type that contains this object as a field, to determine * any generic parameters it may contain. * @param typeStack Keeps track of recursion in the type. - * @return An {@link ObjectAccessor} for {@link #getBlueObject(TypeTag)}. + * @return An {@link ObjectAccessor} for {@link #getBlueObject(TypeTag, LinkedHashSet)}. */ public ObjectAccessor getBlueAccessor( TypeTag enclosingType, diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java index d2c632732..d8cef710f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java @@ -7,7 +7,6 @@ import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; -import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; public final class FieldModifier { @@ -31,43 +30,6 @@ public static FieldModifier of(Field field, Object object) { return new FieldModifier(field, object); } - /** - * Tries to set the field to the specified value. - * - *

Includes static fields but ignores fields that can't be modified reflectively. - * - * @param value The value that the field should get. - * @throws ReflectionException If the operation fails. - */ - public void set(Object value) { - change(() -> field.set(object, value), true); - } - - /** - * Tries to make the field null. Ignores static fields and fields that can't be modified - * reflectively. - * - * @throws ReflectionException If the operation fails. - */ - public void defaultField() { - change(this::setFieldToDefault, false); - } - - /** - * Tries to make the field null. Includes static fields but ignores fields that can't be - * modified reflectively. - * - * @throws ReflectionException If the operation fails. - */ - public void defaultStaticField() { - change(this::setFieldToDefault, true); - } - - private void setFieldToDefault() throws IllegalAccessException { - Class type = field.getType(); - field.set(object, PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(type)); - } - /** * Copies field's value to the corresponding field in the specified object. * @@ -80,22 +42,6 @@ public void copyTo(Object to) { change(() -> field.set(to, field.get(object)), false); } - /** - * Changes the field's value to something else. The new value will never be null. Other than - * that, the precise value is undefined. - * - *

Ignores static fields and fields that can't be modified reflectively. - * - * @param prefabValues If the field is of a type contained within prefabValues, the new value - * will be taken from it. - * @param enclosingType A tag for the type that contains the field. Needed to determine a - * generic type, if it has one.. - * @throws ReflectionException If the operation fails. - */ - public void changeField(PrefabValues prefabValues, TypeTag enclosingType) { - changeField(prefabValues, enclosingType, new LinkedHashSet<>()); - } - /** * Changes the field's value to something else. The new value will never be null. Other than * that, the precise value is undefined. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java index 05f375849..d212add1b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java @@ -2,8 +2,6 @@ import java.lang.reflect.Field; import java.util.LinkedHashSet; -import java.util.function.Function; -import java.util.function.Predicate; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; @@ -24,24 +22,6 @@ final class InPlaceObjectAccessor extends ObjectAccessor { @Override public T copy() { T copy = Instantiator.of(type()).instantiate(); - return copyInto(copy); - } - - /** {@inheritDoc} */ - @Override - public S copyIntoSubclass(Class subclass) { - S copy = Instantiator.of(subclass).instantiate(); - return copyInto(copy); - } - - /** {@inheritDoc} */ - @Override - public T copyIntoAnonymousSubclass() { - T copy = Instantiator.of(type()).instantiateAnonymousSubclass(); - return copyInto(copy); - } - - private S copyInto(S copy) { for (Field field : FieldIterable.of(type())) { fieldModifierFor(field).copyTo(copy); } @@ -54,75 +34,13 @@ public ObjectAccessor scramble( PrefabValues prefabValues, TypeTag enclosingType, LinkedHashSet typeStack - ) { - return scrambleInternal(prefabValues, enclosingType, typeStack, FieldIterable::of); - } - - /** {@inheritDoc} */ - @Override - public ObjectAccessor shallowScramble(PrefabValues prefabValues, TypeTag enclosingType) { - return scrambleInternal( - prefabValues, - enclosingType, - new LinkedHashSet<>(), - FieldIterable::ofIgnoringSuper - ); - } - - private ObjectAccessor scrambleInternal( - PrefabValues prefabValues, - TypeTag enclosingType, - LinkedHashSet typeStack, - Function, FieldIterable> it - ) { - for (Field field : it.apply(type())) { - fieldModifierFor(field).changeField(prefabValues, enclosingType, typeStack); - } - return this; - } - - /** {@inheritDoc} */ - @Override - public ObjectAccessor clear( - Predicate canBeDefault, - PrefabValues prefabValues, - TypeTag enclosingType ) { for (Field field : FieldIterable.of(type())) { - FieldModifier modifier = fieldModifierFor(field); - modifier.defaultField(); - if (!canBeDefault.test(field)) { - modifier.changeField(prefabValues, enclosingType); - } + fieldModifierFor(field).changeField(prefabValues, enclosingType, typeStack); } return this; } - /** {@inheritDoc} */ - @Override - public ObjectAccessor withDefaultedField(Field field) { - fieldModifierFor(field).defaultField(); - return this; - } - - /** {@inheritDoc} */ - @Override - public ObjectAccessor withChangedField( - Field field, - PrefabValues prefabValues, - TypeTag enclosingType - ) { - fieldModifierFor(field).changeField(prefabValues, enclosingType); - return this; - } - - /** {@inheritDoc} */ - @Override - public ObjectAccessor withFieldSetTo(Field field, Object newValue) { - fieldModifierFor(field).set(newValue); - return this; - } - private FieldModifier fieldModifierFor(Field field) { return FieldModifier.of(field, get()); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java index aafe272e5..34438af13 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java @@ -1,10 +1,7 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import java.lang.reflect.Field; import java.util.LinkedHashSet; -import java.util.function.Predicate; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; /** @@ -70,17 +67,6 @@ public Class type() { return type; } - /** - * Returns the value of the given field. - * - * @param field The field whose value we want to get. - * @return The value of the given field. - */ - @SuppressWarnings("unchecked") - public T getField(Field field) { - return (T) FieldProbe.of(field).getValue(object); - } - /** * Creates a copy of the wrapped object. * @@ -90,28 +76,6 @@ public T getField(Field field) { */ public abstract T copy(); - /** - * Creates a copy of the wrapped object, where the copy's type is a specified subclass of the - * wrapped object's class. - * - *

Note: it does a "shallow" copy. Reference fields are not copied recursively. - * - * @param subclass A subclass of the wrapped object's class. - * @param The subclass. - * @return A shallow copy. - */ - public abstract S copyIntoSubclass(Class subclass); - - /** - * Creates a copy of the wrapped object, where the copy type is an anonymous subclass of the - * wrapped object's class. - * - *

Note: it does a "shallow" copy. Reference fields are not copied recursively. - * - * @return A shallow copy. - */ - public abstract T copyIntoAnonymousSubclass(); - /** * Modifies all fields of the wrapped object that are declared in T and in its superclasses. It * may or may not mutate the object of the current ObjectAccessor. Either way, the current @@ -136,105 +100,4 @@ public abstract ObjectAccessor scramble( TypeTag enclosingType, LinkedHashSet typeStack ); - - /** - * Modifies all fields of the wrapped object that are declared in T, but not those inherited - * from superclasses. It may or may not mutate the object of the current ObjectAccessor. Either - * way, the current ObjectAccessor and any reference to its object should be considered 'spent' - * after calling this method. The returned ObjectAccessor can safely be used. - * - *

This method is consistent: given two equal objects; after scrambling both objects, they - * remain equal to each other. - * - *

It may not be able to modify: 1. static final fields, and 2. final fields that are - * initialized to a compile-time constant in the field declaration. These fields may be left - * unmodified. - * - * @param prefabValues Prefabricated values to take values from. - * @param enclosingType Describes the type that contains this object as a field, to determine - * any generic parameters it may contain. - * @return An accessor to the scrambled object. - */ - public abstract ObjectAccessor shallowScramble( - PrefabValues prefabValues, - TypeTag enclosingType - ); - - /** - * Clears all fields of the wrapped object to their default values, but only if {@code - * canBeDefault} for the given field returns true. Otherwise, leaves the value intact. It may or - * may not mutate the object of the current ObjectAccessor. Either way, the current - * ObjectAccessor and any reference to its object should be considered 'spent' after calling - * this method. The returned ObjectAccessor can safely be used. - * - *

It may not be able to modify: 1. static final fields, and 2. final fields that are - * initialized to a compile-time constant in the field declaration. These fields may be left - * unmodified. - * - * @param canBeDefault A predicate that determines for the wrapped object's fields whether or - * not they are allowed to be 'default', i.e. 0 or null. If a field is marked with @NonNull, - * for example, it may not be default. - * @param prefabValues Prefabricated values to take values from. - * @param enclosingType Describes the type that contains this object as a field, to determine - * any generic parameters it may contain. - * @return An accessor to the cleared object. - */ - public abstract ObjectAccessor clear( - Predicate canBeDefault, - PrefabValues prefabValues, - TypeTag enclosingType - ); - - /** - * Clears the given field of the wrapped object to its default value. It may or may not mutate - * the object of the current ObjectAccessor. Either way, the current ObjectAccessor and any - * reference to its object should be considered 'spent' after calling this method. The returned - * ObjectAccessor can safely be used. - * - *

It may not be able to modify: 1. static final fields, and 2. final fields that are - * initialized to a compile-time constant in the field declaration. These fields may be left - * unmodified. - * - * @param field The field to set to its default value. - * @return An accessor to the object with the defaulted field. - */ - public abstract ObjectAccessor withDefaultedField(Field field); - - /** - * Changes the given field of the wrapped object to some unspecified, but different value. It - * may or may not mutate the object of the current ObjectAccessor. Either way, the current - * ObjectAccessor and any reference to its object should be considered 'spent' after calling - * this method. The returned ObjectAccessor can safely be used. - * - *

It may not be able to modify: 1. static final fields, and 2. final fields that are - * initialized to a compile-time constant in the field declaration. These fields may be left - * unmodified. - * - * @param field The field to set to a different value. - * @param prefabValues Prefabricated values to take values from. - * @param enclosingType Describes the type that contains this object as a field, to determine - * any generic parameters it may contain. - * @return An accessor to the object with the changed field. - */ - public abstract ObjectAccessor withChangedField( - Field field, - PrefabValues prefabValues, - TypeTag enclosingType - ); - - /** - * Changes the given field of the wrapped object to the given value. It may or may not mutate - * the object of the current ObjectAccessor. Either way, the current ObjectAccessor and any - * reference to its object should be considered 'spent' after calling this method. The returned - * ObjectAccessor can safely be used. - * - *

It may not be able to modify: 1. static final fields, and 2. final fields that are - * initialized to a compile-time constant in the field declaration. These fields may be left - * unmodified. - * - * @param field The field to set to the given value. - * @param newValue The value to set the field to. - * @return An accessor to the object with the defaulted field. - */ - public abstract ObjectAccessor withFieldSetTo(Field field, Object newValue); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java index b35f0389b..c38c3b459 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java @@ -98,19 +98,6 @@ public Tuple giveTuple(TypeTag tag, LinkedHashSet typeStack) { return cache.getTuple(tag); } - /** - * Returns a prefabricated value of the specified type, that is different from the specified - * value. - * - * @param The type of the value. - * @param tag A description of the desired type, including generic parameters. - * @param value A value that is different from the value that will be returned. - * @return A value that is different from {@code value}. - */ - public T giveOther(TypeTag tag, T value) { - return giveOther(tag, value, new LinkedHashSet<>()); - } - /** * Returns a prefabricated value of the specified type, that is different from the specified * value. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java index 324887674..0dcbb296f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java @@ -4,12 +4,10 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.function.Function; -import java.util.function.Predicate; import java.util.stream.Collectors; -import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.RecordProbe; -import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; /** * Implementation of ObjectAccessor that returns modified copies of its wrapped object, through @@ -35,22 +33,6 @@ public T copy() { return callRecordConstructor(params); } - /** {@inheritDoc} */ - @Override - public S copyIntoSubclass(Class subclass) { - throw new EqualsVerifierInternalBugException( - "Can't copy a record into a subclass of itself." - ); - } - - /** {@inheritDoc} */ - @Override - public T copyIntoAnonymousSubclass() { - throw new EqualsVerifierInternalBugException( - "Can't copy a record into an anonymous subclass of itself." - ); - } - /** {@inheritDoc} */ @Override public ObjectAccessor scramble( @@ -65,55 +47,6 @@ public ObjectAccessor scramble( }); } - /** {@inheritDoc} */ - @Override - public ObjectAccessor shallowScramble(PrefabValues prefabValues, TypeTag enclosingType) { - throw new EqualsVerifierInternalBugException("Record: can't shallow-scramble a record."); - } - - /** {@inheritDoc} */ - @Override - public ObjectAccessor clear( - Predicate canBeDefault, - PrefabValues prefabValues, - TypeTag enclosingType - ) { - return makeAccessor(f -> - canBeDefault.test(f) - ? PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(f.getType()) - : prefabValues.giveRed(TypeTag.of(f, enclosingType)) - ); - } - - /** {@inheritDoc} */ - @Override - public ObjectAccessor withDefaultedField(Field field) { - return modify(field, PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(field.getType())); - } - - /** {@inheritDoc} */ - @Override - public ObjectAccessor withChangedField( - Field field, - PrefabValues prefabValues, - TypeTag enclosingType - ) { - TypeTag tag = TypeTag.of(field, enclosingType); - Object currentValue = getField(field); - Object newValue = prefabValues.giveOther(tag, currentValue); - return modify(field, newValue); - } - - /** {@inheritDoc} */ - @Override - public ObjectAccessor withFieldSetTo(Field field, Object newValue) { - return modify(field, newValue); - } - - private ObjectAccessor modify(Field field, Object value) { - return makeAccessor(f -> f.equals(field) ? value : getField(f)); - } - private ObjectAccessor makeAccessor(Function determineValue) { List params = probe.fields().map(determineValue).collect(Collectors.toList()); T newObject = callRecordConstructor(params); @@ -124,4 +57,9 @@ private T callRecordConstructor(List params) { RecordProbe p = new RecordProbe<>(type()); return p.callRecordConstructor(params); } + + @SuppressWarnings("unchecked") + public T getField(Field field) { + return (T) FieldProbe.of(field).getValue(get()); + } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index 84c77a1c5..0d5889cf3 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -3,7 +3,6 @@ import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; -import nl.jqno.equalsverifier.internal.reflection.instantiation.ModernSubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; @@ -27,7 +26,7 @@ public Context(Configuration configuration, FactoryCache factoryCache) { this.valueProvider = new VintageValueProvider(prefabValues); this.subjectCreator = - new ModernSubjectCreator<>(configuration.getTypeTag(), configuration, valueProvider); + new SubjectCreator<>(configuration.getTypeTag(), configuration, valueProvider); } public Class getType() { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index c4f12e785..563ea37be 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -5,7 +5,6 @@ import com.tngtech.archunit.junit.AnalyzeClasses; import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchRule; -import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageSubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.FieldModifier; @@ -20,12 +19,7 @@ public final class ArchitectureTest { @ArchTest public static final ArchRule ONLY_VINTAGE_INSTANTIATORS_CAN_USE_VINTAGE_REFLECTION = noClasses() .that() - .doNotBelongToAnyOf( - VintageSubjectCreator.class, - VintageValueProvider.class, - Context.class, - PrefabValuesApi.class - ) + .doNotBelongToAnyOf(VintageValueProvider.class, Context.class, PrefabValuesApi.class) .and() .resideOutsideOfPackage("nl.jqno.equalsverifier.internal.reflection.vintage..") .and() diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java index fbac5530d..af422f735 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.prefabvalues.*; import nl.jqno.equalsverifier.testhelpers.types.PointContainer; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.TwoStepNodeA; @@ -15,12 +16,14 @@ public class ClassAccessorTest { + private LinkedHashSet empty; private FactoryCache factoryCache; private PrefabValues prefabValues; private ClassAccessor pointContainerAccessor; @BeforeEach public void setup() { + empty = new LinkedHashSet<>(); factoryCache = JavaApiPrefabValues.build(); prefabValues = new PrefabValues(factoryCache); pointContainerAccessor = ClassAccessor.of(PointContainer.class, prefabValues); @@ -28,7 +31,7 @@ public void setup() { @Test public void getRedObject() { - assertObjectHasNoNullFields(pointContainerAccessor.getRedObject(TypeTag.NULL)); + assertObjectHasNoNullFields(pointContainerAccessor.getRedObject(TypeTag.NULL, empty)); } @Test @@ -39,23 +42,25 @@ public void getRedObjectGeneric() { prefabValues ); GenericTypeVariableListContainer foo = accessor.getRedObject( - new TypeTag(GenericTypeVariableListContainer.class, new TypeTag(String.class)) + new TypeTag(GenericTypeVariableListContainer.class, new TypeTag(String.class)), + empty ); assertEquals(String.class, foo.tList.get(0).getClass()); } @Test public void getRedAccessor() { - PointContainer foo = pointContainerAccessor.getRedObject(TypeTag.NULL); + PointContainer foo = pointContainerAccessor.getRedObject(TypeTag.NULL, empty); ObjectAccessor objectAccessor = pointContainerAccessor.getRedAccessor( - TypeTag.NULL + TypeTag.NULL, + empty ); assertEquals(foo, objectAccessor.get()); } @Test public void getBlueObject() { - assertObjectHasNoNullFields(pointContainerAccessor.getBlueObject(TypeTag.NULL)); + assertObjectHasNoNullFields(pointContainerAccessor.getBlueObject(TypeTag.NULL, empty)); } @Test @@ -66,35 +71,39 @@ public void getBlueObjectGeneric() { prefabValues ); GenericTypeVariableListContainer foo = accessor.getBlueObject( - new TypeTag(GenericTypeVariableListContainer.class, new TypeTag(String.class)) + new TypeTag(GenericTypeVariableListContainer.class, new TypeTag(String.class)), + empty ); assertEquals(String.class, foo.tList.get(0).getClass()); } @Test public void getBlueAccessor() { - PointContainer foo = pointContainerAccessor.getBlueObject(TypeTag.NULL); + PointContainer foo = pointContainerAccessor.getBlueObject(TypeTag.NULL, empty); ObjectAccessor objectAccessor = pointContainerAccessor.getBlueAccessor( - TypeTag.NULL + TypeTag.NULL, + empty ); assertEquals(foo, objectAccessor.get()); } @Test public void redAndBlueNotEqual() { - PointContainer red = pointContainerAccessor.getRedObject(TypeTag.NULL); - PointContainer blue = pointContainerAccessor.getBlueObject(TypeTag.NULL); + PointContainer red = pointContainerAccessor.getRedObject(TypeTag.NULL, empty); + PointContainer blue = pointContainerAccessor.getBlueObject(TypeTag.NULL, empty); assertFalse(red.equals(blue)); } @Test public void instantiateAllTypes() { - ClassAccessor.of(AllTypesContainer.class, prefabValues).getRedObject(TypeTag.NULL); + ClassAccessor.of(AllTypesContainer.class, prefabValues).getRedObject(TypeTag.NULL, empty); } @Test public void instantiateArrayTypes() { - ClassAccessor.of(AllArrayTypesContainer.class, prefabValues).getRedObject(TypeTag.NULL); + ClassAccessor + .of(AllArrayTypesContainer.class, prefabValues) + .getRedObject(TypeTag.NULL, empty); } @Test @@ -104,17 +113,19 @@ public void instantiateRecursiveTypeUsingPrefabValue() { values(new TwoStepNodeB(), new TwoStepNodeB(), new TwoStepNodeB()) ); prefabValues = new PrefabValues(factoryCache); - ClassAccessor.of(TwoStepNodeA.class, prefabValues).getRedObject(TypeTag.NULL); + ClassAccessor.of(TwoStepNodeA.class, prefabValues).getRedObject(TypeTag.NULL, empty); } @Test public void instantiateInterfaceField() { - ClassAccessor.of(InterfaceContainer.class, prefabValues).getRedObject(TypeTag.NULL); + ClassAccessor.of(InterfaceContainer.class, prefabValues).getRedObject(TypeTag.NULL, empty); } @Test public void instantiateAbstractClassField() { - ClassAccessor.of(AbstractClassContainer.class, prefabValues).getRedObject(TypeTag.NULL); + ClassAccessor + .of(AbstractClassContainer.class, prefabValues) + .getRedObject(TypeTag.NULL, empty); } @Test diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java index 135cd67e3..e0b2562b2 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifierTest.java @@ -1,190 +1,17 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.testhelpers.types.Point; -import nl.jqno.equalsverifier.testhelpers.types.PointContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.AbstractAndInterfaceArrayContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.AbstractClassContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.AllArrayTypesContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.AllTypesContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.GenericListContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.GenericTypeVariableListContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.InterfaceContainer; import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.ObjectContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.Outer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.Outer.Inner; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.PointArrayContainer; import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.PrimitiveContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.PrivateObjectContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.StaticContainer; -import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.StaticFinalContainer; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class FieldModifierTest { - private static final Point RED_NEW_POINT = new Point(10, 20); - private static final Point BLUE_NEW_POINT = new Point(20, 10); - private static final Point REDCOPY_NEW_POINT = new Point(10, 20); private static final String FIELD_NAME = "field"; - private PrefabValues prefabValues; - - @BeforeEach - public void setup() { - FactoryCache factoryCache = JavaApiPrefabValues.build(); - factoryCache.put(Point.class, values(RED_NEW_POINT, BLUE_NEW_POINT, REDCOPY_NEW_POINT)); - prefabValues = new PrefabValues(factoryCache); - } - - @Test - public void setValuePrimitive() { - PrimitiveContainer foo = new PrimitiveContainer(); - setField(foo, FIELD_NAME, 20); - assertEquals(20, foo.field); - } - - @Test - public void setValueObject() { - Object object = new Object(); - ObjectContainer foo = new ObjectContainer(); - setField(foo, FIELD_NAME, object); - assertEquals(object, foo.field); - } - - @Test - public void defaultFieldOnObjectSetsNull() { - ObjectContainer foo = new ObjectContainer(); - foo.field = new Object(); - doNullField(foo, FIELD_NAME); - assertNull(foo.field); - } - - @Test - public void defaultFieldOnArraySetsNull() { - AllTypesContainer foo = new AllTypesContainer(); - foo._array = new int[] { 1, 2, 3 }; - doNullField(foo, "_array"); - assertNull(foo._array); - } - - @Test - public void defaultFieldOnBooleanSetsFalse() { - AllTypesContainer foo = new AllTypesContainer(); - foo._boolean = true; - doNullField(foo, "_boolean"); - assertEquals(false, foo._boolean); - } - - @Test - public void defaultFieldOnByteSetsZero() { - AllTypesContainer foo = new AllTypesContainer(); - foo._byte = 10; - doNullField(foo, "_byte"); - assertEquals(0, foo._byte); - } - - @Test - public void defaultFieldOnCharSetsZero() { - AllTypesContainer foo = new AllTypesContainer(); - foo._char = 'a'; - doNullField(foo, "_char"); - assertEquals('\u0000', foo._char); - } - - @Test - public void defaultFieldOnDoubleSetsZero() { - AllTypesContainer foo = new AllTypesContainer(); - foo._double = 1.1; - doNullField(foo, "_double"); - assertEquals(0.0, foo._double, 0.0000001); - } - - @Test - public void defaultFieldOnFloatSetsZero() { - AllTypesContainer foo = new AllTypesContainer(); - foo._float = 1.1f; - doNullField(foo, "_float"); - assertEquals(0.0f, foo._float, 0.0000001); - } - - @Test - public void defaultFieldOnIntSetsZero() { - AllTypesContainer foo = new AllTypesContainer(); - foo._int = 10; - doNullField(foo, "_int"); - assertEquals(0, foo._int); - } - - @Test - public void defaultFieldOnLongSetsZero() { - AllTypesContainer foo = new AllTypesContainer(); - foo._long = 10; - doNullField(foo, "_long"); - assertEquals(0, foo._long); - } - - @Test - public void defaultFieldOnShortSetsZero() { - AllTypesContainer foo = new AllTypesContainer(); - foo._short = 10; - doNullField(foo, "_short"); - assertEquals(0, foo._short); - } - - @SuppressWarnings("static-access") - @Test - public void defaultFieldOnPrimitiveStaticFinalIsNoOp() { - StaticFinalContainer foo = new StaticFinalContainer(); - doNullField(foo, "CONST"); - assertEquals(42, foo.CONST); - } - - @SuppressWarnings("static-access") - @Test - public void defaultFieldOnObjectStaticFinalIsNoOp() { - StaticFinalContainer foo = new StaticFinalContainer(); - Object original = foo.OBJECT; - doNullField(foo, "OBJECT"); - assertSame(original, foo.OBJECT); - } - - @Test - public void defaultFieldOnSyntheticIsNoOp() { - Outer outer = new Outer(); - Inner inner = outer.new Inner(); - String fieldName = getSyntheticFieldName(inner, "this$"); - doNullField(inner, fieldName); - assertSame(outer, inner.getOuter()); - } - - @Test - public void defaultPrivateField() { - PrivateObjectContainer foo = new PrivateObjectContainer(); - doNullField(foo, FIELD_NAME); - assertNull(foo.get()); - } - - @Test - public void defaultStaticField() { - StaticContainer foo = new StaticContainer(); - getAccessorFor(foo, "field").defaultStaticField(); - assertNull(StaticContainer.field); - } - @Test public void copyToPrimitiveField() { int value = 10; @@ -211,146 +38,10 @@ public void copyToObjectField() { assertSame(value, to.field); } - @Test - public void changeField() { - AllTypesContainer reference = new AllTypesContainer(); - AllTypesContainer changed = new AllTypesContainer(); - assertTrue(reference.equals(changed)); - - for (Field field : FieldIterable.of(AllTypesContainer.class)) { - FieldModifier.of(field, changed).changeField(prefabValues, TypeTag.NULL); - assertFalse(reference.equals(changed), "On field: " + field.getName()); - FieldModifier.of(field, reference).changeField(prefabValues, TypeTag.NULL); - assertTrue(reference.equals(changed), "On field: " + field.getName()); - } - } - - @SuppressWarnings("static-access") - @Test - public void changeFieldOnPrimitiveStaticFinalIsNoOp() { - StaticFinalContainer foo = new StaticFinalContainer(); - doChangeField(foo, "CONST"); - assertEquals(42, foo.CONST); - } - - @SuppressWarnings("static-access") - @Test - public void changeFieldStaticFinal() throws SecurityException { - StaticFinalContainer foo = new StaticFinalContainer(); - Object original = foo.OBJECT; - doChangeField(foo, "OBJECT"); - assertEquals(original, foo.OBJECT); - } - - @Test - public void changeAbstractField() { - AbstractClassContainer foo = new AbstractClassContainer(); - doChangeField(foo, FIELD_NAME); - assertNotNull(foo.field); - } - - @Test - public void changeInterfaceField() { - InterfaceContainer foo = new InterfaceContainer(); - doChangeField(foo, FIELD_NAME); - assertNotNull(foo.field); - } - - @Test - public void changeArrayField() { - AllArrayTypesContainer reference = new AllArrayTypesContainer(); - AllArrayTypesContainer changed = new AllArrayTypesContainer(); - assertTrue(reference.equals(changed)); - - for (Field field : FieldIterable.of(AllArrayTypesContainer.class)) { - FieldModifier.of(field, changed).changeField(prefabValues, TypeTag.NULL); - assertFalse(reference.equals(changed), "On field: " + field.getName()); - FieldModifier.of(field, reference).changeField(prefabValues, TypeTag.NULL); - assertTrue(reference.equals(changed), "On field: " + field.getName()); - } - } - - @Test - public void changeAbstractArrayField() { - AbstractAndInterfaceArrayContainer foo = new AbstractAndInterfaceArrayContainer(); - doChangeField(foo, "abstractClasses"); - assertNotNull(foo.abstractClasses[0]); - } - - @Test - public void changeInterfaceArrayField() { - AbstractAndInterfaceArrayContainer foo = new AbstractAndInterfaceArrayContainer(); - doChangeField(foo, "interfaces"); - assertNotNull(foo.interfaces[0]); - } - - @Test - public void changeGenericField() { - GenericListContainer foo = new GenericListContainer(); - doChangeField(foo, "stringList"); - doChangeField(foo, "integerList"); - assertNotEquals(foo.stringList, foo.integerList); - } - - @Test - public void changeTypeVariableGenericField() { - GenericTypeVariableListContainer foo = new GenericTypeVariableListContainer<>(); - doChangeField( - foo, - "tList", - new TypeTag(GenericTypeVariableListContainer.class, new TypeTag(String.class)) - ); - assertFalse(foo.tList.isEmpty()); - } - - @Test - public void addPrefabValues() { - PointContainer foo = new PointContainer(new Point(1, 2)); - - doChangeField(foo, "point"); - assertEquals(RED_NEW_POINT, foo.getPoint()); - - doChangeField(foo, "point"); - assertEquals(BLUE_NEW_POINT, foo.getPoint()); - - doChangeField(foo, "point"); - assertEquals(RED_NEW_POINT, foo.getPoint()); - } - - @Test - public void addPrefabArrayValues() { - PointArrayContainer foo = new PointArrayContainer(); - - doChangeField(foo, "points"); - assertEquals(RED_NEW_POINT, foo.points[0]); - - doChangeField(foo, "points"); - assertEquals(BLUE_NEW_POINT, foo.points[0]); - - doChangeField(foo, "points"); - assertEquals(RED_NEW_POINT, foo.points[0]); - } - - private void setField(Object object, String fieldName, Object value) { - getAccessorFor(object, fieldName).set(value); - } - - private void doNullField(Object object, String fieldName) { - getAccessorFor(object, fieldName).defaultField(); - } - private void doCopyField(Object to, Object from, String fieldName) { getAccessorFor(from, fieldName).copyTo(to); } - private void doChangeField(Object object, String fieldName) { - doChangeField(object, fieldName, TypeTag.NULL); - } - - private void doChangeField(Object object, String fieldName, TypeTag enclosingType) { - getAccessorFor(object, fieldName).changeField(prefabValues, enclosingType); - } - private FieldModifier getAccessorFor(Object object, String fieldName) { try { Field field = object.getClass().getDeclaredField(fieldName); @@ -359,13 +50,4 @@ private FieldModifier getAccessorFor(Object object, String fieldName) { throw new IllegalArgumentException("fieldName: " + fieldName); } } - - private String getSyntheticFieldName(Object object, String prefix) { - for (Field field : object.getClass().getDeclaredFields()) { - if (field.getName().startsWith(prefix)) { - return field.getName(); - } - } - throw new IllegalStateException("Cannot find internal field starting with " + prefix); - } } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java index ddd239ed7..60b6c7b1f 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java @@ -1,10 +1,11 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.reflect.Field; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.testhelpers.types.ColorPoint3D; import nl.jqno.equalsverifier.testhelpers.types.Point; import nl.jqno.equalsverifier.testhelpers.types.Point3D; import nl.jqno.equalsverifier.testhelpers.types.PointContainer; @@ -54,44 +55,6 @@ public void copyFromSub() { assertAllFieldsEqual(original, copy, Point.class); } - @Test - public void copyToSub() { - Point original = new Point(2, 3); - Point3D copy = copyIntoSubclass(original, Point3D.class); - - assertAllFieldsEqual(original, copy, Point.class); - } - - @Test - public void shallowCopyToSub() { - PointContainer original = new PointContainer(new Point(1, 2)); - SubPointContainer copy = copyIntoSubclass(original, SubPointContainer.class); - - assertNotSame(original, copy); - assertTrue(original.getPoint() == copy.getPoint()); - } - - @Test - public void inheritanceCopyToSub() { - Point3D original = new Point3D(2, 3, 4); - Point3D copy = copyIntoSubclass(original, ColorPoint3D.class); - - assertAllFieldsEqual(original, copy, Point.class); - assertAllFieldsEqual(original, copy, Point3D.class); - } - - @Test - public void copyToAnonymousSub() { - Point original = new Point(2, 3); - InPlaceObjectAccessor accessor = create(original); - Point copy = accessor.copyIntoAnonymousSubclass(); - - assertAllFieldsEqual(original, copy, Point.class); - - assertNotSame(original.getClass(), copy.getClass()); - assertTrue(original.getClass().isAssignableFrom(copy.getClass())); - } - @SuppressWarnings("unchecked") private InPlaceObjectAccessor create(T object) { return new InPlaceObjectAccessor(object, (Class) object.getClass()); @@ -105,10 +68,6 @@ private T copyOf(T from, Class type) { return new InPlaceObjectAccessor(from, type).copy(); } - private S copyIntoSubclass(T from, Class subclass) { - return create(from).copyIntoSubclass(subclass); - } - private static void assertAllFieldsEqual(T original, T copy, Class type) { assertNotSame(original, copy); for (Field field : FieldIterable.of(type)) { @@ -119,11 +78,4 @@ private static void assertAllFieldsEqual(T original, T copy, Class accessor; - private Field stringField; - - @BeforeEach - public void setUp() throws Exception { - prefabValues = new PrefabValues(JavaApiPrefabValues.build()); - m = new Modifiable(INITIAL_INT, INITIAL_BOOLEAN, INITIAL_STRING, INITIAL_OBJECT); - accessor = new InPlaceObjectAccessor<>(m, Modifiable.class); - stringField = Modifiable.class.getDeclaredField("s"); - } - - @Test - public void clearClears() { - accessor.clear(f -> true, prefabValues, TypeTag.NULL); - assertEquals(0, m.i); - assertEquals(false, m.b); - assertNull(m.s); - assertNull(m.o); - } - - @Test - public void clearClearsExcept() { - accessor.clear(f -> !f.getName().equals("s"), prefabValues, TypeTag.NULL); - assertEquals(prefabValues.giveRed(new TypeTag(String.class)), m.s); - assertEquals(0, m.i); - assertEquals(false, m.b); - assertNull(m.o); - } - - @Test - public void clearWorksInPlace() { - ObjectAccessor modified = accessor.clear(f -> true, prefabValues, TypeTag.NULL); - assertSame(m, modified.get()); - } - - @Test - public void withDefaultedField() { - accessor.withDefaultedField(stringField); - assertNull(m.s); - assertEquals(INITIAL_INT, m.i); - assertEquals(INITIAL_BOOLEAN, m.b); - assertEquals(INITIAL_OBJECT, m.o); - } - - @Test - public void withDefaultedFieldWorksInPlace() { - ObjectAccessor modified = accessor.withDefaultedField(stringField); - assertSame(m, modified.get()); - } - - @Test - public void withChangedField() { - accessor.withChangedField(stringField, prefabValues, TypeTag.NULL); - assertEquals(prefabValues.giveRed(new TypeTag(String.class)), m.s); - assertEquals(INITIAL_INT, m.i); - assertEquals(INITIAL_BOOLEAN, m.b); - assertEquals(INITIAL_OBJECT, m.o); - } - - @Test - public void withChangedFieldWorksInPlace() { - ObjectAccessor modified = accessor.withChangedField( - stringField, - prefabValues, - TypeTag.NULL - ); - assertSame(m, modified.get()); - } - - @Test - public void withFieldSetTo() { - accessor.withFieldSetTo(stringField, "something else"); - assertEquals("something else", m.s); - assertEquals(INITIAL_INT, m.i); - assertEquals(INITIAL_BOOLEAN, m.b); - assertEquals(INITIAL_OBJECT, m.o); - } - - @Test - public void withFieldSetToWorksInPlace() { - ObjectAccessor modified = accessor.withFieldSetTo( - stringField, - "something else" - ); - assertSame(m, modified.get()); - } - - static class Modifiable { - - private final int i; - private final boolean b; - private final String s; - private final Object o; - - public Modifiable(int i, boolean b, String s, Object o) { - this.i = i; - this.b = b; - this.s = s; - this.o = o; - } - } -} diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java index 93bba8b56..9207b7442 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java @@ -60,18 +60,6 @@ public void deepScramble() { assertFalse(modified.equals(reference)); } - @Test - public void shallowScramble() { - Point3D modified = new Point3D(2, 3, 4); - Point3D reference = copy(modified); - - create(modified).shallowScramble(prefabValues, TypeTag.NULL); - - assertFalse(modified.equals(reference)); - modified.z = 4; - assertTrue(modified.equals(reference)); - } - @SuppressWarnings("static-access") @Test public void scrambleStaticFinal() { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorTest.java index 1a6bd4251..85152215a 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorTest.java @@ -1,10 +1,8 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.lang.reflect.Field; import nl.jqno.equalsverifier.testhelpers.types.Point; import org.junit.jupiter.api.Test; @@ -24,14 +22,6 @@ public void get() { assertSame(foo, accessor.get()); } - @Test - public void getField() throws Exception { - Point p = new Point(1, 2); - Field f = Point.class.getDeclaredField("y"); - InPlaceObjectAccessor accessor = create(p); - assertEquals(2, accessor.getField(f)); - } - @SuppressWarnings("unchecked") private InPlaceObjectAccessor create(T object) { return new InPlaceObjectAccessor(object, (Class) object.getClass()); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java index 7c138d16d..f4fa286cf 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java @@ -3,17 +3,17 @@ import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; import static nl.jqno.equalsverifier.internal.testhelpers.Util.defaultEquals; import static nl.jqno.equalsverifier.internal.testhelpers.Util.defaultHashCode; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.fail; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; -import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; -import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.types.Point; import nl.jqno.equalsverifier.testhelpers.types.ThrowingInitializer; import org.junit.jupiter.api.BeforeEach; @@ -24,7 +24,6 @@ public class PrefabValuesTest { private static final TypeTag STRING_TAG = new TypeTag(String.class); private static final TypeTag POINT_TAG = new TypeTag(Point.class); private static final TypeTag INT_TAG = new TypeTag(int.class); - private static final TypeTag STRING_ARRAY_TAG = new TypeTag(String[].class); private FactoryCache factoryCache = new FactoryCache(); private PrefabValues pv; @@ -104,87 +103,6 @@ public void giveTuple() { assertEquals(Tuple.of(new Point(42, 42), new Point(1337, 1337), new Point(42, 42)), actual); } - @Test - public void giveOtherWhenValueIsKnown() { - Point red = pv.giveRed(POINT_TAG); - Point blue = pv.giveBlue(POINT_TAG); - assertEquals(blue, pv.giveOther(POINT_TAG, red)); - assertEquals(red, pv.giveOther(POINT_TAG, blue)); - } - - @Test - public void giveOtherWhenValueIsCloneOfKnown() { - Point red = new Point(42, 42); - Point blue = new Point(1337, 1337); - assertEquals(blue, pv.giveOther(POINT_TAG, red)); - assertEquals(red, pv.giveOther(POINT_TAG, blue)); - - // Sanity check - assertEquals(red, pv.giveRed(POINT_TAG)); - assertEquals(blue, pv.giveBlue(POINT_TAG)); - } - - @Test - public void giveOtherWhenValueIsUnknown() { - Point value = new Point(-1, -1); - Point expected = pv.giveRed(POINT_TAG); - assertEquals(expected, pv.giveOther(POINT_TAG, value)); - } - - @Test - public void giveOtherWhenValueIsPrimitive() { - int expected = pv.giveRed(INT_TAG); - assertEquals(expected, (int) pv.giveOther(INT_TAG, -10)); - } - - @Test - public void giveOtherWhenValueIsNull() { - Point expected = pv.giveRed(POINT_TAG); - assertEquals(expected, pv.giveOther(POINT_TAG, null)); - } - - @Test - public void giveOtherWhenValueIsNullAndTypeWouldThrowNpe() { - TypeTag tag = new TypeTag(NpeThrowing.class); - NpeThrowing expected = pv.giveRed(tag); - assertEquals(expected, pv.giveOther(tag, null)); - } - - @Test - public void giveOtherWhenValueIsKnownArray() { - String[] red = pv.giveRed(STRING_ARRAY_TAG); - String[] blue = pv.giveBlue(STRING_ARRAY_TAG); - assertArrayEquals(blue, pv.giveOther(STRING_ARRAY_TAG, red)); - assertArrayEquals(red, pv.giveOther(STRING_ARRAY_TAG, blue)); - } - - @Test - public void giveOtherWhenValueIsCloneOfKnownArray() { - String[] red = { "r" }; - String[] blue = { "b" }; - assertArrayEquals(blue, pv.giveOther(STRING_ARRAY_TAG, red)); - assertArrayEquals(red, pv.giveOther(STRING_ARRAY_TAG, blue)); - - // Sanity check - assertArrayEquals(red, pv.giveRed(STRING_ARRAY_TAG)); - assertArrayEquals(blue, pv.giveBlue(STRING_ARRAY_TAG)); - } - - @Test - public void giveOtherWhenValueIsUnknownArray() { - String[] value = { "hello world" }; - String[] expected = pv.giveRed(STRING_ARRAY_TAG); - assertArrayEquals(expected, pv.giveOther(STRING_ARRAY_TAG, value)); - } - - @Test - public void giveOtherWhenTagDoesntMatchValue() { - ExpectedException - .when(() -> pv.giveOther(POINT_TAG, "not a point")) - .assertThrows(ReflectionException.class) - .assertMessageContains("TypeTag does not match value."); - } - @Test public void fallbackDoesNotAffectStaticFields() { int expected = StaticContainer.staticInt; From 8b09485ccec3839ca8c130ca0be6eef3431d300e Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 14:01:11 +0200 Subject: [PATCH 48/74] Uses FieldProbe in more places --- .../internal/prefabvalues/factories/FallbackFactory.java | 6 +++--- .../equalsverifier/internal/reflection/FieldIterable.java | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java index ceeeab7ee..3f608c990 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java @@ -2,12 +2,12 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; @@ -83,8 +83,8 @@ private void traverseFields( ) { Class type = tag.getType(); for (Field field : FieldIterable.of(type)) { - int modifiers = field.getModifiers(); - boolean isStaticAndFinal = Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers); + FieldProbe probe = FieldProbe.of(field); + boolean isStaticAndFinal = probe.isStatic() && probe.isFinal(); if (!isStaticAndFinal) { try { prefabValues.realizeCacheFor(TypeTag.of(field, tag), typeStack); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldIterable.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldIterable.java index a4900cbe3..aa9ec66c6 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldIterable.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldIterable.java @@ -1,7 +1,6 @@ package nl.jqno.equalsverifier.internal.reflection; import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -101,7 +100,7 @@ private List addFieldsFor(Class c) { !"__cobertura_counters".equals(field.getName()) && !field.getName().startsWith("bitmap$init$") // Generated by Scala 2.x's -Xcheckinit flag ) { - boolean isStatic = Modifier.isStatic(field.getModifiers()); + boolean isStatic = FieldProbe.of(field).isStatic(); if (isStatic && includeStatic) { statics.add(field); } From eba0904fcbaab8879f493fa886f1b77cee9747cb Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 14:23:36 +0200 Subject: [PATCH 49/74] Moves PrefabValues classes to vintage package --- .../RecordObjectAccessorScramblingTest.java | 11 +++++----- .../vintage/RecordObjectAccessorTest.java | 8 +++++--- .../ConfiguredEqualsVerifier.java | 2 +- .../api/SingleTypeEqualsVerifierApi.java | 2 +- .../checkers/AbstractDelegationChecker.java | 4 ++-- .../internal/checkers/FieldsChecker.java | 2 +- .../fieldchecks/JpaLazyGetterFieldCheck.java | 4 ++-- .../fieldchecks/ReflexivityFieldCheck.java | 4 ++-- .../fieldchecks/StringFieldCheck.java | 2 +- .../fieldchecks/TransientFieldsCheck.java | 2 +- .../exceptions/RecursionException.java | 2 +- .../factoryproviders/FactoryProvider.java | 7 ------- .../FactoryCache.java | 6 +++--- .../JavaApiPrefabValues.java | 15 +++++++------- .../{prefabvalues => reflection}/Tuple.java | 2 +- .../{prefabvalues => reflection}/TypeTag.java | 2 +- .../instantiation/SubjectCreator.java | 4 ++-- .../instantiation/ValueProvider.java | 4 ++-- .../instantiation/VintageValueProvider.java | 6 +++--- .../reflection/vintage/ClassAccessor.java | 3 ++- .../reflection/vintage/FieldModifier.java | 3 ++- .../vintage/InPlaceObjectAccessor.java | 3 ++- .../reflection/vintage/ObjectAccessor.java | 3 ++- .../vintage/RecordObjectAccessor.java | 3 ++- .../vintage}/prefabvalues/Cache.java | 7 ++++--- .../{ => prefabvalues}/PrefabValues.java | 13 ++++++------ .../factories/AbstractGenericFactory.java | 6 +++--- .../prefabvalues/factories/CopyFactory.java | 8 ++++---- .../factories/EnumMapFactory.java | 8 ++++---- .../factories/EnumSetFactory.java | 8 ++++---- .../factories/ExternalFactory.java | 14 ++++++------- .../prefabvalues/factories/Factories.java | 2 +- .../factories/FallbackFactory.java | 8 ++++---- .../prefabvalues/factories/MapFactory.java | 8 ++++---- .../factories/PrefabValueFactory.java | 8 ++++---- .../prefabvalues/factories/SimpleFactory.java | 8 ++++---- .../factories/SimpleGenericFactory.java | 8 ++++---- .../factoryproviders/AwtFactoryProvider.java | 6 +++--- .../factoryproviders/FactoryProvider.java | 7 +++++++ .../GuavaFactoryProvider.java | 20 +++++++++---------- .../JavaFxFactoryProvider.java | 16 +++++++-------- .../JavaxFactoryProvider.java | 6 +++--- .../factoryproviders/JodaFactoryProvider.java | 6 +++--- .../factoryproviders/RmiFactoryProvider.java | 6 +++--- .../internal/util/Configuration.java | 2 +- .../equalsverifier/internal/util/Context.java | 6 +++--- .../internal/util/PrefabValuesApi.java | 8 ++++---- .../internal/util/Validations.java | 2 +- .../operational/RecursionTest.java | 2 +- .../architecture/ArchitectureTest.java | 16 ++++++++++----- .../exceptions/RecursionExceptionTest.java | 2 +- .../TupleTest.java | 2 +- .../TypeTagParameterizedTest.java | 2 +- .../TypeTagTest.java | 2 +- .../reflection/vintage/ClassAccessorTest.java | 7 +++++-- .../InPlaceObjectAccessorScramblingTest.java | 7 +++++-- .../vintage/PrefabValuesCreatorTest.java | 7 ++++--- .../reflection/vintage/PrefabValuesTest.java | 11 +++++----- .../vintage}/prefabvalues/CacheTest.java | 5 ++++- .../prefabvalues/FactoryCacheTest.java | 7 ++++--- .../factories/AbstractGenericFactoryTest.java | 9 +++++---- .../prefabvalues/factories/FactoriesTest.java | 3 ++- .../factories/FallbackFactoryTest.java | 13 ++++++------ .../factories/MapFactoryTest.java | 11 +++++----- .../factories/SimpleFactoryTest.java | 3 ++- .../factories/SimpleGenericFactoryTest.java | 12 ++++++----- .../JavaFxFactoryProviderTest.java | 15 +++++++------- .../testhelpers/FactoryCacheFactory.java | 4 ++-- 68 files changed, 234 insertions(+), 201 deletions(-) delete mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/FactoryProvider.java rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection}/FactoryCache.java (92%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection}/JavaApiPrefabValues.java (98%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection}/Tuple.java (97%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection}/TypeTag.java (99%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/Cache.java (88%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/{ => prefabvalues}/PrefabValues.java (93%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/AbstractGenericFactory.java (92%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/CopyFactory.java (77%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/EnumMapFactory.java (81%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/EnumSetFactory.java (81%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/ExternalFactory.java (67%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/Factories.java (94%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/FallbackFactory.java (94%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/MapFactory.java (85%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/PrefabValueFactory.java (71%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/SimpleFactory.java (66%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/SimpleGenericFactory.java (85%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factoryproviders/AwtFactoryProvider.java (87%) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/FactoryProvider.java rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factoryproviders/GuavaFactoryProvider.java (91%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factoryproviders/JavaFxFactoryProvider.java (87%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factoryproviders/JavaxFactoryProvider.java (72%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factoryproviders/JodaFactoryProvider.java (82%) rename equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factoryproviders/RmiFactoryProvider.java (63%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection}/TupleTest.java (94%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection}/TypeTagParameterizedTest.java (98%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{prefabvalues => reflection}/TypeTagTest.java (99%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/CacheTest.java (86%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/FactoryCacheTest.java (81%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/AbstractGenericFactoryTest.java (78%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/FactoriesTest.java (60%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/FallbackFactoryTest.java (88%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/MapFactoryTest.java (88%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/SimpleFactoryTest.java (80%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factories/SimpleGenericFactoryTest.java (86%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/{ => reflection/vintage}/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java (80%) diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java index 3f7bad283..3c3e76bad 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java @@ -1,14 +1,15 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotSame; import java.lang.reflect.Constructor; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -16,7 +17,7 @@ public class RecordObjectAccessorScramblingTest { private static final LinkedHashSet EMPTY_TYPE_STACK = new LinkedHashSet<>(); private FactoryCache factoryCache; - private PrefabValues prefabValues; + private nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues prefabValues; @BeforeEach public void setup() throws Exception { diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java index ca30c3f4f..40405652b 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java @@ -7,9 +7,10 @@ import java.util.LinkedHashSet; import java.util.Objects; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.Instantiator; +import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -63,7 +64,8 @@ public void fail_whenConstructorThrowsOnZero() { public void fail_whenConstructorThrowsOnSomethingElse() { Object instance = Instantiator.of(OtherThrowingConstructorRecord.class).instantiate(); - PrefabValues pv = new PrefabValues(JavaApiPrefabValues.build()); + nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues pv = + new PrefabValues(JavaApiPrefabValues.build()); ExpectedException .when(() -> accessorFor(instance).scramble(pv, TypeTag.NULL, EMPTY_TYPE_STACK)) .assertThrows(ReflectionException.class) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java index c9fba2ab4..fb500d9ff 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java @@ -9,7 +9,7 @@ import nl.jqno.equalsverifier.api.EqualsVerifierApi; import nl.jqno.equalsverifier.api.MultipleTypeEqualsVerifierApi; import nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.PackageScanner; import nl.jqno.equalsverifier.internal.util.ListBuilders; import nl.jqno.equalsverifier.internal.util.PrefabValuesApi; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index 430cbe205..7e7ea8111 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -9,7 +9,7 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.*; import nl.jqno.equalsverifier.internal.exceptions.MessagingException; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.util.*; import nl.jqno.equalsverifier.internal.util.Formatter; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java index a92f890e4..8a832753e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java @@ -4,10 +4,10 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.util.*; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java index dbb276d3c..263519800 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/FieldsChecker.java @@ -3,8 +3,8 @@ import java.util.function.Predicate; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.fieldchecks.*; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index 2ea3d1d78..96e0110bc 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -9,11 +9,11 @@ import java.util.function.Function; import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.Instantiator; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index 21b63e8a4..43eb1bac7 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -7,10 +7,10 @@ import java.util.EnumSet; import java.util.Set; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java index da6cb5cc3..e05e50ad5 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/StringFieldCheck.java @@ -4,8 +4,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.util.CachedHashCodeInitializer; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java index bc0acf689..261d970a7 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/TransientFieldsCheck.java @@ -3,8 +3,8 @@ import static nl.jqno.equalsverifier.internal.util.Assert.fail; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/exceptions/RecursionException.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/exceptions/RecursionException.java index 1e48c5625..1221f1c0b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/exceptions/RecursionException.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/exceptions/RecursionException.java @@ -3,7 +3,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.Iterator; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; /** Signals that a recursion has been detected while traversing the fields of a data structure. */ @SuppressWarnings("serial") diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/FactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/FactoryProvider.java deleted file mode 100644 index c044ff744..000000000 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/FactoryProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders; - -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; - -public interface FactoryProvider { - FactoryCache getFactoryCache(); -} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java similarity index 92% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCache.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java index 7ba5b0b53..33d702f6e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCache.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java @@ -1,10 +1,10 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; /** Contains a cache of factories, for {@link PrefabValues}. */ public class FactoryCache implements Iterable>> { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/JavaApiPrefabValues.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/JavaApiPrefabValues.java similarity index 98% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/JavaApiPrefabValues.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/JavaApiPrefabValues.java index 466a4eac2..5de84d95a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/JavaApiPrefabValues.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/JavaApiPrefabValues.java @@ -1,8 +1,8 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.*; import static nl.jqno.equalsverifier.internal.reflection.Util.classes; import static nl.jqno.equalsverifier.internal.reflection.Util.objects; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.*; import static nl.jqno.equalsverifier.internal.util.Rethrow.rethrow; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -28,12 +28,11 @@ import java.util.concurrent.locks.StampedLock; import java.util.function.Supplier; import java.util.regex.Pattern; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.EnumMapFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.EnumSetFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.ExternalFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; -import nl.jqno.equalsverifier.internal.reflection.ConditionalInstantiator; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.EnumMapFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.EnumSetFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.ExternalFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; /** * Creates instances of classes for use in a {@link PrefabValues} object. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Tuple.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Tuple.java similarity index 97% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Tuple.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Tuple.java index 3eb85fbae..c276f3fac 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Tuple.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Tuple.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection; /** * Container for three values of the same type: a "red" one, a "blue" one, and a shallow copy of the diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/TypeTag.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/TypeTag.java similarity index 99% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/TypeTag.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/TypeTag.java index a8bf32662..09b30a6e8 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/TypeTag.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/TypeTag.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection; import static nl.jqno.equalsverifier.internal.reflection.Util.classForName; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java index d318f367e..dcf99d0a3 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java @@ -3,11 +3,11 @@ import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.util.Configuration; public class SubjectCreator { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java index c1ac95f27..7a32b0f8e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java @@ -1,7 +1,7 @@ package nl.jqno.equalsverifier.internal.reflection.instantiation; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; public interface ValueProvider { Tuple provide(TypeTag tag); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java index ce0beb9cb..7df093e9b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java @@ -2,9 +2,9 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import nl.jqno.equalsverifier.internal.exceptions.ModuleException; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; public class VintageValueProvider implements ValueProvider { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java index cff82e0e9..96aecad87 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java @@ -1,8 +1,9 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.Instantiator; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Instantiates and populates objects of a given class. {@link ClassAccessor} can create two diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java index d8cef710f..7835be9fb 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java @@ -5,8 +5,9 @@ import java.lang.reflect.Field; import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; public final class FieldModifier { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java index d212add1b..ceb54205f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java @@ -2,9 +2,10 @@ import java.lang.reflect.Field; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Implementation of ObjectAccessor that modifies its wrapped object in-place through reflection. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java index 34438af13..61cd750d8 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java @@ -1,8 +1,9 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Wraps an object to provide access to it. ObjectAccessor can copy and scramble the wrapped object. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java index 0dcbb296f..789d3b22d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java @@ -5,9 +5,10 @@ import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.RecordProbe; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Implementation of ObjectAccessor that returns modified copies of its wrapped object, through diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Cache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java similarity index 88% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Cache.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java index 582d02032..7f7d10444 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/Cache.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java @@ -1,11 +1,12 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues; import java.util.HashMap; import java.util.Map; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; /** Contains a cache of prefabricated values, for {@link PrefabValues}. */ -public class Cache { +class Cache { @SuppressWarnings("rawtypes") private final Map cache = new HashMap<>(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/PrefabValues.java similarity index 93% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/PrefabValues.java index c38c3b459..f6c079c8e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValues.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/PrefabValues.java @@ -1,16 +1,15 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.Arrays; import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.RecursionException; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.prefabvalues.Cache; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.FallbackFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; /** diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactory.java similarity index 92% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactory.java index a669e8376..4c05f24db 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactory.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.InvocationTargetException; @@ -7,8 +7,8 @@ import java.util.LinkedHashSet; import java.util.List; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Abstract implementation of {@link PrefabValueFactory} that provides helper functions for dealing diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/CopyFactory.java similarity index 77% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/CopyFactory.java index 15042dfd7..1bc180671 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/CopyFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/CopyFactory.java @@ -1,10 +1,10 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import java.util.LinkedHashSet; import java.util.function.Function; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; public class CopyFactory extends AbstractGenericFactory { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumMapFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumMapFactory.java similarity index 81% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumMapFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumMapFactory.java index f04da56f5..5a1cdd0e8 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumMapFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumMapFactory.java @@ -1,12 +1,12 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.function.Function; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; @SuppressWarnings({ "unchecked", "rawtypes" }) public final class EnumMapFactory extends AbstractGenericFactory { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumSetFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumSetFactory.java similarity index 81% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumSetFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumSetFactory.java index c5a00935a..9d585a811 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/EnumSetFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumSetFactory.java @@ -1,12 +1,12 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.function.Function; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Implementation of {@link PrefabValueFactory} that instantiates EnumSets using reflection, while diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/ExternalFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/ExternalFactory.java similarity index 67% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/ExternalFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/ExternalFactory.java index 671051d77..832b2ad71 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/ExternalFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/ExternalFactory.java @@ -1,20 +1,20 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import static nl.jqno.equalsverifier.internal.reflection.Util.classes; import static nl.jqno.equalsverifier.internal.reflection.Util.objects; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders.FactoryProvider; import nl.jqno.equalsverifier.internal.reflection.ConditionalInstantiator; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders.FactoryProvider; public class ExternalFactory implements PrefabValueFactory { private static final String EXTERNAL_FACTORIES_PACKAGE = - "nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders."; + "nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders."; private final String factoryName; private FactoryCache factoryCache; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/Factories.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/Factories.java similarity index 94% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/Factories.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/Factories.java index b532e8e2c..42cf962cd 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/Factories.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/Factories.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import java.util.Collection; import java.util.Map; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java similarity index 94% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java index 3f608c990..6bdcc353f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java @@ -1,15 +1,15 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.ModuleException; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Implementation of {@link PrefabValueFactory} that instantiates types "by force". diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactory.java similarity index 85% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactory.java index a7fae5007..8bd10db23 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactory.java @@ -1,11 +1,11 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import java.util.LinkedHashSet; import java.util.Map; import java.util.function.Supplier; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Implementation of {@link PrefabValueFactory} that specializes in creating implementations of diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/PrefabValueFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/PrefabValueFactory.java similarity index 71% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/PrefabValueFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/PrefabValueFactory.java index 7da083fba..a8c8fc432 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/PrefabValueFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/PrefabValueFactory.java @@ -1,9 +1,9 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Creates instances of generic types for use as prefab value. diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactory.java similarity index 66% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactory.java index 76f3241ab..c4bf81482 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactory.java @@ -1,9 +1,9 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Implementation of {@link PrefabValueFactory} that holds on to two instances that have already diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactory.java similarity index 85% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactory.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactory.java index 63dc2e761..a4378e466 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactory.java @@ -1,13 +1,13 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.function.Supplier; import nl.jqno.equalsverifier.Func; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; public class SimpleGenericFactory extends AbstractGenericFactory { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/AwtFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/AwtFactoryProvider.java similarity index 87% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/AwtFactoryProvider.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/AwtFactoryProvider.java index a8096d9c6..2312d3b5a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/AwtFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/AwtFactoryProvider.java @@ -1,13 +1,13 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import java.awt.*; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; import java.awt.image.BufferedImage; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; public final class AwtFactoryProvider implements FactoryProvider { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/FactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/FactoryProvider.java new file mode 100644 index 000000000..c81cda452 --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/FactoryProvider.java @@ -0,0 +1,7 @@ +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders; + +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; + +public interface FactoryProvider { + FactoryCache getFactoryCache(); +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/GuavaFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/GuavaFactoryProvider.java similarity index 91% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/GuavaFactoryProvider.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/GuavaFactoryProvider.java index dfc89fd46..07e727c7f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/GuavaFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/GuavaFactoryProvider.java @@ -1,19 +1,19 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.*; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.*; import com.google.common.collect.*; import com.google.common.reflect.TypeToken; import java.util.*; import java.util.function.Supplier; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.AbstractGenericFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.EnumMapFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.EnumSetFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.AbstractGenericFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.EnumMapFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.EnumSetFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories; public final class GuavaFactoryProvider implements FactoryProvider { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProvider.java similarity index 87% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProvider.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProvider.java index 4c0db5d2f..60c775242 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProvider.java @@ -1,20 +1,20 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.copy; import static nl.jqno.equalsverifier.internal.reflection.Util.*; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.copy; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.AbstractGenericFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.reflection.ConditionalInstantiator; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.AbstractGenericFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; public final class JavaFxFactoryProvider implements FactoryProvider { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaxFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaxFactoryProvider.java similarity index 72% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaxFactoryProvider.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaxFactoryProvider.java index 8d761dfe9..386bb67ae 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaxFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaxFactoryProvider.java @@ -1,10 +1,10 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import javax.naming.Reference; import javax.swing.tree.DefaultMutableTreeNode; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; public final class JavaxFactoryProvider implements FactoryProvider { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JodaFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JodaFactoryProvider.java similarity index 82% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JodaFactoryProvider.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JodaFactoryProvider.java index c56ccda29..da40b542d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JodaFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JodaFactoryProvider.java @@ -1,8 +1,8 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import org.joda.time.*; import org.joda.time.chrono.GregorianChronology; import org.joda.time.chrono.ISOChronology; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/RmiFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/RmiFactoryProvider.java similarity index 63% rename from equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/RmiFactoryProvider.java rename to equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/RmiFactoryProvider.java index 8749a01a1..edb25d411 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/RmiFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/RmiFactoryProvider.java @@ -1,10 +1,10 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import java.rmi.dgc.VMID; import java.rmi.server.UID; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; public final class RmiFactoryProvider implements FactoryProvider { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index 51e7f1161..6b9be50a5 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -6,7 +6,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.annotations.*; public final class Configuration { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index 0d5889cf3..b0b9fb09d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -1,12 +1,12 @@ package nl.jqno.equalsverifier.internal.util; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; public final class Context { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java index 30940e367..6f972db72 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java @@ -1,13 +1,13 @@ package nl.jqno.equalsverifier.internal.util; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.simple; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.simple; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import nl.jqno.equalsverifier.Func.Func1; import nl.jqno.equalsverifier.Func.Func2; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; public final class PrefabValuesApi { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java index 0a67506c0..ab274310c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java @@ -9,10 +9,10 @@ import java.util.Set; import java.util.stream.Collectors; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; public final class Validations { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/RecursionTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/RecursionTest.java index a83cace23..952b32f0f 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/RecursionTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/RecursionTest.java @@ -9,7 +9,7 @@ import java.util.List; import java.util.Objects; import nl.jqno.equalsverifier.EqualsVerifier; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index 563ea37be..796ee7dec 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -5,13 +5,15 @@ import com.tngtech.archunit.junit.AnalyzeClasses; import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchRule; +import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.FieldModifier; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.PrefabValuesApi; +import nl.jqno.equalsverifier.testhelpers.FactoryCacheFactory; @AnalyzeClasses(packages = "nl.jqno.equalsverifier") public final class ArchitectureTest { @@ -19,11 +21,15 @@ public final class ArchitectureTest { @ArchTest public static final ArchRule ONLY_VINTAGE_INSTANTIATORS_CAN_USE_VINTAGE_REFLECTION = noClasses() .that() - .doNotBelongToAnyOf(VintageValueProvider.class, Context.class, PrefabValuesApi.class) + .doNotBelongToAnyOf( + VintageValueProvider.class, + Context.class, + PrefabValuesApi.class, + JavaApiPrefabValues.class, + FactoryCacheFactory.class + ) .and() .resideOutsideOfPackage("nl.jqno.equalsverifier.internal.reflection.vintage..") - .and() - .resideOutsideOfPackage("nl.jqno.equalsverifier.internal.prefabvalues..") .should() .accessClassesThat() .resideInAPackage("nl.jqno.equalsverifier.internal.reflection.vintage.."); @@ -74,7 +80,7 @@ public final class ArchitectureTest { ); private static final String FACTORYPROVIDER_PATTERN = - "nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders.."; + "nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders.."; private static final String TEST_CLASS_PATTERN = ".*Test(\\$.*)?$"; private ArchitectureTest() { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/exceptions/RecursionExceptionTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/exceptions/RecursionExceptionTest.java index 5e4c59587..6b118672c 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/exceptions/RecursionExceptionTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/exceptions/RecursionExceptionTest.java @@ -3,7 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.testhelpers.types.Point; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/TupleTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/TupleTest.java similarity index 94% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/TupleTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/TupleTest.java index 572484ce1..ec04bba0b 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/TupleTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/TupleTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotSame; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/TypeTagParameterizedTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/TypeTagParameterizedTest.java similarity index 98% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/TypeTagParameterizedTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/TypeTagParameterizedTest.java index eb5a66e2c..424ecef38 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/TypeTagParameterizedTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/TypeTagParameterizedTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/TypeTagTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/TypeTagTest.java similarity index 99% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/TypeTagTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/TypeTagTest.java index 26083bfab..f74a6cc5a 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/TypeTagTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/TypeTagTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java index af422f735..4cf1ca42c 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java @@ -1,12 +1,15 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.prefabvalues.*; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.testhelpers.types.PointContainer; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.TwoStepNodeA; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.TwoStepNodeB; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java index 9207b7442..7dc5c7edc 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java @@ -1,13 +1,16 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.*; import java.text.AttributedString; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; -import nl.jqno.equalsverifier.internal.prefabvalues.*; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.types.Point; import nl.jqno.equalsverifier.testhelpers.types.Point3D; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java index 894d4ab62..c04a67713 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java @@ -1,11 +1,12 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.*; import nl.jqno.equalsverifier.internal.exceptions.RecursionException; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.FactoryCacheFactory; import nl.jqno.equalsverifier.testhelpers.types.Point; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java index f4fa286cf..6d17f39a6 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java @@ -1,6 +1,6 @@ package nl.jqno.equalsverifier.internal.reflection.vintage; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import static nl.jqno.equalsverifier.internal.testhelpers.Util.defaultEquals; import static nl.jqno.equalsverifier.internal.testhelpers.Util.defaultHashCode; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -10,10 +10,11 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.testhelpers.types.Point; import nl.jqno.equalsverifier.testhelpers.types.ThrowingInitializer; import org.junit.jupiter.api.BeforeEach; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/CacheTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java similarity index 86% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/CacheTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java index 2d1ad46f0..f17641c6d 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/CacheTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java @@ -1,9 +1,12 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.Cache; import org.junit.jupiter.api.Test; public class CacheTest { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCacheTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/FactoryCacheTest.java similarity index 81% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCacheTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/FactoryCacheTest.java index 42fdad4a7..f6f91b7d2 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/FactoryCacheTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/FactoryCacheTest.java @@ -1,9 +1,10 @@ -package nl.jqno.equalsverifier.internal.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues; import static org.junit.jupiter.api.Assertions.*; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.SimpleFactory; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.SimpleFactory; import org.junit.jupiter.api.Test; public class FactoryCacheTest { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactoryTest.java similarity index 78% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactoryTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactoryTest.java index a0714fed4..591a635d4 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/AbstractGenericFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactoryTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import static nl.jqno.equalsverifier.internal.reflection.Util.classes; import static nl.jqno.equalsverifier.internal.reflection.Util.objects; @@ -6,9 +6,10 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.AbstractGenericFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FactoriesTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FactoriesTest.java similarity index 60% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FactoriesTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FactoriesTest.java index 4b951f4de..a8f805f77 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FactoriesTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FactoriesTest.java @@ -1,7 +1,8 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import static nl.jqno.equalsverifier.internal.testhelpers.Util.coverThePrivateConstructor; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories; import org.junit.jupiter.api.Test; public class FactoriesTest { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java similarity index 88% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactoryTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java index d019e34d2..70f81b50b 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/FallbackFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java @@ -1,6 +1,6 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import static nl.jqno.equalsverifier.internal.testhelpers.Util.defaultEquals; import static nl.jqno.equalsverifier.internal.testhelpers.Util.defaultHashCode; import static org.junit.jupiter.api.Assertions.assertArrayEquals; @@ -8,10 +8,11 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.RecursionException; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.FallbackFactory; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.Node; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.NodeArray; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java similarity index 88% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactoryTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java index 2f868316d..83202f4ee 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/MapFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java @@ -1,14 +1,15 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.MapFactory; import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.OneElementEnum; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactoryTest.java similarity index 80% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactoryTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactoryTest.java index 1dc6650dc..b235c290b 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactoryTest.java @@ -1,8 +1,9 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotSame; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.SimpleFactory; import org.junit.jupiter.api.Test; public class SimpleFactoryTest { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java similarity index 86% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactoryTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java index 9a79f22ba..d33dcff08 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factories/SimpleGenericFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java @@ -1,13 +1,15 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factories; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.LinkedHashSet; import java.util.Optional; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.testhelpers.types.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java similarity index 80% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java index 787a62105..a346df248 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java @@ -1,16 +1,17 @@ -package nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders; +package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.List; import java.util.Map; -import nl.jqno.equalsverifier.internal.prefabvalues.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.prefabvalues.Tuple; -import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag; -import nl.jqno.equalsverifier.internal.prefabvalues.factories.PrefabValueFactory; -import nl.jqno.equalsverifier.internal.prefabvalues.factoryproviders.JavaFxFactoryProvider.PropertyFactory; -import nl.jqno.equalsverifier.internal.reflection.vintage.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders.JavaFxFactoryProvider; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders.JavaFxFactoryProvider.PropertyFactory; import nl.jqno.equalsverifier.testhelpers.types.Point; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/FactoryCacheFactory.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/FactoryCacheFactory.java index c12e7ca33..9f9871c6e 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/FactoryCacheFactory.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/FactoryCacheFactory.java @@ -1,8 +1,8 @@ package nl.jqno.equalsverifier.testhelpers; -import static nl.jqno.equalsverifier.internal.prefabvalues.factories.Factories.values; +import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; -import nl.jqno.equalsverifier.internal.prefabvalues.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; public final class FactoryCacheFactory { From 67142f8d921ae194c9d77a48d288bd086440105d Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 15:03:58 +0200 Subject: [PATCH 50/74] Folds PrefabValues class into VintageValueProvider --- .../RecordObjectAccessorScramblingTest.java | 8 +- .../vintage/RecordObjectAccessorTest.java | 7 +- .../fieldchecks/MutableStateFieldCheck.java | 5 - .../internal/reflection/FactoryCache.java | 4 +- .../reflection/JavaApiPrefabValues.java | 6 +- .../instantiation/VintageValueProvider.java | 180 ++++++++++++++++- .../reflection/vintage/ClassAccessor.java | 20 +- .../reflection/vintage/FieldModifier.java | 8 +- .../vintage/InPlaceObjectAccessor.java | 6 +- .../reflection/vintage/ObjectAccessor.java | 6 +- .../vintage/RecordObjectAccessor.java | 6 +- .../vintage/prefabvalues/Cache.java | 5 +- .../vintage/prefabvalues/PrefabValues.java | 186 ------------------ .../factories/AbstractGenericFactory.java | 10 +- .../prefabvalues/factories/CopyFactory.java | 12 +- .../factories/EnumMapFactory.java | 14 +- .../factories/EnumSetFactory.java | 12 +- .../factories/ExternalFactory.java | 6 +- .../factories/FallbackFactory.java | 30 +-- .../prefabvalues/factories/MapFactory.java | 16 +- .../factories/PrefabValueFactory.java | 10 +- .../prefabvalues/factories/SimpleFactory.java | 4 +- .../factories/SimpleGenericFactory.java | 10 +- .../GuavaFactoryProvider.java | 44 ++--- .../JavaFxFactoryProvider.java | 24 +-- .../equalsverifier/internal/util/Context.java | 9 +- .../architecture/ArchitectureTest.java | 13 +- .../VintageValueProviderCreatorTest.java} | 65 +++--- .../VintageValueProviderTest.java} | 77 ++++---- .../reflection/vintage/ClassAccessorTest.java | 26 +-- .../InPlaceObjectAccessorScramblingTest.java | 8 +- .../vintage/prefabvalues/CacheTest.java | 1 - .../factories/AbstractGenericFactoryTest.java | 5 +- .../prefabvalues/factories/FactoriesTest.java | 1 - .../factories/FallbackFactoryTest.java | 18 +- .../factories/MapFactoryTest.java | 25 ++- .../factories/SimpleFactoryTest.java | 1 - .../factories/SimpleGenericFactoryTest.java | 28 ++- .../JavaFxFactoryProviderTest.java | 19 +- 39 files changed, 450 insertions(+), 485 deletions(-) delete mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/PrefabValues.java rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{vintage/PrefabValuesCreatorTest.java => instantiation/VintageValueProviderCreatorTest.java} (68%) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{vintage/PrefabValuesTest.java => instantiation/VintageValueProviderTest.java} (76%) diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java index 3c3e76bad..80afbd8e8 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java @@ -9,7 +9,7 @@ import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -17,12 +17,12 @@ public class RecordObjectAccessorScramblingTest { private static final LinkedHashSet EMPTY_TYPE_STACK = new LinkedHashSet<>(); private FactoryCache factoryCache; - private nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues prefabValues; + private VintageValueProvider valueProvider; @BeforeEach public void setup() throws Exception { factoryCache = JavaApiPrefabValues.build(); - prefabValues = new PrefabValues(factoryCache); + valueProvider = new VintageValueProvider(factoryCache); } @Test @@ -56,7 +56,7 @@ private RecordObjectAccessor create(T object) { } private ObjectAccessor doScramble(Object object) { - return create(object).scramble(prefabValues, TypeTag.NULL, EMPTY_TYPE_STACK); + return create(object).scramble(valueProvider, TypeTag.NULL, EMPTY_TYPE_STACK); } record Point(int x, int y) {} diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java index 40405652b..b09f96b92 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java @@ -10,7 +10,7 @@ import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -64,10 +64,9 @@ public void fail_whenConstructorThrowsOnZero() { public void fail_whenConstructorThrowsOnSomethingElse() { Object instance = Instantiator.of(OtherThrowingConstructorRecord.class).instantiate(); - nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues pv = - new PrefabValues(JavaApiPrefabValues.build()); + VintageValueProvider vp = new VintageValueProvider(JavaApiPrefabValues.build()); ExpectedException - .when(() -> accessorFor(instance).scramble(pv, TypeTag.NULL, EMPTY_TYPE_STACK)) + .when(() -> accessorFor(instance).scramble(vp, TypeTag.NULL, EMPTY_TYPE_STACK)) .assertThrows(ReflectionException.class) .assertMessageContains("Record:", "failed to run constructor", "prefab values"); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java index c8f952a28..13b0b576e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/MutableStateFieldCheck.java @@ -2,7 +2,6 @@ import static nl.jqno.equalsverifier.internal.util.Assert.fail; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.function.Predicate; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; @@ -13,10 +12,6 @@ public class MutableStateFieldCheck implements FieldCheck { private final SubjectCreator subjectCreator; private final Predicate isCachedHashCodeField; - @SuppressFBWarnings( - value = "EI_EXPOSE_REP2", - justification = "PrefabValues is inherently mutable." - ) public MutableStateFieldCheck( SubjectCreator subjectCreator, Predicate isCachedHashCodeField diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java index 33d702f6e..97f3f191e 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java @@ -3,10 +3,10 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; -/** Contains a cache of factories, for {@link PrefabValues}. */ +/** Contains a cache of factories, for {@link VintageValueProvider}. */ public class FactoryCache implements Iterable>> { /** diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/JavaApiPrefabValues.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/JavaApiPrefabValues.java index 5de84d95a..0105c4b26 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/JavaApiPrefabValues.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/JavaApiPrefabValues.java @@ -28,14 +28,14 @@ import java.util.concurrent.locks.StampedLock; import java.util.function.Supplier; import java.util.regex.Pattern; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.EnumMapFactory; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.EnumSetFactory; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.ExternalFactory; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; /** - * Creates instances of classes for use in a {@link PrefabValues} object. + * Creates instances of classes for use in a {@link VintageValueProvider} object. * *

Contains hand-made instances of well-known Java API classes that cannot be instantiated * dynamically because of an internal infinite recursion of types, or other issues. @@ -432,7 +432,7 @@ private void addSets() { addFactory(CopyOnWriteArraySet.class, collection(CopyOnWriteArraySet::new)); addFactory(HashSet.class, collection(HashSet::new)); addFactory(TreeSet.class, collection(() -> new TreeSet<>(OBJECT_COMPARATOR))); - addFactory(EnumSet.class, new EnumSetFactory<>(EnumSet::copyOf)); + addFactory(EnumSet.class, new EnumSetFactory<>(c -> EnumSet.copyOf(c))); addValues( BitSet.class, BitSet.valueOf(new byte[] { 0 }), diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java index 7df093e9b..33b7056ac 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java @@ -1,27 +1,39 @@ package nl.jqno.equalsverifier.internal.reflection.instantiation; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.util.Arrays; +import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.exceptions.ModuleException; +import nl.jqno.equalsverifier.internal.exceptions.RecursionException; +import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; +import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.Cache; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.FallbackFactory; +import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; +import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; public class VintageValueProvider implements ValueProvider { - private final PrefabValues prefabValues; + private final Cache cache = new Cache(); + private final FactoryCache factoryCache; + private final PrefabValueFactory fallbackFactory = new FallbackFactory<>(); - @SuppressFBWarnings( - value = "EI_EXPOSE_REP2", - justification = "PrefabValues is inherently mutable." - ) - public VintageValueProvider(PrefabValues prefabValues) { - this.prefabValues = prefabValues; + /** + * Constructor. + * + * @param factoryCache The factories that can be used to create values. + */ + @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "A cache is inherently mutable.") + public VintageValueProvider(FactoryCache factoryCache) { + this.factoryCache = factoryCache; } @Override public Tuple provide(TypeTag tag) { try { - return prefabValues.giveTuple(tag); + return giveTuple(tag); } catch (RuntimeException e) { // InaccessibleObjectException is not yet available in Java 8 if (e.getClass().getName().endsWith("InaccessibleObjectException")) { @@ -34,4 +46,154 @@ public Tuple provide(TypeTag tag) { } } } + + /** + * Returns the "red" prefabricated value of the specified type. + * + *

It's always a different value from the "blue" one. + * + * @param The return value is cast to this type. + * @param tag A description of the desired type, including generic parameters. + * @return The "red" prefabricated value. + */ + public T giveRed(TypeTag tag) { + return this.giveTuple(tag).getRed(); + } + + /** + * Returns the "blue" prefabricated value of the specified type. + * + *

It's always a different value from the "red" one. + * + * @param The return value is cast to this type. + * @param tag A description of the desired type, including generic parameters. + * @return The "blue" prefabricated value. + */ + public T giveBlue(TypeTag tag) { + return this.giveTuple(tag).getBlue(); + } + + /** + * Returns a shallow copy of the "red" prefabricated value of the specified type. + * + *

When possible, it's equal to but not the same as the "red" object. + * + * @param The return value is cast to this type. + * @param tag A description of the desired type, including generic parameters. + * @return A shallow copy of the "red" prefabricated value. + */ + public T giveRedCopy(TypeTag tag) { + return this.giveTuple(tag).getRedCopy(); + } + + /** + * Returns a tuple of two different prefabricated values of the specified type. + * + * @param The returned tuple will have this generic type. + * @param tag A description of the desired type, including generic parameters. + * @return A tuple of two different values of the given type. + */ + public Tuple giveTuple(TypeTag tag) { + return giveTuple(tag, new LinkedHashSet<>()); + } + + /** + * Returns a tuple of two different prefabricated values of the specified type. + * + * @param The returned tuple will have this generic type. + * @param tag A description of the desired type, including generic parameters. + * @param typeStack Keeps track of recursion in the type. + * @return A tuple of two different values of the given type. + */ + public Tuple giveTuple(TypeTag tag, LinkedHashSet typeStack) { + realizeCacheFor(tag, typeStack); + return cache.getTuple(tag); + } + + /** + * Returns a prefabricated value of the specified type, that is different from the specified + * value. + * + * @param The type of the value. + * @param tag A description of the desired type, including generic parameters. + * @param value A value that is different from the value that will be returned. + * @param typeStack Keeps track of recursion in the type. + * @return A value that is different from {@code value}. + */ + // CHECKSTYLE OFF: CyclomaticComplexity + public T giveOther(TypeTag tag, T value, LinkedHashSet typeStack) { + Class type = tag.getType(); + if ( + value != null && + !type.isAssignableFrom(value.getClass()) && + !wraps(type, value.getClass()) + ) { + throw new ReflectionException("TypeTag does not match value."); + } + + Tuple tuple = giveTuple(tag, typeStack); + if (tuple.getRed() == null) { + return null; + } + if (type.isArray() && arraysAreDeeplyEqual(tuple.getRed(), value)) { + return tuple.getBlue(); + } + if (!type.isArray() && value != null) { + try { + // red's equals can potentially call an abstract method + if (tuple.getRed().equals(value)) { + return tuple.getBlue(); + } + } catch (AbstractMethodError e) { + return tuple.getRed(); + } + } + return tuple.getRed(); + } + + // CHECKSTYLE ON: CyclomaticComplexity + + private boolean wraps(Class expectedClass, Class actualClass) { + return PrimitiveMappers.PRIMITIVE_OBJECT_MAPPER.get(expectedClass) == actualClass; + } + + private boolean arraysAreDeeplyEqual(Object x, Object y) { + // Arrays.deepEquals doesn't accept Object values so we need to wrap them in another array. + return Arrays.deepEquals(new Object[] { x }, new Object[] { y }); + } + + /** + * Makes sure that values for the specified type are present in the cache, but doesn't return + * them. + * + * @param The desired type. + * @param tag A description of the desired type, including generic parameters. + * @param typeStack Keeps track of recursion in the type. + */ + public void realizeCacheFor(TypeTag tag, LinkedHashSet typeStack) { + if (!cache.contains(tag)) { + Tuple tuple = createTuple(tag, typeStack); + addToCache(tag, tuple); + } + } + + private Tuple createTuple(TypeTag tag, LinkedHashSet typeStack) { + if (typeStack.contains(tag)) { + throw new RecursionException(typeStack); + } + + Class type = tag.getType(); + if (factoryCache.contains(type)) { + PrefabValueFactory factory = factoryCache.get(type); + return factory.createValues(tag, this, typeStack); + } + + @SuppressWarnings("unchecked") + Tuple result = (Tuple) fallbackFactory.createValues(tag, this, typeStack); + return result; + } + + private void addToCache(TypeTag tag, Tuple tuple) { + cache.put(tag, tuple.getRed(), tuple.getBlue(), tuple.getRedCopy()); + } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java index 96aecad87..387f8fe7c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java @@ -3,7 +3,7 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; /** * Instantiates and populates objects of a given class. {@link ClassAccessor} can create two @@ -15,12 +15,12 @@ public class ClassAccessor { private final Class type; - private final PrefabValues prefabValues; + private final VintageValueProvider valueProvider; /** Private constructor. Call {@link #of(Class, PrefabValues)} instead. */ - ClassAccessor(Class type, PrefabValues prefabValues) { + ClassAccessor(Class type, VintageValueProvider valueProvider) { this.type = type; - this.prefabValues = prefabValues; + this.valueProvider = valueProvider; } /** @@ -28,11 +28,11 @@ public class ClassAccessor { * * @param The class on which {@link ClassAccessor} operates. * @param type The class on which {@link ClassAccessor} operates. Should be the same as T. - * @param prefabValues Prefabricated values with which to fill instantiated objects. + * @param valueProvider Prefabricated values with which to fill instantiated objects. * @return A {@link ClassAccessor} for T. */ - public static ClassAccessor of(Class type, PrefabValues prefabValues) { - return new ClassAccessor<>(type, prefabValues); + public static ClassAccessor of(Class type, VintageValueProvider valueProvider) { + return new ClassAccessor<>(type, valueProvider); } /** @@ -60,7 +60,7 @@ public ObjectAccessor getRedAccessor( TypeTag enclosingType, LinkedHashSet typeStack ) { - return buildObjectAccessor().scramble(prefabValues, enclosingType, typeStack); + return buildObjectAccessor().scramble(valueProvider, enclosingType, typeStack); } /** @@ -89,8 +89,8 @@ public ObjectAccessor getBlueAccessor( LinkedHashSet typeStack ) { return buildObjectAccessor() - .scramble(prefabValues, enclosingType, typeStack) - .scramble(prefabValues, enclosingType, typeStack); + .scramble(valueProvider, enclosingType, typeStack) + .scramble(valueProvider, enclosingType, typeStack); } private ObjectAccessor buildObjectAccessor() { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java index 7835be9fb..0b91e5f87 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/FieldModifier.java @@ -7,7 +7,7 @@ import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; public final class FieldModifier { @@ -49,7 +49,7 @@ public void copyTo(Object to) { * *

Ignores static fields and fields that can't be modified reflectively. * - * @param prefabValues If the field is of a type contained within prefabValues, the new value + * @param valueProvider If the field is of a type contained within prefabValues, the new value * will be taken from it. * @param enclosingType A tag for the type that contains the field. Needed to determine a * generic type, if it has one.. @@ -57,13 +57,13 @@ public void copyTo(Object to) { * @throws ReflectionException If the operation fails. */ public void changeField( - PrefabValues prefabValues, + VintageValueProvider valueProvider, TypeTag enclosingType, LinkedHashSet typeStack ) { FieldChanger fm = () -> { TypeTag tag = TypeTag.of(field, enclosingType); - Object newValue = prefabValues.giveOther(tag, field.get(object), typeStack); + Object newValue = valueProvider.giveOther(tag, field.get(object), typeStack); field.set(object, newValue); }; change(fm, false); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java index ceb54205f..b991efc3f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java @@ -5,7 +5,7 @@ import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; /** * Implementation of ObjectAccessor that modifies its wrapped object in-place through reflection. @@ -32,12 +32,12 @@ public T copy() { /** {@inheritDoc} */ @Override public ObjectAccessor scramble( - PrefabValues prefabValues, + VintageValueProvider valueProvider, TypeTag enclosingType, LinkedHashSet typeStack ) { for (Field field : FieldIterable.of(type())) { - fieldModifierFor(field).changeField(prefabValues, enclosingType, typeStack); + fieldModifierFor(field).changeField(valueProvider, enclosingType, typeStack); } return this; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java index 61cd750d8..72b031683 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java @@ -3,7 +3,7 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; /** * Wraps an object to provide access to it. ObjectAccessor can copy and scramble the wrapped object. @@ -90,14 +90,14 @@ public Class type() { * initialized to a compile-time constant in the field declaration. These fields may be left * unmodified. * - * @param prefabValues Prefabricated values to take values from. + * @param valueProvider Prefabricated values to take values from. * @param enclosingType Describes the type that contains this object as a field, to determine * any generic parameters it may contain. * @param typeStack Keeps track of recursion in the type. * @return An accessor to the scrambled object. */ public abstract ObjectAccessor scramble( - PrefabValues prefabValues, + VintageValueProvider valueProvider, TypeTag enclosingType, LinkedHashSet typeStack ); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java index 789d3b22d..459f50b66 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java @@ -8,7 +8,7 @@ import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.RecordProbe; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; /** * Implementation of ObjectAccessor that returns modified copies of its wrapped object, through @@ -37,14 +37,14 @@ public T copy() { /** {@inheritDoc} */ @Override public ObjectAccessor scramble( - PrefabValues prefabValues, + VintageValueProvider valueProvider, TypeTag enclosingType, LinkedHashSet typeStack ) { return makeAccessor(f -> { Object value = getField(f); TypeTag tag = TypeTag.of(f, enclosingType); - return prefabValues.giveOther(tag, value, typeStack); + return valueProvider.giveOther(tag, value, typeStack); }); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java index 7f7d10444..a3f3dc049 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java @@ -4,9 +4,10 @@ import java.util.Map; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; -/** Contains a cache of prefabricated values, for {@link PrefabValues}. */ -class Cache { +/** Contains a cache of prefabricated values, for {@link VintageValueProvider}. */ +public class Cache { @SuppressWarnings("rawtypes") private final Map cache = new HashMap<>(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/PrefabValues.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/PrefabValues.java deleted file mode 100644 index f6c079c8e..000000000 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/PrefabValues.java +++ /dev/null @@ -1,186 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.util.Arrays; -import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.exceptions.RecursionException; -import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; -import nl.jqno.equalsverifier.internal.reflection.FactoryCache; -import nl.jqno.equalsverifier.internal.reflection.Tuple; -import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.FallbackFactory; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; -import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; - -/** - * Container and creator of prefabricated instances of objects and classes. - * - *

Only creates values ones, and caches them once they've been created. Takes generics into - * account; i.e., {@code List} is different from {@code List}. - */ -public class PrefabValues { - - private final Cache cache = new Cache(); - private final FactoryCache factoryCache; - private final PrefabValueFactory fallbackFactory = new FallbackFactory<>(); - - /** - * Constructor. - * - * @param factoryCache The factories that can be used to create values. - */ - @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "A cache is inherently mutable.") - public PrefabValues(FactoryCache factoryCache) { - this.factoryCache = factoryCache; - } - - /** - * Returns the "red" prefabricated value of the specified type. - * - *

It's always a different value from the "blue" one. - * - * @param The return value is cast to this type. - * @param tag A description of the desired type, including generic parameters. - * @return The "red" prefabricated value. - */ - public T giveRed(TypeTag tag) { - return this.giveTuple(tag).getRed(); - } - - /** - * Returns the "blue" prefabricated value of the specified type. - * - *

It's always a different value from the "red" one. - * - * @param The return value is cast to this type. - * @param tag A description of the desired type, including generic parameters. - * @return The "blue" prefabricated value. - */ - public T giveBlue(TypeTag tag) { - return this.giveTuple(tag).getBlue(); - } - - /** - * Returns a shallow copy of the "red" prefabricated value of the specified type. - * - *

When possible, it's equal to but not the same as the "red" object. - * - * @param The return value is cast to this type. - * @param tag A description of the desired type, including generic parameters. - * @return A shallow copy of the "red" prefabricated value. - */ - public T giveRedCopy(TypeTag tag) { - return this.giveTuple(tag).getRedCopy(); - } - - /** - * Returns a tuple of two different prefabricated values of the specified type. - * - * @param The returned tuple will have this generic type. - * @param tag A description of the desired type, including generic parameters. - * @return A tuple of two different values of the given type. - */ - public Tuple giveTuple(TypeTag tag) { - return giveTuple(tag, new LinkedHashSet<>()); - } - - /** - * Returns a tuple of two different prefabricated values of the specified type. - * - * @param The returned tuple will have this generic type. - * @param tag A description of the desired type, including generic parameters. - * @param typeStack Keeps track of recursion in the type. - * @return A tuple of two different values of the given type. - */ - public Tuple giveTuple(TypeTag tag, LinkedHashSet typeStack) { - realizeCacheFor(tag, typeStack); - return cache.getTuple(tag); - } - - /** - * Returns a prefabricated value of the specified type, that is different from the specified - * value. - * - * @param The type of the value. - * @param tag A description of the desired type, including generic parameters. - * @param value A value that is different from the value that will be returned. - * @param typeStack Keeps track of recursion in the type. - * @return A value that is different from {@code value}. - */ - // CHECKSTYLE OFF: CyclomaticComplexity - public T giveOther(TypeTag tag, T value, LinkedHashSet typeStack) { - Class type = tag.getType(); - if ( - value != null && - !type.isAssignableFrom(value.getClass()) && - !wraps(type, value.getClass()) - ) { - throw new ReflectionException("TypeTag does not match value."); - } - - Tuple tuple = giveTuple(tag, typeStack); - if (tuple.getRed() == null) { - return null; - } - if (type.isArray() && arraysAreDeeplyEqual(tuple.getRed(), value)) { - return tuple.getBlue(); - } - if (!type.isArray() && value != null) { - try { - // red's equals can potentially call an abstract method - if (tuple.getRed().equals(value)) { - return tuple.getBlue(); - } - } catch (AbstractMethodError e) { - return tuple.getRed(); - } - } - return tuple.getRed(); - } - - // CHECKSTYLE ON: CyclomaticComplexity - - private boolean wraps(Class expectedClass, Class actualClass) { - return PrimitiveMappers.PRIMITIVE_OBJECT_MAPPER.get(expectedClass) == actualClass; - } - - private boolean arraysAreDeeplyEqual(Object x, Object y) { - // Arrays.deepEquals doesn't accept Object values so we need to wrap them in another array. - return Arrays.deepEquals(new Object[] { x }, new Object[] { y }); - } - - /** - * Makes sure that values for the specified type are present in the cache, but doesn't return - * them. - * - * @param The desired type. - * @param tag A description of the desired type, including generic parameters. - * @param typeStack Keeps track of recursion in the type. - */ - public void realizeCacheFor(TypeTag tag, LinkedHashSet typeStack) { - if (!cache.contains(tag)) { - Tuple tuple = createTuple(tag, typeStack); - addToCache(tag, tuple); - } - } - - private Tuple createTuple(TypeTag tag, LinkedHashSet typeStack) { - if (typeStack.contains(tag)) { - throw new RecursionException(typeStack); - } - - Class type = tag.getType(); - if (factoryCache.contains(type)) { - PrefabValueFactory factory = factoryCache.get(type); - return factory.createValues(tag, this, typeStack); - } - - @SuppressWarnings("unchecked") - Tuple result = (Tuple) fallbackFactory.createValues(tag, this, typeStack); - return result; - } - - private void addToCache(TypeTag tag, Tuple tuple) { - cache.put(tag, tuple.getRed(), tuple.getBlue(), tuple.getRedCopy()); - } -} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactory.java index 4c05f24db..0058867ad 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactory.java @@ -8,7 +8,7 @@ import java.util.List; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; /** * Abstract implementation of {@link PrefabValueFactory} that provides helper functions for dealing @@ -36,16 +36,16 @@ protected TypeTag copyGenericTypesInto(Class type, TypeTag source) { protected TypeTag determineAndCacheActualTypeTag( int n, TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { - return determineAndCacheActualTypeTag(n, tag, prefabValues, typeStack, null); + return determineAndCacheActualTypeTag(n, tag, valueProvider, typeStack, null); } protected TypeTag determineAndCacheActualTypeTag( int n, TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack, Class bottomType ) { @@ -53,7 +53,7 @@ protected TypeTag determineAndCacheActualTypeTag( if (bottomType != null && result.getType().equals(Object.class)) { result = new TypeTag(bottomType); } - prefabValues.realizeCacheFor(result, typeStack); + valueProvider.realizeCacheFor(result, typeStack); return result; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/CopyFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/CopyFactory.java index 1bc180671..1b1222861 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/CopyFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/CopyFactory.java @@ -4,7 +4,7 @@ import java.util.function.Function; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; public class CopyFactory extends AbstractGenericFactory { @@ -19,16 +19,16 @@ public CopyFactory(Class source, Function copy) { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { LinkedHashSet clone = cloneWith(typeStack, tag); TypeTag sourceTag = copyGenericTypesInto(source, tag); - prefabValues.realizeCacheFor(sourceTag, clone); + valueProvider.realizeCacheFor(sourceTag, clone); - S redSource = prefabValues.giveRed(sourceTag); - S blueSource = prefabValues.giveBlue(sourceTag); - S redCopySource = prefabValues.giveRedCopy(sourceTag); + S redSource = valueProvider.giveRed(sourceTag); + S blueSource = valueProvider.giveBlue(sourceTag); + S redCopySource = valueProvider.giveRedCopy(sourceTag); return Tuple.of(copy.apply(redSource), copy.apply(blueSource), copy.apply(redCopySource)); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumMapFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumMapFactory.java index 5a1cdd0e8..5b1424694 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumMapFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumMapFactory.java @@ -6,7 +6,7 @@ import java.util.function.Function; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; @SuppressWarnings({ "unchecked", "rawtypes" }) public final class EnumMapFactory extends AbstractGenericFactory { @@ -20,19 +20,19 @@ public EnumMapFactory(Function factory) { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { LinkedHashSet clone = cloneWith(typeStack, tag); - TypeTag keyTag = determineAndCacheActualTypeTag(0, tag, prefabValues, clone, Enum.class); - TypeTag valueTag = determineAndCacheActualTypeTag(1, tag, prefabValues, clone, Enum.class); + TypeTag keyTag = determineAndCacheActualTypeTag(0, tag, valueProvider, clone, Enum.class); + TypeTag valueTag = determineAndCacheActualTypeTag(1, tag, valueProvider, clone, Enum.class); Map red = new HashMap<>(); Map blue = new HashMap<>(); Map redCopy = new HashMap<>(); - red.put(prefabValues.giveRed(keyTag), prefabValues.giveBlue(valueTag)); - blue.put(prefabValues.giveBlue(keyTag), prefabValues.giveBlue(valueTag)); - redCopy.put(prefabValues.giveRed(keyTag), prefabValues.giveBlue(valueTag)); + red.put(valueProvider.giveRed(keyTag), valueProvider.giveBlue(valueTag)); + blue.put(valueProvider.giveBlue(keyTag), valueProvider.giveBlue(valueTag)); + redCopy.put(valueProvider.giveRed(keyTag), valueProvider.giveBlue(valueTag)); return Tuple.of(factory.apply(red), factory.apply(blue), factory.apply(redCopy)); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumSetFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumSetFactory.java index 9d585a811..61a59e447 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumSetFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/EnumSetFactory.java @@ -6,7 +6,7 @@ import java.util.function.Function; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; /** * Implementation of {@link PrefabValueFactory} that instantiates EnumSets using reflection, while @@ -24,18 +24,18 @@ public EnumSetFactory(Function factory) { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { LinkedHashSet clone = cloneWith(typeStack, tag); - TypeTag entryTag = determineAndCacheActualTypeTag(0, tag, prefabValues, clone, Enum.class); + TypeTag entryTag = determineAndCacheActualTypeTag(0, tag, valueProvider, clone, Enum.class); Collection red = new HashSet<>(); Collection blue = new HashSet<>(); Collection redCopy = new HashSet<>(); - red.add(prefabValues.giveRed(entryTag)); - blue.add(prefabValues.giveBlue(entryTag)); - redCopy.add(prefabValues.giveRed(entryTag)); + red.add(valueProvider.giveRed(entryTag)); + blue.add(valueProvider.giveBlue(entryTag)); + redCopy.add(valueProvider.giveRed(entryTag)); return new Tuple<>(factory.apply(red), factory.apply(blue), factory.apply(redCopy)); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/ExternalFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/ExternalFactory.java index 832b2ad71..0bea3340b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/ExternalFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/ExternalFactory.java @@ -8,7 +8,7 @@ import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders.FactoryProvider; public class ExternalFactory implements PrefabValueFactory { @@ -26,7 +26,7 @@ public ExternalFactory(String factoryName) { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { if (factoryCache == null) { @@ -36,6 +36,6 @@ public Tuple createValues( } PrefabValueFactory factory = factoryCache.get(tag.getType()); - return factory.createValues(tag, prefabValues, typeStack); + return factory.createValues(tag, valueProvider, typeStack); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java index 6bdcc353f..282e2c0b9 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java @@ -8,21 +8,21 @@ import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; /** * Implementation of {@link PrefabValueFactory} that instantiates types "by force". * *

It instantiates the type using bytecode magic, bypassing the constructor. Then it uses {@link - * PrefabValues} to fill up all the fields, recursively. + * VintageValueProvider} to fill up all the fields, recursively. */ public class FallbackFactory implements PrefabValueFactory { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { @SuppressWarnings("unchecked") @@ -34,11 +34,11 @@ public Tuple createValues( return giveEnumInstances(tag); } if (type.isArray()) { - return giveArrayInstances(tag, prefabValues, clone); + return giveArrayInstances(tag, valueProvider, clone); } - traverseFields(tag, prefabValues, clone); - return giveInstances(tag, prefabValues, clone); + traverseFields(tag, valueProvider, clone); + return giveInstances(tag, valueProvider, clone); } private Tuple giveEnumInstances(TypeTag tag) { @@ -58,27 +58,27 @@ private Tuple giveEnumInstances(TypeTag tag) { @SuppressWarnings("unchecked") private Tuple giveArrayInstances( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { Class type = tag.getType(); Class componentType = type.getComponentType(); TypeTag componentTag = new TypeTag(componentType); - prefabValues.realizeCacheFor(componentTag, typeStack); + valueProvider.realizeCacheFor(componentTag, typeStack); T red = (T) Array.newInstance(componentType, 1); - Array.set(red, 0, prefabValues.giveRed(componentTag)); + Array.set(red, 0, valueProvider.giveRed(componentTag)); T blue = (T) Array.newInstance(componentType, 1); - Array.set(blue, 0, prefabValues.giveBlue(componentTag)); + Array.set(blue, 0, valueProvider.giveBlue(componentTag)); T redCopy = (T) Array.newInstance(componentType, 1); - Array.set(redCopy, 0, prefabValues.giveRed(componentTag)); + Array.set(redCopy, 0, valueProvider.giveRed(componentTag)); return new Tuple<>(red, blue, redCopy); } private void traverseFields( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { Class type = tag.getType(); @@ -87,7 +87,7 @@ private void traverseFields( boolean isStaticAndFinal = probe.isStatic() && probe.isFinal(); if (!isStaticAndFinal) { try { - prefabValues.realizeCacheFor(TypeTag.of(field, tag), typeStack); + valueProvider.realizeCacheFor(TypeTag.of(field, tag), typeStack); } catch (RuntimeException e) { // InaccessibleObjectException is not yet available in Java 8 if (e.getClass().getName().endsWith("InaccessibleObjectException")) { @@ -102,10 +102,10 @@ private void traverseFields( private Tuple giveInstances( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { - ClassAccessor accessor = ClassAccessor.of(tag.getType(), prefabValues); + ClassAccessor accessor = ClassAccessor.of(tag.getType(), valueProvider); T red = accessor.getRedObject(tag, typeStack); T blue = accessor.getBlueObject(tag, typeStack); T redCopy = accessor.getRedObject(tag, typeStack); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactory.java index 8bd10db23..f835cfe90 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactory.java @@ -5,7 +5,7 @@ import java.util.function.Supplier; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; /** * Implementation of {@link PrefabValueFactory} that specializes in creating implementations of @@ -23,27 +23,27 @@ public MapFactory(Supplier createEmpty) { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { LinkedHashSet clone = cloneWith(typeStack, tag); - TypeTag keyTag = determineAndCacheActualTypeTag(0, tag, prefabValues, clone); - TypeTag valueTag = determineAndCacheActualTypeTag(1, tag, prefabValues, clone); + TypeTag keyTag = determineAndCacheActualTypeTag(0, tag, valueProvider, clone); + TypeTag valueTag = determineAndCacheActualTypeTag(1, tag, valueProvider, clone); // Use red for key and blue for value in the Red map to avoid having identical keys and // values. // But don't do it in the Blue map, or they may cancel each other out again. - Object redKey = prefabValues.giveRed(keyTag); - Object blueKey = prefabValues.giveBlue(keyTag); - Object blueValue = prefabValues.giveBlue(valueTag); + Object redKey = valueProvider.giveRed(keyTag); + Object blueKey = valueProvider.giveBlue(keyTag); + Object blueValue = valueProvider.giveBlue(valueTag); T red = createEmpty.get(); red.put(redKey, blueValue); T blue = createEmpty.get(); if (!redKey.equals(blueKey)) { // This happens with single-element enums - blue.put(prefabValues.giveBlue(keyTag), blueValue); + blue.put(valueProvider.giveBlue(keyTag), blueValue); } T redCopy = createEmpty.get(); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/PrefabValueFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/PrefabValueFactory.java index a8c8fc432..4616c2660 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/PrefabValueFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/PrefabValueFactory.java @@ -3,7 +3,7 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; /** * Creates instances of generic types for use as prefab value. @@ -16,10 +16,14 @@ public interface PrefabValueFactory { * Creates a tuple of two prefab values. * * @param tag The typetag of the type for which to create values. - * @param prefabValues Repository for querying instances of generic types of the type tag. + * @param valueProvider Repository for querying instances of generic types of the type tag. * @param typeStack A stack of {@link TypeTag}s that require tag in order to be created. Used * for recursion detection. * @return A "red" instance of {@code T}. */ - Tuple createValues(TypeTag tag, PrefabValues prefabValues, LinkedHashSet typeStack); + Tuple createValues( + TypeTag tag, + VintageValueProvider valueProvider, + LinkedHashSet typeStack + ); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactory.java index c4bf81482..44a7ae041 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactory.java @@ -3,7 +3,7 @@ import java.util.LinkedHashSet; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; /** * Implementation of {@link PrefabValueFactory} that holds on to two instances that have already @@ -20,7 +20,7 @@ public SimpleFactory(T red, T blue, T redCopy) { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { return tuple; diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactory.java index a4378e466..748f64f7f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactory.java @@ -7,7 +7,7 @@ import nl.jqno.equalsverifier.Func; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; public class SimpleGenericFactory extends AbstractGenericFactory { @@ -22,7 +22,7 @@ public SimpleGenericFactory(Func factory, Supplier emptyFactory) { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { LinkedHashSet clone = cloneWith(typeStack, tag); @@ -33,10 +33,10 @@ public Tuple createValues( boolean useEmpty = false; int n = tag.getType().getTypeParameters().length; for (int i = 0; i < n; i++) { - TypeTag paramTag = determineAndCacheActualTypeTag(i, tag, prefabValues, clone); + TypeTag paramTag = determineAndCacheActualTypeTag(i, tag, valueProvider, clone); - Object redValue = prefabValues.giveRed(paramTag); - Object blueValue = prefabValues.giveBlue(paramTag); + Object redValue = valueProvider.giveRed(paramTag); + Object blueValue = valueProvider.giveBlue(paramTag); if (redValue.equals(blueValue)) { // This happens with single-element enums useEmpty = true; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/GuavaFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/GuavaFactoryProvider.java index 07e727c7f..4416de38c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/GuavaFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/GuavaFactoryProvider.java @@ -9,7 +9,7 @@ import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.AbstractGenericFactory; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.EnumMapFactory; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.EnumSetFactory; @@ -43,7 +43,7 @@ private void putMultisets(FactoryCache cache) { cache.put(TreeMultiset.class, collection(() -> TreeMultiset.create(OBJECT_COMPARATOR))); cache.put(LinkedHashMultiset.class, collection(LinkedHashMultiset::create)); cache.put(ConcurrentHashMultiset.class, collection(ConcurrentHashMultiset::create)); - cache.put(EnumMultiset.class, new EnumSetFactory<>(EnumMultiset::create)); + cache.put(EnumMultiset.class, new EnumSetFactory<>(c -> EnumMultiset.create(c))); cache.put(ImmutableMultiset.class, copy(Set.class, ImmutableMultiset::copyOf)); cache.put( ImmutableSortedMultiset.class, @@ -79,7 +79,7 @@ private void putBiMaps(FactoryCache cache) { cache.put(HashBiMap.class, map(HashBiMap::create)); cache.put(EnumHashBiMap.class, copy(EnumMap.class, EnumHashBiMap::create)); cache.put(ImmutableBiMap.class, copy(Map.class, ImmutableBiMap::copyOf)); - cache.put(EnumBiMap.class, new EnumMapFactory<>(EnumBiMap::create)); + cache.put(EnumBiMap.class, new EnumMapFactory<>(c -> EnumBiMap.create(c))); } @SuppressWarnings("unchecked") @@ -159,19 +159,19 @@ private MultimapFactory(Supplier factory) { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { LinkedHashSet clone = cloneWith(typeStack, tag); - TypeTag keyTag = determineAndCacheActualTypeTag(0, tag, prefabValues, clone); - TypeTag valueTag = determineAndCacheActualTypeTag(1, tag, prefabValues, clone); + TypeTag keyTag = determineAndCacheActualTypeTag(0, tag, valueProvider, clone); + TypeTag valueTag = determineAndCacheActualTypeTag(1, tag, valueProvider, clone); T red = factory.get(); T blue = factory.get(); T redCopy = factory.get(); - red.put(prefabValues.giveRed(keyTag), prefabValues.giveBlue(valueTag)); - blue.put(prefabValues.giveBlue(keyTag), prefabValues.giveBlue(valueTag)); - redCopy.put(prefabValues.giveRed(keyTag), prefabValues.giveBlue(valueTag)); + red.put(valueProvider.giveRed(keyTag), valueProvider.giveBlue(valueTag)); + blue.put(valueProvider.giveBlue(keyTag), valueProvider.giveBlue(valueTag)); + redCopy.put(valueProvider.giveRed(keyTag), valueProvider.giveBlue(valueTag)); return Tuple.of(red, blue, redCopy); } @@ -189,31 +189,31 @@ private TableFactory(Supplier factory) { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { LinkedHashSet clone = cloneWith(typeStack, tag); - TypeTag columnTag = determineAndCacheActualTypeTag(0, tag, prefabValues, clone); - TypeTag rowTag = determineAndCacheActualTypeTag(1, tag, prefabValues, clone); - TypeTag valueTag = determineAndCacheActualTypeTag(2, tag, prefabValues, clone); + TypeTag columnTag = determineAndCacheActualTypeTag(0, tag, valueProvider, clone); + TypeTag rowTag = determineAndCacheActualTypeTag(1, tag, valueProvider, clone); + TypeTag valueTag = determineAndCacheActualTypeTag(2, tag, valueProvider, clone); T red = factory.get(); T blue = factory.get(); T redCopy = factory.get(); red.put( - prefabValues.giveRed(columnTag), - prefabValues.giveRed(rowTag), - prefabValues.giveBlue(valueTag) + valueProvider.giveRed(columnTag), + valueProvider.giveRed(rowTag), + valueProvider.giveBlue(valueTag) ); blue.put( - prefabValues.giveBlue(columnTag), - prefabValues.giveBlue(rowTag), - prefabValues.giveBlue(valueTag) + valueProvider.giveBlue(columnTag), + valueProvider.giveBlue(rowTag), + valueProvider.giveBlue(valueTag) ); redCopy.put( - prefabValues.giveRed(columnTag), - prefabValues.giveRed(rowTag), - prefabValues.giveBlue(valueTag) + valueProvider.giveRed(columnTag), + valueProvider.giveRed(rowTag), + valueProvider.giveBlue(valueTag) ); return Tuple.of(red, blue, redCopy); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProvider.java index 60c775242..aa2b6a3ca 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProvider.java @@ -1,18 +1,14 @@ package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders; -import static nl.jqno.equalsverifier.internal.reflection.Util.*; +import static nl.jqno.equalsverifier.internal.reflection.Util.classForName; +import static nl.jqno.equalsverifier.internal.reflection.Util.classes; +import static nl.jqno.equalsverifier.internal.reflection.Util.objects; import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.copy; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.Function; -import nl.jqno.equalsverifier.internal.reflection.ConditionalInstantiator; -import nl.jqno.equalsverifier.internal.reflection.FactoryCache; -import nl.jqno.equalsverifier.internal.reflection.Tuple; -import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.*; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.AbstractGenericFactory; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; @@ -111,7 +107,7 @@ static final class PropertyFactory extends AbstractGenericFactory { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { ConditionalInstantiator ci = new ConditionalInstantiator(fullyQualifiedTypeName); @@ -119,15 +115,15 @@ public Tuple createValues( T red = ci.instantiate( classes(parameterRawType), - objects(prefabValues.giveRed(singleParameterTag)) + objects(valueProvider.giveRed(singleParameterTag)) ); T blue = ci.instantiate( classes(parameterRawType), - objects(prefabValues.giveBlue(singleParameterTag)) + objects(valueProvider.giveBlue(singleParameterTag)) ); T redCopy = ci.instantiate( classes(parameterRawType), - objects(prefabValues.giveRed(singleParameterTag)) + objects(valueProvider.giveRed(singleParameterTag)) ); return Tuple.of(red, blue, redCopy); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index b0b9fb09d..7026b7037 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -1,12 +1,12 @@ package nl.jqno.equalsverifier.internal.util; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; public final class Context { @@ -22,9 +22,8 @@ public Context(Configuration configuration, FactoryCache factoryCache) { this.classProbe = new ClassProbe<>(configuration.getType()); FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); - PrefabValues prefabValues = new PrefabValues(cache); - this.valueProvider = new VintageValueProvider(prefabValues); + this.valueProvider = new VintageValueProvider(cache); this.subjectCreator = new SubjectCreator<>(configuration.getTypeTag(), configuration, valueProvider); } @@ -41,6 +40,10 @@ public ClassProbe getClassProbe() { return classProbe; } + @SuppressFBWarnings( + value = "EI_EXPOSE_REP", + justification = "VintageValueProvider can use a mutable cache." + ) public ValueProvider getValueProvider() { return valueProvider; } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index 796ee7dec..1caad144b 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -7,10 +7,11 @@ import com.tngtech.archunit.lang.ArchRule; import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProviderCreatorTest; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProviderTest; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.FieldModifier; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.util.Context; import nl.jqno.equalsverifier.internal.util.PrefabValuesApi; import nl.jqno.equalsverifier.testhelpers.FactoryCacheFactory; @@ -26,7 +27,10 @@ public final class ArchitectureTest { Context.class, PrefabValuesApi.class, JavaApiPrefabValues.class, - FactoryCacheFactory.class + // 👇 Test classes + FactoryCacheFactory.class, + VintageValueProviderTest.class, + VintageValueProviderCreatorTest.class ) .and() .resideOutsideOfPackage("nl.jqno.equalsverifier.internal.reflection.vintage..") @@ -46,10 +50,7 @@ public final class ArchitectureTest { .areAssignableTo(ObjectAccessor.class) .orShould() .accessClassesThat() - .areAssignableTo(FieldModifier.class) - .orShould() - .accessClassesThat() - .areAssignableTo(PrefabValues.class); + .areAssignableTo(FieldModifier.class); @ArchTest public static final ArchRule APACHE_COMMONS = noClasses() diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderCreatorTest.java similarity index 68% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderCreatorTest.java index c04a67713..d95680d10 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesCreatorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderCreatorTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage; +package nl.jqno.equalsverifier.internal.reflection.instantiation; import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import static org.junit.jupiter.api.Assertions.*; @@ -6,7 +6,6 @@ import nl.jqno.equalsverifier.internal.exceptions.RecursionException; import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.FactoryCacheFactory; import nl.jqno.equalsverifier.testhelpers.types.Point; @@ -17,7 +16,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class PrefabValuesCreatorTest { +public class VintageValueProviderCreatorTest { private static final TypeTag POINT_TAG = new TypeTag(Point.class); private static final TypeTag ENUM_TAG = new TypeTag(Enum.class); @@ -29,59 +28,59 @@ public class PrefabValuesCreatorTest { private static final TypeTag TWOSTEP_NODE_ARRAY_A_TAG = new TypeTag(TwoStepNodeArrayA.class); private FactoryCache factoryCache; - private PrefabValues prefabValues; + private VintageValueProvider valueProvider; @BeforeEach public void setup() { factoryCache = FactoryCacheFactory.withPrimitiveFactories(); - prefabValues = new PrefabValues(factoryCache); + valueProvider = new VintageValueProvider(factoryCache); } @Test public void simple() { - Point red = prefabValues.giveRed(POINT_TAG); - Point blue = prefabValues.giveBlue(POINT_TAG); + Point red = valueProvider.giveRed(POINT_TAG); + Point blue = valueProvider.giveBlue(POINT_TAG); assertFalse(red.equals(blue)); } @Test public void createSecondTimeIsNoOp() { - Point red = prefabValues.giveRed(POINT_TAG); - Point blue = prefabValues.giveBlue(POINT_TAG); + Point red = valueProvider.giveRed(POINT_TAG); + Point blue = valueProvider.giveBlue(POINT_TAG); - assertSame(red, prefabValues.giveRed(POINT_TAG)); - assertSame(blue, prefabValues.giveBlue(POINT_TAG)); + assertSame(red, valueProvider.giveRed(POINT_TAG)); + assertSame(blue, valueProvider.giveBlue(POINT_TAG)); } @Test public void createEnum() { - assertNotNull(prefabValues.giveRed(ENUM_TAG)); - assertNotNull(prefabValues.giveBlue(ENUM_TAG)); + assertNotNull(valueProvider.giveRed(ENUM_TAG)); + assertNotNull(valueProvider.giveBlue(ENUM_TAG)); } @Test public void createOneElementEnum() { - assertNotNull(prefabValues.giveRed(ONE_ELT_ENUM_TAG)); - assertNotNull(prefabValues.giveBlue(ONE_ELT_ENUM_TAG)); + assertNotNull(valueProvider.giveRed(ONE_ELT_ENUM_TAG)); + assertNotNull(valueProvider.giveBlue(ONE_ELT_ENUM_TAG)); } @Test public void createEmptyEnum() { - assertNull(prefabValues.giveRed(EMPTY_ENUM_TAG)); - assertNull(prefabValues.giveBlue(EMPTY_ENUM_TAG)); + assertNull(valueProvider.giveRed(EMPTY_ENUM_TAG)); + assertNull(valueProvider.giveBlue(EMPTY_ENUM_TAG)); } @Test public void oneStepRecursiveType() { factoryCache.put(Node.class, values(new Node(), new Node(), new Node())); - prefabValues = new PrefabValues(factoryCache); - prefabValues.giveRed(NODE_TAG); + valueProvider = new VintageValueProvider(factoryCache); + valueProvider.giveRed(NODE_TAG); } @Test public void dontAddOneStepRecursiveType() { ExpectedException - .when(() -> prefabValues.giveRed(NODE_TAG)) + .when(() -> valueProvider.giveRed(NODE_TAG)) .assertThrows(RecursionException.class); } @@ -91,14 +90,14 @@ public void oneStepRecursiveArrayType() { NodeArray.class, values(new NodeArray(), new NodeArray(), new NodeArray()) ); - prefabValues = new PrefabValues(factoryCache); - prefabValues.giveRed(NODE_ARRAY_TAG); + valueProvider = new VintageValueProvider(factoryCache); + valueProvider.giveRed(NODE_ARRAY_TAG); } @Test public void dontAddOneStepRecursiveArrayType() { ExpectedException - .when(() -> prefabValues.giveRed(NODE_ARRAY_TAG)) + .when(() -> valueProvider.giveRed(NODE_ARRAY_TAG)) .assertThrows(RecursionException.class); } @@ -108,14 +107,14 @@ public void addTwoStepRecursiveType() { TwoStepNodeB.class, values(new TwoStepNodeB(), new TwoStepNodeB(), new TwoStepNodeB()) ); - prefabValues = new PrefabValues(factoryCache); - prefabValues.giveRed(TWOSTEP_NODE_A_TAG); + valueProvider = new VintageValueProvider(factoryCache); + valueProvider.giveRed(TWOSTEP_NODE_A_TAG); } @Test public void dontAddTwoStepRecursiveType() { ExpectedException - .when(() -> prefabValues.giveRed(TWOSTEP_NODE_A_TAG)) + .when(() -> valueProvider.giveRed(TWOSTEP_NODE_A_TAG)) .assertThrows(RecursionException.class); } @@ -125,26 +124,26 @@ public void twoStepRecursiveArrayType() { TwoStepNodeArrayB.class, values(new TwoStepNodeArrayB(), new TwoStepNodeArrayB(), new TwoStepNodeArrayB()) ); - prefabValues = new PrefabValues(factoryCache); - prefabValues.giveRed(TWOSTEP_NODE_ARRAY_A_TAG); + valueProvider = new VintageValueProvider(factoryCache); + valueProvider.giveRed(TWOSTEP_NODE_ARRAY_A_TAG); } @Test public void dontAddTwoStepRecursiveArrayType() { ExpectedException - .when(() -> prefabValues.giveRed(TWOSTEP_NODE_ARRAY_A_TAG)) + .when(() -> valueProvider.giveRed(TWOSTEP_NODE_ARRAY_A_TAG)) .assertThrows(RecursionException.class); } @Test public void sameClassTwiceButNoRecursion() { - prefabValues.giveRed(new TypeTag(NotRecursiveA.class)); + valueProvider.giveRed(new TypeTag(NotRecursiveA.class)); } @Test public void recursiveWithAnotherFieldFirst() { ExpectedException - .when(() -> prefabValues.giveRed(new TypeTag(RecursiveWithAnotherFieldFirst.class))) + .when(() -> valueProvider.giveRed(new TypeTag(RecursiveWithAnotherFieldFirst.class))) .assertThrows(RecursionException.class) .assertDescriptionContains(RecursiveWithAnotherFieldFirst.class.getSimpleName()) .assertDescriptionDoesNotContain(RecursiveThisIsTheOtherField.class.getSimpleName()); @@ -153,7 +152,7 @@ public void recursiveWithAnotherFieldFirst() { @Test public void exceptionMessage() { ExpectedException - .when(() -> prefabValues.giveRed(TWOSTEP_NODE_A_TAG)) + .when(() -> valueProvider.giveRed(TWOSTEP_NODE_A_TAG)) .assertThrows(RecursionException.class) .assertDescriptionContains( TwoStepNodeA.class.getSimpleName(), @@ -163,7 +162,7 @@ public void exceptionMessage() { @Test public void skipStaticFinal() { - prefabValues.giveRed(new TypeTag(StaticFinalContainer.class)); + valueProvider.giveRed(new TypeTag(StaticFinalContainer.class)); } static class StaticFinalContainer { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java similarity index 76% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java index 6d17f39a6..a39bbd787 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/PrefabValuesTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java @@ -1,4 +1,4 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage; +package nl.jqno.equalsverifier.internal.reflection.instantiation; import static nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories.values; import static nl.jqno.equalsverifier.internal.testhelpers.Util.defaultEquals; @@ -13,27 +13,26 @@ import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.testhelpers.types.Point; import nl.jqno.equalsverifier.testhelpers.types.ThrowingInitializer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class PrefabValuesTest { +public class VintageValueProviderTest { private static final TypeTag STRING_TAG = new TypeTag(String.class); private static final TypeTag POINT_TAG = new TypeTag(Point.class); private static final TypeTag INT_TAG = new TypeTag(int.class); private FactoryCache factoryCache = new FactoryCache(); - private PrefabValues pv; + private VintageValueProvider vp; @BeforeEach public void setUp() { factoryCache.put(String.class, new AppendingStringTestFactory()); factoryCache.put(int.class, values(42, 1337, 42)); - pv = new PrefabValues(factoryCache); + vp = new VintageValueProvider(factoryCache); } @Test @@ -46,78 +45,78 @@ public void sanityTestFactoryIncreasesStringLength() { @Test public void giveRedFromFactory() { - assertEquals("r", pv.giveRed(STRING_TAG)); + assertEquals("r", vp.giveRed(STRING_TAG)); } @Test public void giveRedFromCache() { - pv.giveRed(STRING_TAG); - assertEquals("r", pv.giveRed(STRING_TAG)); + vp.giveRed(STRING_TAG); + assertEquals("r", vp.giveRed(STRING_TAG)); } @Test public void giveBlueFromFactory() { - assertEquals("b", pv.giveBlue(STRING_TAG)); + assertEquals("b", vp.giveBlue(STRING_TAG)); } @Test public void giveBlueFromCache() { - pv.giveBlue(STRING_TAG); - assertEquals("b", pv.giveBlue(STRING_TAG)); + vp.giveBlue(STRING_TAG); + assertEquals("b", vp.giveBlue(STRING_TAG)); } @Test public void giveRedCopyFromFactory() { - assertEquals("r", pv.giveRedCopy(STRING_TAG)); - assertNotSame(pv.giveRed(STRING_TAG), pv.giveRedCopy(STRING_TAG)); + assertEquals("r", vp.giveRedCopy(STRING_TAG)); + assertNotSame(vp.giveRed(STRING_TAG), vp.giveRedCopy(STRING_TAG)); } @Test public void giveRedCopyFromCache() { - pv.giveRedCopy(STRING_TAG); - assertEquals("r", pv.giveRedCopy(STRING_TAG)); - assertNotSame(pv.giveRed(STRING_TAG), pv.giveRedCopy(STRING_TAG)); + vp.giveRedCopy(STRING_TAG); + assertEquals("r", vp.giveRedCopy(STRING_TAG)); + assertNotSame(vp.giveRed(STRING_TAG), vp.giveRedCopy(STRING_TAG)); } @Test public void giveRedFromFallbackFactory() { - Point actual = pv.giveRed(POINT_TAG); + Point actual = vp.giveRed(POINT_TAG); assertEquals(new Point(42, 42), actual); } @Test public void giveBlueFromFallbackFactory() { - Point actual = pv.giveBlue(POINT_TAG); + Point actual = vp.giveBlue(POINT_TAG); assertEquals(new Point(1337, 1337), actual); } @Test public void giveRedCopyFromFallbackFactory() { - Point actual = pv.giveRedCopy(POINT_TAG); + Point actual = vp.giveRedCopy(POINT_TAG); assertEquals(new Point(42, 42), actual); - assertNotSame(pv.giveRed(POINT_TAG), actual); + assertNotSame(vp.giveRed(POINT_TAG), actual); } @Test public void giveTuple() { - Tuple actual = pv.giveTuple(POINT_TAG); + Tuple actual = vp.giveTuple(POINT_TAG); assertEquals(Tuple.of(new Point(42, 42), new Point(1337, 1337), new Point(42, 42)), actual); } @Test public void fallbackDoesNotAffectStaticFields() { int expected = StaticContainer.staticInt; - pv.giveRed(new TypeTag(StaticContainer.class)); + vp.giveRed(new TypeTag(StaticContainer.class)); assertEquals(expected, StaticContainer.staticInt); } @Test public void stringListIsSeparateFromIntegerList() { factoryCache.put(List.class, new ListTestFactory()); - pv = new PrefabValues(factoryCache); + vp = new VintageValueProvider(factoryCache); - List strings = pv.giveRed(new TypeTag(List.class, STRING_TAG)); - List ints = pv.giveRed(new TypeTag(List.class, INT_TAG)); + List strings = vp.giveRed(new TypeTag(List.class, STRING_TAG)); + List ints = vp.giveRed(new TypeTag(List.class, INT_TAG)); assertEquals("r", strings.get(0)); assertEquals(42, (int) ints.get(0)); @@ -131,19 +130,19 @@ public void addingNullDoesntBreakAnything() { @Test public void addingATypeTwiceOverrulesTheExistingOne() { factoryCache.put(int.class, values(-1, -2, -1)); - pv = new PrefabValues(factoryCache); - assertEquals(-1, (int) pv.giveRed(INT_TAG)); - assertEquals(-2, (int) pv.giveBlue(INT_TAG)); + vp = new VintageValueProvider(factoryCache); + assertEquals(-1, (int) vp.giveRed(INT_TAG)); + assertEquals(-2, (int) vp.giveBlue(INT_TAG)); } @Test public void addLazyFactoryWorks() { TypeTag lazyTag = new TypeTag(Lazy.class); factoryCache.put(Lazy.class.getName(), values(Lazy.X, Lazy.Y, Lazy.X)); - pv = new PrefabValues(factoryCache); - assertEquals(Lazy.X, pv.giveRed(lazyTag)); - assertEquals(Lazy.Y, pv.giveBlue(lazyTag)); - assertEquals(Lazy.X, pv.giveRedCopy(lazyTag)); + vp = new VintageValueProvider(factoryCache); + assertEquals(Lazy.X, vp.giveRed(lazyTag)); + assertEquals(Lazy.Y, vp.giveBlue(lazyTag)); + assertEquals(Lazy.X, vp.giveRedCopy(lazyTag)); } @Test @@ -156,11 +155,11 @@ public void addLazyFactoryIsLazy() { (t, p, ts) -> Tuple.of(ThrowingInitializer.X, ThrowingInitializer.Y, ThrowingInitializer.X) ); - pv = new PrefabValues(factoryCache); + vp = new VintageValueProvider(factoryCache); // Should throw, because `giveRed` does instantiate objects: try { - pv.giveRed(throwingInitializerTag); + vp.giveRed(throwingInitializerTag); fail("Expected an exception"); } catch (Error e) { // succeed @@ -203,7 +202,7 @@ public AppendingStringTestFactory() { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { red += "r"; @@ -219,19 +218,19 @@ private static final class ListTestFactory implements PrefabValueFactory { @SuppressWarnings("unchecked") public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { TypeTag subtag = tag.getGenericTypes().get(0); List red = new ArrayList<>(); - red.add(prefabValues.giveRed(subtag)); + red.add(valueProvider.giveRed(subtag)); List blue = new ArrayList<>(); - blue.add(prefabValues.giveBlue(subtag)); + blue.add(valueProvider.giveBlue(subtag)); List redCopy = new ArrayList<>(); - redCopy.add(prefabValues.giveRed(subtag)); + redCopy.add(valueProvider.giveRed(subtag)); return new Tuple<>(red, blue, redCopy); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java index 4cf1ca42c..5c588b924 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java @@ -9,7 +9,7 @@ import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.testhelpers.types.PointContainer; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.TwoStepNodeA; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.TwoStepNodeB; @@ -21,15 +21,15 @@ public class ClassAccessorTest { private LinkedHashSet empty; private FactoryCache factoryCache; - private PrefabValues prefabValues; + private VintageValueProvider valueProvider; private ClassAccessor pointContainerAccessor; @BeforeEach public void setup() { empty = new LinkedHashSet<>(); factoryCache = JavaApiPrefabValues.build(); - prefabValues = new PrefabValues(factoryCache); - pointContainerAccessor = ClassAccessor.of(PointContainer.class, prefabValues); + valueProvider = new VintageValueProvider(factoryCache); + pointContainerAccessor = ClassAccessor.of(PointContainer.class, valueProvider); } @Test @@ -42,7 +42,7 @@ public void getRedObject() { public void getRedObjectGeneric() { ClassAccessor accessor = ClassAccessor.of( GenericTypeVariableListContainer.class, - prefabValues + valueProvider ); GenericTypeVariableListContainer foo = accessor.getRedObject( new TypeTag(GenericTypeVariableListContainer.class, new TypeTag(String.class)), @@ -71,7 +71,7 @@ public void getBlueObject() { public void getBlueObjectGeneric() { ClassAccessor accessor = ClassAccessor.of( GenericTypeVariableListContainer.class, - prefabValues + valueProvider ); GenericTypeVariableListContainer foo = accessor.getBlueObject( new TypeTag(GenericTypeVariableListContainer.class, new TypeTag(String.class)), @@ -99,13 +99,13 @@ public void redAndBlueNotEqual() { @Test public void instantiateAllTypes() { - ClassAccessor.of(AllTypesContainer.class, prefabValues).getRedObject(TypeTag.NULL, empty); + ClassAccessor.of(AllTypesContainer.class, valueProvider).getRedObject(TypeTag.NULL, empty); } @Test public void instantiateArrayTypes() { ClassAccessor - .of(AllArrayTypesContainer.class, prefabValues) + .of(AllArrayTypesContainer.class, valueProvider) .getRedObject(TypeTag.NULL, empty); } @@ -115,25 +115,25 @@ public void instantiateRecursiveTypeUsingPrefabValue() { TwoStepNodeB.class, values(new TwoStepNodeB(), new TwoStepNodeB(), new TwoStepNodeB()) ); - prefabValues = new PrefabValues(factoryCache); - ClassAccessor.of(TwoStepNodeA.class, prefabValues).getRedObject(TypeTag.NULL, empty); + valueProvider = new VintageValueProvider(factoryCache); + ClassAccessor.of(TwoStepNodeA.class, valueProvider).getRedObject(TypeTag.NULL, empty); } @Test public void instantiateInterfaceField() { - ClassAccessor.of(InterfaceContainer.class, prefabValues).getRedObject(TypeTag.NULL, empty); + ClassAccessor.of(InterfaceContainer.class, valueProvider).getRedObject(TypeTag.NULL, empty); } @Test public void instantiateAbstractClassField() { ClassAccessor - .of(AbstractClassContainer.class, prefabValues) + .of(AbstractClassContainer.class, valueProvider) .getRedObject(TypeTag.NULL, empty); } @Test public void anInvalidTypeShouldNotThrowAnExceptionUponCreation() { - ClassAccessor.of(null, prefabValues); + ClassAccessor.of(null, valueProvider); } private void assertObjectHasNoNullFields(PointContainer foo) { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java index 7dc5c7edc..30e67859e 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java @@ -10,7 +10,7 @@ import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.types.Point; import nl.jqno.equalsverifier.testhelpers.types.Point3D; @@ -23,13 +23,13 @@ public class InPlaceObjectAccessorScramblingTest { private static final LinkedHashSet EMPTY_TYPE_STACK = new LinkedHashSet<>(); - private PrefabValues prefabValues; + private VintageValueProvider valueProviderTest; @BeforeEach public void setup() { FactoryCache factoryCache = JavaApiPrefabValues.build(); factoryCache.put(Point.class, values(new Point(1, 2), new Point(2, 3), new Point(1, 2))); - prefabValues = new PrefabValues(factoryCache); + valueProviderTest = new VintageValueProvider(factoryCache); } @Test @@ -153,7 +153,7 @@ private T copy(T object) { } private ObjectAccessor doScramble(Object object) { - return create(object).scramble(prefabValues, TypeTag.NULL, EMPTY_TYPE_STACK); + return create(object).scramble(valueProviderTest, TypeTag.NULL, EMPTY_TYPE_STACK); } static final class StringContainer { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java index f17641c6d..543342f8b 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java @@ -6,7 +6,6 @@ import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.Cache; import org.junit.jupiter.api.Test; public class CacheTest { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactoryTest.java index 591a635d4..e0a2263fd 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/AbstractGenericFactoryTest.java @@ -8,8 +8,7 @@ import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.AbstractGenericFactory; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -26,7 +25,7 @@ public void setUp() { @Override public Tuple createValues( TypeTag tag, - PrefabValues prefabValues, + VintageValueProvider valueProvider, LinkedHashSet typeStack ) { return Tuple.of("red", "blue", new String("red")); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FactoriesTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FactoriesTest.java index a8f805f77..98337dd5a 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FactoriesTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FactoriesTest.java @@ -2,7 +2,6 @@ import static nl.jqno.equalsverifier.internal.testhelpers.Util.coverThePrivateConstructor; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories; import org.junit.jupiter.api.Test; public class FactoriesTest { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java index 70f81b50b..2af38cf09 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java @@ -11,8 +11,7 @@ import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.FallbackFactory; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.Node; import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.NodeArray; @@ -26,7 +25,7 @@ public class FallbackFactoryTest { private FallbackFactory factory; - private PrefabValues prefabValues; + private VintageValueProvider valueProvider; private LinkedHashSet typeStack; @BeforeEach @@ -34,7 +33,7 @@ public void setUp() { factory = new FallbackFactory<>(); FactoryCache factoryCache = new FactoryCache(); factoryCache.put(int.class, values(42, 1337, 42)); - prefabValues = new PrefabValues(factoryCache); + valueProvider = new VintageValueProvider(factoryCache); typeStack = new LinkedHashSet<>(); } @@ -55,7 +54,7 @@ public void giveMultiElementEnum() { @Test public void giveArray() { - Tuple tuple = factory.createValues(new TypeTag(int[].class), prefabValues, typeStack); + Tuple tuple = factory.createValues(new TypeTag(int[].class), valueProvider, typeStack); assertArrayEquals(new int[] { 42 }, (int[]) tuple.getRed()); assertArrayEquals(new int[] { 1337 }, (int[]) tuple.getBlue()); } @@ -75,7 +74,7 @@ public void giveClassWithFields() { @Test public void dontGiveRecursiveClass() { ExpectedException - .when(() -> factory.createValues(new TypeTag(Node.class), prefabValues, typeStack)) + .when(() -> factory.createValues(new TypeTag(Node.class), valueProvider, typeStack)) .assertThrows(RecursionException.class); } @@ -83,7 +82,7 @@ public void dontGiveRecursiveClass() { public void dontGiveTwoStepRecursiveClass() { ExpectedException .when(() -> - factory.createValues(new TypeTag(TwoStepNodeA.class), prefabValues, typeStack) + factory.createValues(new TypeTag(TwoStepNodeA.class), valueProvider, typeStack) ) .assertThrows(RecursionException.class) .assertDescriptionContains("TwoStepNodeA", "TwoStepNodeB"); @@ -92,12 +91,13 @@ public void dontGiveTwoStepRecursiveClass() { @Test public void dontGiveRecursiveArray() { ExpectedException - .when(() -> factory.createValues(new TypeTag(NodeArray.class), prefabValues, typeStack)) + .when(() -> factory.createValues(new TypeTag(NodeArray.class), valueProvider, typeStack) + ) .assertThrows(RecursionException.class); } private void assertCorrectTuple(Class type, T expectedRed, T expectedBlue) { - Tuple tuple = factory.createValues(new TypeTag(type), prefabValues, typeStack); + Tuple tuple = factory.createValues(new TypeTag(type), valueProvider, typeStack); assertEquals(expectedRed, tuple.getRed()); assertEquals(expectedBlue, tuple.getBlue()); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java index 83202f4ee..5b67f1674 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java @@ -8,8 +8,7 @@ import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.MapFactory; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.OneElementEnum; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -40,7 +39,7 @@ public class MapFactoryTest { private static final MapFactory MAP_FACTORY = new MapFactory<>(HashMap::new); private final LinkedHashSet typeStack = new LinkedHashSet<>(); - private PrefabValues prefabValues; + private VintageValueProvider valueProvider; private String red; private String blue; private Object redObject; @@ -49,19 +48,19 @@ public class MapFactoryTest { @BeforeEach public void setUp() { - prefabValues = new PrefabValues(JavaApiPrefabValues.build()); - red = prefabValues.giveRed(STRING_TYPETAG); - blue = prefabValues.giveBlue(STRING_TYPETAG); - redObject = prefabValues.giveRed(OBJECT_TYPETAG); - blueObject = prefabValues.giveBlue(OBJECT_TYPETAG); - redEnum = prefabValues.giveBlue(ONEELEMENTENUM_TYPETAG); + valueProvider = new VintageValueProvider(JavaApiPrefabValues.build()); + red = valueProvider.giveRed(STRING_TYPETAG); + blue = valueProvider.giveBlue(STRING_TYPETAG); + redObject = valueProvider.giveRed(OBJECT_TYPETAG); + blueObject = valueProvider.giveBlue(OBJECT_TYPETAG); + redEnum = valueProvider.giveBlue(ONEELEMENTENUM_TYPETAG); } @Test public void createMapsOfStringToString() { Tuple tuple = MAP_FACTORY.createValues( STRINGSTRINGMAP_TYPETAG, - prefabValues, + valueProvider, typeStack ); assertEquals(mapOf(red, blue), tuple.getRed()); @@ -70,14 +69,14 @@ public void createMapsOfStringToString() { @Test public void createMapsOfWildcard() { - Tuple tuple = MAP_FACTORY.createValues(WILDCARDMAP_TYPETAG, prefabValues, typeStack); + Tuple tuple = MAP_FACTORY.createValues(WILDCARDMAP_TYPETAG, valueProvider, typeStack); assertEquals(mapOf(redObject, blueObject), tuple.getRed()); assertEquals(mapOf(blueObject, blueObject), tuple.getBlue()); } @Test public void createRawMaps() { - Tuple tuple = MAP_FACTORY.createValues(RAWMAP_TYPETAG, prefabValues, typeStack); + Tuple tuple = MAP_FACTORY.createValues(RAWMAP_TYPETAG, valueProvider, typeStack); assertEquals(mapOf(redObject, blueObject), tuple.getRed()); assertEquals(mapOf(blueObject, blueObject), tuple.getBlue()); } @@ -86,7 +85,7 @@ public void createRawMaps() { public void createMapOfOneElementEnumKey() { Tuple tuple = MAP_FACTORY.createValues( ONEELEMENTENUMKEYMAP_TYPETAG, - prefabValues, + valueProvider, typeStack ); assertEquals(mapOf(redEnum, blueObject), tuple.getRed()); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactoryTest.java index b235c290b..3adabc58f 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleFactoryTest.java @@ -3,7 +3,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotSame; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.SimpleFactory; import org.junit.jupiter.api.Test; public class SimpleFactoryTest { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java index d33dcff08..e7d69dc49 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java @@ -7,9 +7,7 @@ import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.Factories; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.testhelpers.types.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -42,7 +40,7 @@ public class SimpleGenericFactoryTest { private static final PrefabValueFactory PAIR_FACTORY = Factories.simple(Pair::new, null); private final LinkedHashSet typeStack = new LinkedHashSet<>(); - private PrefabValues prefabValues; + private VintageValueProvider valueProvider; private String redString; private String blueString; private Integer redInt; @@ -52,20 +50,20 @@ public class SimpleGenericFactoryTest { @BeforeEach public void setUp() { - prefabValues = new PrefabValues(JavaApiPrefabValues.build()); - redString = prefabValues.giveRed(STRING_TYPETAG); - blueString = prefabValues.giveBlue(STRING_TYPETAG); - redInt = prefabValues.giveRed(INTEGER_TYPETAG); - blueInt = prefabValues.giveBlue(INTEGER_TYPETAG); - redObject = prefabValues.giveRed(OBJECT_TYPETAG); - blueObject = prefabValues.giveBlue(OBJECT_TYPETAG); + valueProvider = new VintageValueProvider(JavaApiPrefabValues.build()); + redString = valueProvider.giveRed(STRING_TYPETAG); + blueString = valueProvider.giveBlue(STRING_TYPETAG); + redInt = valueProvider.giveRed(INTEGER_TYPETAG); + blueInt = valueProvider.giveBlue(INTEGER_TYPETAG); + redObject = valueProvider.giveRed(OBJECT_TYPETAG); + blueObject = valueProvider.giveBlue(OBJECT_TYPETAG); } @Test public void createOptionalsOfMapOfString() { Tuple tuple = OPTIONAL_FACTORY.createValues( STRINGOPTIONAL_TYPETAG, - prefabValues, + valueProvider, typeStack ); assertEquals(Optional.of(redString), tuple.getRed()); @@ -76,7 +74,7 @@ public void createOptionalsOfMapOfString() { public void createOptionalsOfWildcard() { Tuple tuple = OPTIONAL_FACTORY.createValues( WILDCARDOPTIONAL_TYPETAG, - prefabValues, + valueProvider, typeStack ); assertEquals(Optional.of(redObject), tuple.getRed()); @@ -87,7 +85,7 @@ public void createOptionalsOfWildcard() { public void createRawOptionals() { Tuple tuple = OPTIONAL_FACTORY.createValues( RAWOPTIONAL_TYPETAG, - prefabValues, + valueProvider, typeStack ); assertEquals(Optional.of(redObject), tuple.getRed()); @@ -96,7 +94,7 @@ public void createRawOptionals() { @Test public void createSomethingWithMoreThanOneTypeParameter() { - Tuple tuple = PAIR_FACTORY.createValues(PAIR_TYPETAG, prefabValues, typeStack); + Tuple tuple = PAIR_FACTORY.createValues(PAIR_TYPETAG, valueProvider, typeStack); assertEquals(new Pair<>(redString, redInt), tuple.getRed()); assertEquals(new Pair<>(blueString, blueInt), tuple.getBlue()); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java index a346df248..f3612ccf7 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java @@ -8,9 +8,8 @@ import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.PrefabValues; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders.JavaFxFactoryProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factoryproviders.JavaFxFactoryProvider.PropertyFactory; import nl.jqno.equalsverifier.testhelpers.types.Point; import org.junit.jupiter.api.BeforeEach; @@ -19,11 +18,11 @@ @SuppressWarnings("rawtypes") public class JavaFxFactoryProviderTest { - private PrefabValues prefabValues; + private VintageValueProvider valueProvider; @BeforeEach public void setUp() { - prefabValues = new PrefabValues(JavaApiPrefabValues.build()); + valueProvider = new VintageValueProvider(JavaApiPrefabValues.build()); } @Test @@ -40,10 +39,10 @@ public void createInstancesWithCorrectSingleGenericParameter() { GenericContainer.class.getName(), List.class ); - Tuple tuple = factory.createValues(tag, prefabValues, null); + Tuple tuple = factory.createValues(tag, valueProvider, null); - assertEquals(prefabValues.giveRed(listTag), tuple.getRed().t); - assertEquals(prefabValues.giveBlue(listTag), tuple.getBlue().t); + assertEquals(valueProvider.giveRed(listTag), tuple.getRed().t); + assertEquals(valueProvider.giveBlue(listTag), tuple.getBlue().t); assertEquals(String.class, tuple.getRed().t.get(0).getClass()); } @@ -64,10 +63,10 @@ public void createInstancesWithCorrectMultipleGenericParameter() { GenericMultiContainer.class.getName(), Map.class ); - Tuple tuple = factory.createValues(tag, prefabValues, null); + Tuple tuple = factory.createValues(tag, valueProvider, null); - assertEquals(prefabValues.giveRed(mapTag), tuple.getRed().t); - assertEquals(prefabValues.giveBlue(mapTag), tuple.getBlue().t); + assertEquals(valueProvider.giveRed(mapTag), tuple.getRed().t); + assertEquals(valueProvider.giveBlue(mapTag), tuple.getBlue().t); Map.Entry next = (Map.Entry) tuple.getRed().t.entrySet().iterator().next(); assertEquals(String.class, next.getKey().getClass()); From 3f9a54145fe233e7ab57707022d29f3823614fc5 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 15:06:28 +0200 Subject: [PATCH 51/74] Restores coverage threshold --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0c7631213..4a5a69a64 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ ${argline.module} ${argline.preview} ${argline.experimental} - 0.94 + 0.95 checkstyle-config.xml Max Low From 256f77f2195198b251b61282b3f909df0a07637c Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 16 Sep 2024 19:48:11 +0200 Subject: [PATCH 52/74] Adds fieldCache to SubjectCreator --- .../internal/reflection/instantiation/SubjectCreator.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java index dcf99d0a3..bc45558e1 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java @@ -17,6 +17,7 @@ public class SubjectCreator { private final Configuration config; private final ValueProvider valueProvider; private final ClassProbe classProbe; + private final Map> fieldCache = new HashMap<>(); public SubjectCreator(TypeTag typeTag, Configuration config, ValueProvider valueProvider) { this.typeTag = typeTag; @@ -158,6 +159,11 @@ private FieldIterable nonSuperFields() { } private Tuple valuesFor(Field f) { - return valueProvider.provide(TypeTag.of(f, typeTag)); + if (fieldCache.containsKey(f)) { + return fieldCache.get(f); + } + Tuple tuple = valueProvider.provide(TypeTag.of(f, typeTag)); + fieldCache.put(f, tuple); + return tuple; } } From 6b76d724318400dfdef604515535dd00ce5082d4 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Tue, 17 Sep 2024 09:19:13 +0200 Subject: [PATCH 53/74] Replaces Cache class with HashMap --- .../instantiation/VintageValueProvider.java | 19 +++--- .../vintage/prefabvalues/Cache.java | 52 ---------------- .../vintage/prefabvalues/CacheTest.java | 60 ------------------- 3 files changed, 8 insertions(+), 123 deletions(-) delete mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java delete mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java index 33b7056ac..bd63d3231 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java @@ -1,22 +1,22 @@ package nl.jqno.equalsverifier.internal.reflection.instantiation; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.util.Arrays; -import java.util.LinkedHashSet; +import java.util.*; import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.exceptions.RecursionException; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.Cache; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.FallbackFactory; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; public class VintageValueProvider implements ValueProvider { - private final Cache cache = new Cache(); + // I'd like to remove this, but that affects recursion detection it a way I can't yet explain + private final Map> valueCache = new HashMap<>(); + private final FactoryCache factoryCache; private final PrefabValueFactory fallbackFactory = new FallbackFactory<>(); @@ -105,9 +105,10 @@ public Tuple giveTuple(TypeTag tag) { * @param typeStack Keeps track of recursion in the type. * @return A tuple of two different values of the given type. */ + @SuppressWarnings("unchecked") public Tuple giveTuple(TypeTag tag, LinkedHashSet typeStack) { realizeCacheFor(tag, typeStack); - return cache.getTuple(tag); + return (Tuple) valueCache.get(tag); } /** @@ -171,9 +172,9 @@ private boolean arraysAreDeeplyEqual(Object x, Object y) { * @param typeStack Keeps track of recursion in the type. */ public void realizeCacheFor(TypeTag tag, LinkedHashSet typeStack) { - if (!cache.contains(tag)) { + if (!valueCache.containsKey(tag)) { Tuple tuple = createTuple(tag, typeStack); - addToCache(tag, tuple); + valueCache.put(tag, tuple); } } @@ -192,8 +193,4 @@ private Tuple createTuple(TypeTag tag, LinkedHashSet typeStack) Tuple result = (Tuple) fallbackFactory.createValues(tag, this, typeStack); return result; } - - private void addToCache(TypeTag tag, Tuple tuple) { - cache.put(tag, tuple.getRed(), tuple.getBlue(), tuple.getRedCopy()); - } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java deleted file mode 100644 index a3f3dc049..000000000 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/Cache.java +++ /dev/null @@ -1,52 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues; - -import java.util.HashMap; -import java.util.Map; -import nl.jqno.equalsverifier.internal.reflection.Tuple; -import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; - -/** Contains a cache of prefabricated values, for {@link VintageValueProvider}. */ -public class Cache { - - @SuppressWarnings("rawtypes") - private final Map cache = new HashMap<>(); - - /** - * Adds a prefabricated value to the cache for the given type. - * - * @param tag A description of the type. Takes generics into account. - * @param red A "red" value for the given type. - * @param blue A "blue" value for the given type. - * @param redCopy A shallow copy of the given red value. - * @param The type of given tag. - */ - public void put(TypeTag tag, T red, T blue, T redCopy) { - cache.put(tag, new Tuple<>(red, blue, redCopy)); - } - - /** - * Returns a {@link Tuple} of prefabricated values for the specified type. - * - *

What happens when there is no value, is undefined. Always call {@link #contains(TypeTag)} - * first. - * - * @param tag A description of the type. Takes generics into account. - * @param the type of the Tuple. - * @return Tuple of type T. - */ - @SuppressWarnings("unchecked") - public Tuple getTuple(TypeTag tag) { - return cache.get(tag); - } - - /** - * Returns whether prefabricated values are available for the given type. - * - * @param tag A description of the type. Takes generics into account. - * @return true if prefabricated values are available. - */ - public boolean contains(TypeTag tag) { - return cache.containsKey(tag); - } -} diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java deleted file mode 100644 index 543342f8b..000000000 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/CacheTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import nl.jqno.equalsverifier.internal.reflection.Tuple; -import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import org.junit.jupiter.api.Test; - -public class CacheTest { - - private static final TypeTag STRING_TAG = new TypeTag(String.class); - private static final Tuple STRING_TUPLE = new Tuple<>("red", "blue", new String("red")); - private static final TypeTag INT_TAG = new TypeTag(int.class); - private static final Tuple INT_TUPLE = new Tuple<>(42, 1337, 42); - - private Cache cache = new Cache(); - - @Test - public void putAndGetTuple() { - cache.put( - STRING_TAG, - STRING_TUPLE.getRed(), - STRING_TUPLE.getBlue(), - STRING_TUPLE.getRedCopy() - ); - assertEquals(STRING_TUPLE, cache.getTuple(STRING_TAG)); - } - - @Test - public void putTwiceAndGetBoth() { - cache.put( - STRING_TAG, - STRING_TUPLE.getRed(), - STRING_TUPLE.getBlue(), - STRING_TUPLE.getRedCopy() - ); - cache.put(INT_TAG, INT_TUPLE.getRed(), INT_TUPLE.getBlue(), INT_TUPLE.getRedCopy()); - - assertEquals(INT_TUPLE, cache.getTuple(INT_TAG)); - assertEquals(STRING_TUPLE, cache.getTuple(STRING_TAG)); - } - - @Test - public void contains() { - cache.put( - STRING_TAG, - STRING_TUPLE.getRed(), - STRING_TUPLE.getBlue(), - STRING_TUPLE.getRedCopy() - ); - assertTrue(cache.contains(STRING_TAG)); - } - - @Test - public void doesntContain() { - assertFalse(cache.contains(STRING_TAG)); - } -} From 27b9b439ddf2e2fc361046df5ed9b3021806bcfe Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Tue, 17 Sep 2024 09:58:16 +0200 Subject: [PATCH 54/74] Moves FactoryCacheTest to correct package --- .../equalsverifier/internal/architecture/ArchitectureTest.java | 2 ++ .../{vintage/prefabvalues => }/FactoryCacheTest.java | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) rename equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/{vintage/prefabvalues => }/FactoryCacheTest.java (92%) diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java index 1caad144b..b7461f4e9 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/architecture/ArchitectureTest.java @@ -5,6 +5,7 @@ import com.tngtech.archunit.junit.AnalyzeClasses; import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchRule; +import nl.jqno.equalsverifier.internal.reflection.FactoryCacheTest; import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProviderCreatorTest; @@ -29,6 +30,7 @@ public final class ArchitectureTest { JavaApiPrefabValues.class, // 👇 Test classes FactoryCacheFactory.class, + FactoryCacheTest.class, VintageValueProviderTest.class, VintageValueProviderCreatorTest.class ) diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/FactoryCacheTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FactoryCacheTest.java similarity index 92% rename from equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/FactoryCacheTest.java rename to equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FactoryCacheTest.java index f6f91b7d2..f8f9a1b2f 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/FactoryCacheTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FactoryCacheTest.java @@ -1,8 +1,7 @@ -package nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues; +package nl.jqno.equalsverifier.internal.reflection; import static org.junit.jupiter.api.Assertions.*; -import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.SimpleFactory; import org.junit.jupiter.api.Test; From cf8d1515affc3d5f8090937266eccd3fe5f8f3eb Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Tue, 17 Sep 2024 10:18:53 +0200 Subject: [PATCH 55/74] Introduces proper FieldCache --- .../internal/reflection/FactoryCache.java | 11 +--- .../internal/reflection/FieldCache.java | 54 +++++++++++++++++++ .../instantiation/SubjectCreator.java | 15 +++--- .../internal/reflection/FactoryCacheTest.java | 18 +++++++ .../internal/reflection/FieldCacheTest.java | 48 +++++++++++++++++ 5 files changed, 128 insertions(+), 18 deletions(-) create mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldCache.java create mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldCacheTest.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java index 97f3f191e..1d77eabdd 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FactoryCache.java @@ -1,13 +1,12 @@ package nl.jqno.equalsverifier.internal.reflection; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; /** Contains a cache of factories, for {@link VintageValueProvider}. */ -public class FactoryCache implements Iterable>> { +public class FactoryCache { /** * We store Strings instead of Classes, so that the cache can be lazy and initializers won't be @@ -82,14 +81,8 @@ public FactoryCache merge(FactoryCache other) { } private void copy(FactoryCache to, FactoryCache from) { - for (Map.Entry> entry : from) { + for (Map.Entry> entry : from.cache.entrySet()) { to.put(entry.getKey(), entry.getValue()); } } - - /** Provides an iterator over all available factories. */ - @Override - public Iterator>> iterator() { - return cache.entrySet().iterator(); - } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldCache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldCache.java new file mode 100644 index 000000000..57a0355e2 --- /dev/null +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldCache.java @@ -0,0 +1,54 @@ +package nl.jqno.equalsverifier.internal.reflection; + +import java.util.HashMap; +import java.util.Map; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; + +/** Contains a cache for values connected to specific fields, for {@link SubjectCreator}. */ +public class FieldCache { + + /** + * We store Strings instead of Fields, to make it easier to interact with when we don't + * actually have a reference to a Field. + */ + private final Map> cache = new HashMap<>(); + + /** + * Adds the given factory to the cache and associates it with the given type. + * + * @param The type of the values. + * @param fieldName The name of the field to associate with the values. + * @param tuple The tuple that contains the values. + */ + public void put(String fieldName, Tuple tuple) { + if (fieldName != null) { + cache.put(fieldName, tuple); + } + } + + /** + * Retrieves the values from the cache for the given field. + * + *

What happens when there are no values, is undefined. Always call {@link #contains(String)} + * first. + * + * @param The returned values will have this as generic type. + * @param fieldName The name of the field for which values are needed. + * @return A tuple of values for the given type, or {@code null} if none is available. + */ + @SuppressWarnings("unchecked") + public Tuple get(String fieldName) { + if (fieldName == null) { + return null; + } + return (Tuple) cache.get(fieldName); + } + + /** + * @param fieldName The name of the field for which values are needed. + * @return Whether values are available for the given field. + */ + public boolean contains(String fieldName) { + return cache.containsKey(fieldName); + } +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java index bc45558e1..a50b8f547 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java @@ -3,11 +3,7 @@ import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; -import nl.jqno.equalsverifier.internal.reflection.ClassProbe; -import nl.jqno.equalsverifier.internal.reflection.FieldIterable; -import nl.jqno.equalsverifier.internal.reflection.FieldProbe; -import nl.jqno.equalsverifier.internal.reflection.Tuple; -import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.*; import nl.jqno.equalsverifier.internal.util.Configuration; public class SubjectCreator { @@ -17,7 +13,7 @@ public class SubjectCreator { private final Configuration config; private final ValueProvider valueProvider; private final ClassProbe classProbe; - private final Map> fieldCache = new HashMap<>(); + private final FieldCache fieldCache = new FieldCache(); public SubjectCreator(TypeTag typeTag, Configuration config, ValueProvider valueProvider) { this.typeTag = typeTag; @@ -159,11 +155,12 @@ private FieldIterable nonSuperFields() { } private Tuple valuesFor(Field f) { - if (fieldCache.containsKey(f)) { - return fieldCache.get(f); + String fieldName = f.getName(); + if (fieldCache.contains(fieldName)) { + return fieldCache.get(fieldName); } Tuple tuple = valueProvider.provide(TypeTag.of(f, typeTag)); - fieldCache.put(f, tuple); + fieldCache.put(fieldName, tuple); return tuple; } } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FactoryCacheTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FactoryCacheTest.java index f8f9a1b2f..bbe20d280 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FactoryCacheTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FactoryCacheTest.java @@ -54,4 +54,22 @@ public void contains() { public void doesntContain() { assertFalse(cache.contains(STRING_CLASS)); } + + @Test + public void merge() { + FactoryCache a = new FactoryCache(); + a.put(STRING_CLASS, STRING_FACTORY); + + FactoryCache b = new FactoryCache(); + b.put(INT_CLASS, INT_FACTORY); + + FactoryCache combined = a.merge(b); + + assertTrue(combined.contains(STRING_CLASS)); + assertTrue(combined.contains(INT_CLASS)); + + assertFalse(a == combined); + assertFalse(a.contains(INT_CLASS)); + assertFalse(b.contains(STRING_CLASS)); + } } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldCacheTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldCacheTest.java new file mode 100644 index 000000000..19b7bd8fb --- /dev/null +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldCacheTest.java @@ -0,0 +1,48 @@ +package nl.jqno.equalsverifier.internal.reflection; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +public class FieldCacheTest { + + private String stringField = "string"; + private final Tuple stringValues = new Tuple<>("red", "blue", "red"); + + private String intField = "int"; + private final Tuple intValues = new Tuple<>(1, 2, 1); + + private FieldCache cache = new FieldCache(); + + @Test + public void putAndGetTuple() { + cache.put(stringField, stringValues); + assertEquals(stringValues, cache.get(stringField)); + } + + @Test + public void putTwiceAndGetBoth() { + cache.put(stringField, stringValues); + cache.put(intField, intValues); + + assertEquals(intValues, cache.get(intField)); + assertEquals(stringValues, cache.get(stringField)); + } + + @Test + public void putNullAndGetNothingBack() { + cache.put(null, stringValues); + assertNull(cache.get(null)); + } + + @Test + public void contains() { + cache.put(stringField, stringValues); + assertTrue(cache.contains(stringField)); + } + + @Test + public void doesntContain() { + assertFalse(cache.contains(stringField)); + } +} From 531324d3f0512e26dfcc4461db8363c8a1a5cda8 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Tue, 17 Sep 2024 14:39:27 +0200 Subject: [PATCH 56/74] Uses SubjectCreator where ValueProvider was inappropriate; fixes exceptions that changed as a result --- .../checkers/AbstractDelegationChecker.java | 8 +++--- .../instantiation/SubjectCreator.java | 25 +++++++++++++++---- .../instantiation/VintageValueProvider.java | 16 ++---------- .../factories/FallbackFactory.java | 25 +------------------ .../equalsverifier/internal/util/Rethrow.java | 10 +++++++- .../InPlaceObjectAccessorScramblingTest.java | 7 ++---- 6 files changed, 39 insertions(+), 52 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java index 8a832753e..ca64fabb1 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/AbstractDelegationChecker.java @@ -8,6 +8,7 @@ import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.util.*; @@ -15,6 +16,7 @@ public class AbstractDelegationChecker implements Checker { private final Class type; private final TypeTag typeTag; + private final SubjectCreator subjectCreator; private final ValueProvider valueProvider; private final ClassProbe classProbe; private final CachedHashCodeInitializer cachedHashCodeInitializer; @@ -23,6 +25,7 @@ public AbstractDelegationChecker(Context context) { Configuration config = context.getConfiguration(); this.type = context.getType(); this.typeTag = config.getTypeTag(); + this.subjectCreator = context.getSubjectCreator(); this.valueProvider = context.getValueProvider(); this.classProbe = context.getClassProbe(); this.cachedHashCodeInitializer = config.getCachedHashCodeInitializer(); @@ -34,9 +37,8 @@ public void check() { checkAbstractDelegationInFields(); - Tuple tuple = valueProvider.provide(typeTag); - T instance = tuple.getRed(); - T copy = tuple.getBlue(); + T instance = subjectCreator.plain(); + T copy = subjectCreator.plain(); checkAbstractDelegation(instance, copy); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java index a50b8f547..ed690067f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java @@ -3,8 +3,10 @@ import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; +import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.reflection.*; import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.Rethrow; public class SubjectCreator { @@ -114,8 +116,8 @@ public S copyIntoSubclass(T original, Class subType) { private T createInstance(Map givens) { Map values = determineValues(givens); - InstanceCreator instaceCreator = new InstanceCreator<>(classProbe); - return instaceCreator.instantiate(values); + InstanceCreator instanceCreator = new InstanceCreator<>(classProbe); + return Rethrow.rethrow(() -> instanceCreator.instantiate(values)); } private Map determineValues(Map givens) { @@ -159,8 +161,21 @@ private Tuple valuesFor(Field f) { if (fieldCache.contains(fieldName)) { return fieldCache.get(fieldName); } - Tuple tuple = valueProvider.provide(TypeTag.of(f, typeTag)); - fieldCache.put(fieldName, tuple); - return tuple; + try { + Tuple tuple = valueProvider.provide(TypeTag.of(f, typeTag)); + fieldCache.put(fieldName, tuple); + return tuple; + } catch (ModuleException e) { + throw new ModuleException( + "Field " + + f.getName() + + " of type " + + f.getType().getName() + + " is not accessible via the Java Module System.\nConsider opening the module that contains it, or add prefab values for type " + + f.getType().getName() + + ".", + e + ); + } } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java index bd63d3231..d25dd520a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java @@ -2,7 +2,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.*; -import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.exceptions.RecursionException; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; import nl.jqno.equalsverifier.internal.reflection.FactoryCache; @@ -11,6 +10,7 @@ import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.FallbackFactory; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; +import nl.jqno.equalsverifier.internal.util.Rethrow; public class VintageValueProvider implements ValueProvider { @@ -32,19 +32,7 @@ public VintageValueProvider(FactoryCache factoryCache) { @Override public Tuple provide(TypeTag tag) { - try { - return giveTuple(tag); - } catch (RuntimeException e) { - // InaccessibleObjectException is not yet available in Java 8 - if (e.getClass().getName().endsWith("InaccessibleObjectException")) { - throw new ModuleException( - "The class is not accessible via the Java Module system. Consider opening the module that contains it.", - e - ); - } else { - throw e; - } - } + return Rethrow.rethrow(() -> giveTuple(tag)); } /** diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java index 282e2c0b9..3c673dc91 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java @@ -3,7 +3,6 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; import java.util.LinkedHashSet; -import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.FieldProbe; import nl.jqno.equalsverifier.internal.reflection.Tuple; @@ -86,16 +85,7 @@ private void traverseFields( FieldProbe probe = FieldProbe.of(field); boolean isStaticAndFinal = probe.isStatic() && probe.isFinal(); if (!isStaticAndFinal) { - try { - valueProvider.realizeCacheFor(TypeTag.of(field, tag), typeStack); - } catch (RuntimeException e) { - // InaccessibleObjectException is not yet available in Java 8 - if (e.getClass().getName().endsWith("InaccessibleObjectException")) { - handleInaccessibleObjectException(e, type, field); - } else { - throw e; - } - } + valueProvider.realizeCacheFor(TypeTag.of(field, tag), typeStack); } } } @@ -111,17 +101,4 @@ private Tuple giveInstances( T redCopy = accessor.getRedObject(tag, typeStack); return new Tuple<>(red, blue, redCopy); } - - private void handleInaccessibleObjectException(Throwable e, Class type, Field field) { - throw new ModuleException( - "Field " + - field.getName() + - " of type " + - field.getType().getName() + - " is not accessible via the Java Module System.\nConsider opening the module that contains it, or add prefab values for type " + - field.getType().getName() + - ".", - e - ); - } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Rethrow.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Rethrow.java index 5d61c788c..1c07f2e18 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Rethrow.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Rethrow.java @@ -2,6 +2,7 @@ import java.util.function.Function; import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; +import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.exceptions.ReflectionException; /** @@ -33,7 +34,14 @@ public static T rethrow( try { return supplier.get(); } catch (RuntimeException e) { - throw e; + if (e.getClass().getName().endsWith("InaccessibleObjectException")) { + throw new ModuleException( + "The class is not accessible via the Java Module system. Consider opening the module that contains it.", + e + ); + } else { + throw e; + } } catch (ReflectiveOperationException e) { throw new ReflectionException(errorMessage.apply(e), e); } catch (Exception e) { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java index 30e67859e..04e7668a0 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; +import nl.jqno.equalsverifier.internal.exceptions.ModuleException; import nl.jqno.equalsverifier.internal.reflection.FactoryCache; import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; import nl.jqno.equalsverifier.internal.reflection.TypeTag; @@ -136,11 +137,7 @@ public void scrambleSutInaccessible() { public void scrambleFieldInaccessible() { InaccessibleContainer ic = new InaccessibleContainer(new AttributedString("x")); - ExpectedException - .when(() -> doScramble(ic)) - // InaccessibleObjectException, but it's not available in Java 8 - .assertThrows(RuntimeException.class) - .assertMessageContains("accessible: module", "does not \"opens"); + ExpectedException.when(() -> doScramble(ic)).assertThrows(ModuleException.class); } @SuppressWarnings("unchecked") From edce7d39fa617d3717d96b0a143ef366291aecb3 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Tue, 17 Sep 2024 15:57:11 +0200 Subject: [PATCH 57/74] Adds #withPrefabValuesForField --- .../PrefabValuesForFieldInRecordTest.java | 76 +++++++++++++++++++ .../api/SingleTypeEqualsVerifierApi.java | 27 ++++++- .../instantiation/SubjectCreator.java | 15 +++- .../equalsverifier/internal/util/Context.java | 14 ++-- .../internal/util/PrefabValuesApi.java | 26 +++++++ .../internal/util/Validations.java | 27 ++++++- 6 files changed, 172 insertions(+), 13 deletions(-) create mode 100644 equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java new file mode 100644 index 000000000..d99afb1c9 --- /dev/null +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java @@ -0,0 +1,76 @@ +package nl.jqno.equalsverifier.integration.extended_contract; + +import nl.jqno.equalsverifier.EqualsVerifier; +import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; +import org.junit.jupiter.api.Test; + +public class PrefabValuesForFieldInRecordTest { + + @Test + public void fail_whenRecordHasSinglePrecondition() { + ExpectedException + .when(() -> EqualsVerifier.forClass(SinglePrecondition.class).verify()) + .assertFailure() + .assertMessageContains("Record:", "failed to run constructor", "[1]"); + } + + @Test + public void succeed_whenRecordHasSinglePrecondition_givenPrefabValuesForField() { + EqualsVerifier + .forClass(SinglePrecondition.class) + .withPrefabValuesForField("i", 111, 142) + .suppress(Warning.ZERO_FIELDS) + .verify(); + } + + @Test + public void fail_whenRecordHasDualPrecondition() { + ExpectedException + .when(() -> EqualsVerifier.forClass(DualPrecondition.class).verify()) + .assertFailure() + .assertMessageContains("Record:", "failed to run constructor", "[1, 1]"); + } + + @Test + public void fail_whenRecordHasDualPrecondition_givenPrefabValuesForOnlyOneField() { + ExpectedException + .when(() -> + EqualsVerifier + .forClass(DualPrecondition.class) + .withPrefabValuesForField("x", 111, 142) + .verify() + ) + .assertFailure() + .assertMessageContains("Record:", "failed to run constructor", "[111, 1]"); + } + + @Test + public void succeed_whenRecordHasDualPrecondition_givenPrefabValueForBothFields() { + EqualsVerifier + .forClass(DualPrecondition.class) + .withPrefabValuesForField("x", 111, 142) + .withPrefabValuesForField("y", 505, 555) + .suppress(Warning.ZERO_FIELDS) + .verify(); + } + + record SinglePrecondition(int i) { + public SinglePrecondition { + if (i < 100 || i > 200) { + throw new IllegalArgumentException("i must be between 100 and 200!"); + } + } + } + + record DualPrecondition(int x, int y) { + public DualPrecondition { + if (x < 100 || x > 200) { + throw new IllegalArgumentException("x must be between 100 and 200!"); + } + if (y < 500 || y > 600) { + throw new IllegalArgumentException("y must be between 500 and 600!"); + } + } + } +} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index 7e7ea8111..d08a8ed71 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -10,6 +10,7 @@ import nl.jqno.equalsverifier.internal.checkers.*; import nl.jqno.equalsverifier.internal.exceptions.MessagingException; import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.FieldCache; import nl.jqno.equalsverifier.internal.util.*; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -28,6 +29,7 @@ public class SingleTypeEqualsVerifierApi implements EqualsVerifierApi { private boolean hasRedefinedSuperclass = false; private Class redefinedSubclass = null; private FactoryCache factoryCache = new FactoryCache(); + private FieldCache fieldCache = new FieldCache(); private CachedHashCodeInitializer cachedHashCodeInitializer = CachedHashCodeInitializer.passthrough(); private Function fieldnameToGetter = null; @@ -107,6 +109,29 @@ public SingleTypeEqualsVerifierApi withPrefabValues(Class otherType, S return this; } + /** + * Adds prefabricated values for instance fields with a given name (and only the fields with + * the given name) that EqualsVerifier cannot instantiate by itself. + * + * @param The class of the prefabricated values. + * @param fieldName The name of the field that the prefabricated values are linked to. + * @param red An instance of {@code S}. + * @param blue Another instance of {@code S}, not equal to {@code red}. + * @return {@code this}, for easy method chaining. + * @throws NullPointerException If {@code red} or {@code blue} is null, or if the named field + * does not exist in the class. + * @throws IllegalArgumentException If {@code red} equals {@code blue}. + */ + public SingleTypeEqualsVerifierApi withPrefabValuesForField( + String fieldName, + S red, + S blue + ) { + Validations.validateFieldNameExists(type, fieldName, actualFields); + PrefabValuesApi.addPrefabValuesForField(fieldCache, type, fieldName, red, blue); + return this; + } + /** {@inheritDoc} */ @Override public SingleTypeEqualsVerifierApi withGenericPrefabValues( @@ -391,7 +416,7 @@ private void performVerification() { Validations.validateClassCanBeVerified(type); Configuration config = buildConfig(); - Context context = new Context<>(config, factoryCache); + Context context = new Context<>(config, factoryCache, fieldCache); Validations.validateProcessedAnnotations( type, config.getAnnotationCache(), diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java index ed690067f..3799febf0 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java @@ -1,5 +1,6 @@ package nl.jqno.equalsverifier.internal.reflection.instantiation; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; @@ -15,14 +16,20 @@ public class SubjectCreator { private final Configuration config; private final ValueProvider valueProvider; private final ClassProbe classProbe; - private final FieldCache fieldCache = new FieldCache(); - - public SubjectCreator(TypeTag typeTag, Configuration config, ValueProvider valueProvider) { - this.typeTag = typeTag; + private final FieldCache fieldCache; + + @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "A cache is inherently mutable") + public SubjectCreator( + Configuration config, + ValueProvider valueProvider, + FieldCache fieldCache + ) { + this.typeTag = config.getTypeTag(); this.type = typeTag.getType(); this.config = config; this.valueProvider = valueProvider; this.classProbe = new ClassProbe<>(type); + this.fieldCache = fieldCache; } public T plain() { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index 7026b7037..d3303c78b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -1,9 +1,7 @@ package nl.jqno.equalsverifier.internal.util; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import nl.jqno.equalsverifier.internal.reflection.ClassProbe; -import nl.jqno.equalsverifier.internal.reflection.FactoryCache; -import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; +import nl.jqno.equalsverifier.internal.reflection.*; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; @@ -16,16 +14,18 @@ public final class Context { private final SubjectCreator subjectCreator; private final ValueProvider valueProvider; - public Context(Configuration configuration, FactoryCache factoryCache) { + public Context( + Configuration configuration, + FactoryCache factoryCache, + FieldCache fieldCache + ) { this.type = configuration.getType(); this.configuration = configuration; this.classProbe = new ClassProbe<>(configuration.getType()); FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); - this.valueProvider = new VintageValueProvider(cache); - this.subjectCreator = - new SubjectCreator<>(configuration.getTypeTag(), configuration, valueProvider); + this.subjectCreator = new SubjectCreator<>(configuration, valueProvider, fieldCache); } public Class getType() { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java index 6f972db72..8493682e6 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java @@ -6,6 +6,8 @@ import nl.jqno.equalsverifier.Func.Func1; import nl.jqno.equalsverifier.Func.Func2; import nl.jqno.equalsverifier.internal.reflection.FactoryCache; +import nl.jqno.equalsverifier.internal.reflection.FieldCache; +import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; @@ -34,6 +36,30 @@ public static void addPrefabValues( } } + @SuppressWarnings("unchecked") + public static void addPrefabValuesForField( + FieldCache fieldCache, + Class type, + String fieldName, + T red, + T blue + ) { + Validations.validateRedAndBluePrefabValues((Class) red.getClass(), red, blue); + Validations.validateFieldTypeMatches(type, fieldName, red.getClass()); + + if (red.getClass().isArray()) { + fieldCache.put(fieldName, new Tuple<>(red, blue, red)); + } else { + try { + T redCopy = ObjectAccessor.of(red).copy(); + fieldCache.put(fieldName, new Tuple<>(red, blue, redCopy)); + } catch (RuntimeException ignored) { + /* specifically, on Java 9+: InacessibleObjectException */ + fieldCache.put(fieldName, new Tuple<>(red, blue, red)); + } + } + } + public static void addGenericPrefabValues( FactoryCache factoryCache, Class otherType, diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java index ab274310c..cdcb3ec8c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java @@ -33,7 +33,7 @@ public static void validateFieldNamesExist( givenFields.forEach(f -> validateFieldNameExists(type, f, actualFields)); } - private static void validateFieldNameExists( + public static void validateFieldNameExists( Class type, String field, Set actualFields @@ -89,6 +89,31 @@ public static void validateRedAndBluePrefabValues(Class type, T red, T bl ); } + public static void validateFieldTypeMatches( + Class container, + String fieldName, + Class fieldType + ) { + try { + Field f = container.getDeclaredField(fieldName); + validate( + f.getType().equals(fieldType), + "Prefab values for field " + + fieldName + + " should be of type " + + f.getType().getSimpleName() + + " but are " + + fieldType.getSimpleName() + + "." + ); + } catch (NoSuchFieldException e) { + validate( + false, + "Class " + container.getSimpleName() + " has no field named " + fieldName + "." + ); + } + } + public static void validateGenericPrefabValues( Class type, PrefabValueFactory factory, From d724033413100efbcda77cc9753f4637e47f684b Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Tue, 17 Sep 2024 19:26:43 +0200 Subject: [PATCH 58/74] Automatically suppresses Warning.ZERO_FIELDS when using #withPrefabValuesForField --- .../extended_contract/PrefabValuesForFieldInRecordTest.java | 3 --- .../jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java index d99afb1c9..778b741df 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java @@ -1,7 +1,6 @@ package nl.jqno.equalsverifier.integration.extended_contract; import nl.jqno.equalsverifier.EqualsVerifier; -import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.Test; @@ -20,7 +19,6 @@ public void succeed_whenRecordHasSinglePrecondition_givenPrefabValuesForField() EqualsVerifier .forClass(SinglePrecondition.class) .withPrefabValuesForField("i", 111, 142) - .suppress(Warning.ZERO_FIELDS) .verify(); } @@ -51,7 +49,6 @@ public void succeed_whenRecordHasDualPrecondition_givenPrefabValueForBothFields( .forClass(DualPrecondition.class) .withPrefabValuesForField("x", 111, 142) .withPrefabValuesForField("y", 505, 555) - .suppress(Warning.ZERO_FIELDS) .verify(); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index d08a8ed71..664713aa3 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -113,6 +113,9 @@ public SingleTypeEqualsVerifierApi withPrefabValues(Class otherType, S * Adds prefabricated values for instance fields with a given name (and only the fields with * the given name) that EqualsVerifier cannot instantiate by itself. * + * Automatically suppresses {@code Warning.ZERO_FIELDS}, because fields that get a specific + * prefabricated value should usually not be assigned to zero. + * * @param The class of the prefabricated values. * @param fieldName The name of the field that the prefabricated values are linked to. * @param red An instance of {@code S}. @@ -129,6 +132,7 @@ public SingleTypeEqualsVerifierApi withPrefabValuesForField( ) { Validations.validateFieldNameExists(type, fieldName, actualFields); PrefabValuesApi.addPrefabValuesForField(fieldCache, type, fieldName, red, blue); + suppress(Warning.ZERO_FIELDS); return this; } From 2f111533b16a20170527e7697de12d80bbd71062 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 19 Sep 2024 08:25:18 +0200 Subject: [PATCH 59/74] Refines #withPrefabValuesForField --- .../PrefabValuesForFieldInRecordTest.java | 6 +- .../api/SingleTypeEqualsVerifierApi.java | 2 + .../fieldchecks/ReflexivityFieldCheck.java | 15 +- .../internal/reflection/FieldCache.java | 10 +- .../internal/util/Configuration.java | 9 + .../equalsverifier/internal/util/Context.java | 12 + .../internal/util/Validations.java | 8 +- .../WithPrefabValuesForFieldTest.java | 227 ++++++++++++++++++ .../internal/reflection/FieldCacheTest.java | 13 + .../internal/util/ConfigurationHelper.java | 2 + .../testhelpers/types/FinalPoint.java | 8 + 11 files changed, 300 insertions(+), 12 deletions(-) create mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithPrefabValuesForFieldTest.java diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java index 778b741df..c0f29a826 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/PrefabValuesForFieldInRecordTest.java @@ -55,7 +55,7 @@ public void succeed_whenRecordHasDualPrecondition_givenPrefabValueForBothFields( record SinglePrecondition(int i) { public SinglePrecondition { if (i < 100 || i > 200) { - throw new IllegalArgumentException("i must be between 100 and 200!"); + throw new IllegalArgumentException("i must be between 100 and 200! But was " + i); } } } @@ -63,10 +63,10 @@ record SinglePrecondition(int i) { record DualPrecondition(int x, int y) { public DualPrecondition { if (x < 100 || x > 200) { - throw new IllegalArgumentException("x must be between 100 and 200!"); + throw new IllegalArgumentException("x must be between 100 and 200! But was " + x); } if (y < 500 || y > 600) { - throw new IllegalArgumentException("y must be between 500 and 600!"); + throw new IllegalArgumentException("y must be between 500 and 600! But was " + y); } } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index 664713aa3..3999234dd 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -132,6 +132,7 @@ public SingleTypeEqualsVerifierApi withPrefabValuesForField( ) { Validations.validateFieldNameExists(type, fieldName, actualFields); PrefabValuesApi.addPrefabValuesForField(fieldCache, type, fieldName, red, blue); + withNonnullFields(fieldName); suppress(Warning.ZERO_FIELDS); return this; } @@ -439,6 +440,7 @@ private Configuration buildConfig() { allExcludedFields, allIncludedFields, nonnullFields, + fieldCache.getFieldNames(), cachedHashCodeInitializer, hasRedefinedSuperclass, redefinedSubclass, diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index 43eb1bac7..f22625ef8 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -7,10 +7,7 @@ import java.util.EnumSet; import java.util.Set; import nl.jqno.equalsverifier.Warning; -import nl.jqno.equalsverifier.internal.reflection.ClassProbe; -import nl.jqno.equalsverifier.internal.reflection.FieldProbe; -import nl.jqno.equalsverifier.internal.reflection.Tuple; -import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.reflection.*; import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache; import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; @@ -26,7 +23,9 @@ public class ReflexivityFieldCheck implements FieldCheck { private final ValueProvider valueProvider; private final EnumSet warningsToSuppress; private final Set nonnullFields; + private final Set prefabbedFields; private final AnnotationCache annotationCache; + private final FieldCache fieldCache; public ReflexivityFieldCheck(Context context) { this.subjectCreator = context.getSubjectCreator(); @@ -36,7 +35,9 @@ public ReflexivityFieldCheck(Context context) { this.typeTag = config.getTypeTag(); this.warningsToSuppress = config.getWarningsToSuppress(); this.nonnullFields = config.getNonnullFields(); + this.prefabbedFields = config.getPrefabbedFields(); this.annotationCache = config.getAnnotationCache(); + this.fieldCache = context.getFieldCache(); } @Override @@ -77,8 +78,12 @@ private void checkValueReflexivity(FieldProbe probe) { } Field field = probe.getField(); + String fieldName = field.getName(); TypeTag tag = TypeTag.of(field, typeTag); - Tuple tuple = valueProvider.provide(tag); + Tuple tuple = prefabbedFields.contains(fieldName) + ? fieldCache.get(fieldName) + : valueProvider.provide(tag); + Object left = subjectCreator.withFieldSetTo(field, tuple.getRed()); Object right = subjectCreator.withFieldSetTo(field, tuple.getRedCopy()); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldCache.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldCache.java index 57a0355e2..455a786e5 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldCache.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldCache.java @@ -1,7 +1,6 @@ package nl.jqno.equalsverifier.internal.reflection; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; /** Contains a cache for values connected to specific fields, for {@link SubjectCreator}. */ @@ -51,4 +50,11 @@ public Tuple get(String fieldName) { public boolean contains(String fieldName) { return cache.containsKey(fieldName); } + + /** + * @return The fields preset in the cache. + */ + public Set getFieldNames() { + return new HashSet<>(cache.keySet()); + } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java index 6b9be50a5..72c06ef98 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Configuration.java @@ -16,6 +16,7 @@ public final class Configuration { private final Class type; private final Set nonnullFields; + private final Set prefabbedFields; private final CachedHashCodeInitializer cachedHashCodeInitializer; private final boolean hasRedefinedSuperclass; private final Class redefinedSubclass; @@ -36,6 +37,7 @@ private Configuration( TypeTag typeTag, Set ignoredFields, Set nonnullFields, + Set prefabbedFields, AnnotationCache annotationCache, CachedHashCodeInitializer cachedHashCodeInitializer, boolean hasRedefinedSuperclass, @@ -50,6 +52,7 @@ private Configuration( this.typeTag = typeTag; this.ignoredFields = ignoredFields; this.nonnullFields = nonnullFields; + this.prefabbedFields = prefabbedFields; this.annotationCache = annotationCache; this.cachedHashCodeInitializer = cachedHashCodeInitializer; this.hasRedefinedSuperclass = hasRedefinedSuperclass; @@ -66,6 +69,7 @@ public static Configuration build( Set excludedFields, Set includedFields, Set nonnullFields, + Set prefabbedFields, CachedHashCodeInitializer cachedHashCodeInitializer, boolean hasRedefinedSuperclass, Class redefinedSubclass, @@ -96,6 +100,7 @@ public static Configuration build( typeTag, ignoredFields, nonnullFields, + prefabbedFields, annotationCache, cachedHashCodeInitializer, hasRedefinedSuperclass, @@ -190,6 +195,10 @@ public Set getNonnullFields() { return Collections.unmodifiableSet(nonnullFields); } + public Set getPrefabbedFields() { + return Collections.unmodifiableSet(prefabbedFields); + } + public CachedHashCodeInitializer getCachedHashCodeInitializer() { return cachedHashCodeInitializer; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index d3303c78b..456b45704 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -11,9 +11,15 @@ public final class Context { private final Class type; private final Configuration configuration; private final ClassProbe classProbe; + private final FieldCache fieldCache; + private final SubjectCreator subjectCreator; private final ValueProvider valueProvider; + @SuppressFBWarnings( + value = "EI_EXPOSE_REP2", + justification = "FieldCache is inherently mutable" + ) public Context( Configuration configuration, FactoryCache factoryCache, @@ -22,6 +28,7 @@ public Context( this.type = configuration.getType(); this.configuration = configuration; this.classProbe = new ClassProbe<>(configuration.getType()); + this.fieldCache = fieldCache; FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); this.valueProvider = new VintageValueProvider(cache); @@ -40,6 +47,11 @@ public ClassProbe getClassProbe() { return classProbe; } + @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "A cache is inherently mutable") + public FieldCache getFieldCache() { + return fieldCache; + } + @SuppressFBWarnings( value = "EI_EXPOSE_REP", justification = "VintageValueProvider can use a mutable cache." diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java index cdcb3ec8c..0adb4f04d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Validations.java @@ -96,11 +96,15 @@ public static void validateFieldTypeMatches( ) { try { Field f = container.getDeclaredField(fieldName); + boolean sameFields = f.getType().equals(fieldType); + boolean compatibleFields = fieldType.equals( + PrimitiveMappers.PRIMITIVE_OBJECT_MAPPER.get(f.getType()) + ); validate( - f.getType().equals(fieldType), + !sameFields && !compatibleFields, "Prefab values for field " + fieldName + - " should be of type " + + " should be of type " + f.getType().getSimpleName() + " but are " + fieldType.getSimpleName() + diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithPrefabValuesForFieldTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithPrefabValuesForFieldTest.java new file mode 100644 index 000000000..2ade8be58 --- /dev/null +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithPrefabValuesForFieldTest.java @@ -0,0 +1,227 @@ +package nl.jqno.equalsverifier.integration.operational; + +import java.time.LocalDate; +import java.time.Month; +import java.util.Objects; +import nl.jqno.equalsverifier.EqualsVerifier; +import nl.jqno.equalsverifier.Warning; +import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; +import nl.jqno.equalsverifier.testhelpers.types.FinalPoint; +import org.junit.jupiter.api.Test; + +public class WithPrefabValuesForFieldTest { + + private final FinalPoint pRed = new FinalPoint(3, 42); + private final FinalPoint pBlue = new FinalPoint(3, 1337); + private final int iRed = 111; + private final int iBlue = 142; + + @Test + public void fail_whenRecordHasSinglePrecondition() { + ExpectedException + .when(() -> + EqualsVerifier + .forClass(SinglePrecondition.class) + .suppress(Warning.NULL_FIELDS) + .verify() + ) + .assertFailure() + .assertMessageContains("x coordinate must be"); + } + + @Test + public void succeed_whenRecordHasSinglePrecondition_givenPrefabValuesForField() { + EqualsVerifier + .forClass(SinglePrecondition.class) + .withPrefabValuesForField("point", pRed, pBlue) + .verify(); + } + + @Test + public void fail_whenRecordHasDualPrecondition() { + ExpectedException + .when(() -> EqualsVerifier.forClass(DualPrecondition.class).verify()) + .assertFailure() + .assertMessageContains("x must be between"); + } + + @Test + public void fail_whenRecordHasDualPrecondition_givenPrefabValuesForOnlyOneField() { + ExpectedException + .when(() -> + EqualsVerifier + .forClass(DualPrecondition.class) + .withPrefabValuesForField("x", iRed, iBlue) + .verify() + ) + .assertFailure() + .assertMessageContains("y must be between"); + } + + @Test + public void succeed_whenRecordHasDualPrecondition_givenPrefabValueForBothFields() { + EqualsVerifier + .forClass(DualPrecondition.class) + .withPrefabValuesForField("x", iRed, iBlue) + .withPrefabValuesForField("y", 505, 555) + .verify(); + } + + @Test + public void throw_whenFieldDoesNotExistInClass() { + ExpectedException + .when(() -> + EqualsVerifier + .forClass(SinglePrecondition.class) + .withPrefabValuesForField("doesnt_exist", 1, 2) + ) + .assertThrows(IllegalStateException.class) + .assertMessageContains("Precondition:", "does not contain field doesnt_exist"); + } + + @Test + public void throw_whenFirstPrefabValueIsNull() { + ExpectedException + .when(() -> + EqualsVerifier + .forClass(SinglePrecondition.class) + .withPrefabValuesForField("point", null, pBlue) + ) + .assertThrows(NullPointerException.class); + } + + @Test + public void throw_whenSecondPrefabValueIsNull() { + ExpectedException + .when(() -> + EqualsVerifier + .forClass(SinglePrecondition.class) + .withPrefabValuesForField("point", pRed, null) + ) + .assertThrows(NullPointerException.class); + } + + @Test + public void throw_whenThePrefabValuesAreTheSame() { + ExpectedException + .when(() -> + EqualsVerifier + .forClass(SinglePrecondition.class) + .withPrefabValuesForField("point", pRed, pRed) + ) + .assertThrows(IllegalStateException.class) + .assertMessageContains( + "Precondition", + "both prefab values of type FinalPoint are equal" + ); + } + + @Test + public void throw_whenThePrefabValuesAreEqual() { + FinalPoint red1 = new FinalPoint(3, 4); + FinalPoint red2 = new FinalPoint(3, 4); + + ExpectedException + .when(() -> + EqualsVerifier + .forClass(SinglePrecondition.class) + .withPrefabValuesForField("point", red1, red2) + ) + .assertThrows(IllegalStateException.class) + .assertMessageContains( + "Precondition", + "both prefab values of type FinalPoint are equal" + ); + } + + @Test + public void dontThrow_whenAddingPrefabValuesFromAnotherModuleAndThereforeARedCopyCantBeMade() { + EqualsVerifier + .forClass(OtherModuleContainer.class) + .withPrefabValuesForField("date", LocalDate.of(2024, 9, 18), LocalDate.of(2024, 9, 19)) + .verify(); + } + + static final class SinglePrecondition { + + private final FinalPoint point; + + public SinglePrecondition(FinalPoint point) { + this.point = point; + } + + @Override + public boolean equals(Object obj) { + if (point == null || point.getX() != 3) { + throw new IllegalArgumentException("x coordinate must be 3! But was " + point); + } + if (!(obj instanceof SinglePrecondition)) { + return false; + } + SinglePrecondition other = (SinglePrecondition) obj; + return Objects.equals(point, other.point); + } + + @Override + public int hashCode() { + return Objects.hash(point); + } + } + + static final class DualPrecondition { + + private final int x; + private final int y; + + public DualPrecondition(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (x < 100 || x > 200) { + throw new IllegalArgumentException("x must be between 100 and 200! But was " + x); + } + if (y < 500 || y > 600) { + throw new IllegalArgumentException("y must be between 500 and 600! But was " + y); + } + if (!(obj instanceof DualPrecondition)) { + return false; + } + DualPrecondition other = (DualPrecondition) obj; + return Objects.equals(x, other.x) && Objects.equals(y, other.y); + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } + } + + static final class OtherModuleContainer { + + private final LocalDate date; + + public OtherModuleContainer(LocalDate date) { + this.date = date; + } + + @Override + public boolean equals(Object obj) { + if (date == null || date.getMonth() != Month.SEPTEMBER) { + throw new IllegalArgumentException("date must be in September! But was " + date); + } + if (!(obj instanceof OtherModuleContainer)) { + return false; + } + OtherModuleContainer other = (OtherModuleContainer) obj; + return Objects.equals(date, other.date); + } + + @Override + public int hashCode() { + return Objects.hash(date); + } + } +} diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldCacheTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldCacheTest.java index 19b7bd8fb..5d09df19a 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldCacheTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldCacheTest.java @@ -2,6 +2,9 @@ import static org.junit.jupiter.api.Assertions.*; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import org.junit.jupiter.api.Test; public class FieldCacheTest { @@ -45,4 +48,14 @@ public void contains() { public void doesntContain() { assertFalse(cache.contains(stringField)); } + + @Test + public void getFieldNames() { + assertEquals(Collections.emptySet(), cache.getFieldNames()); + + cache.put(stringField, stringValues); + Set expected = new HashSet<>(); + expected.add(stringField); + assertEquals(expected, cache.getFieldNames()); + } } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java index d23c139c2..d3e92c825 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java @@ -16,6 +16,7 @@ public static final Configuration emptyConfiguration( Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), + Collections.emptySet(), null, false, null, @@ -40,6 +41,7 @@ public static final Configuration emptyConfigurationWithNonnullFields( Collections.emptySet(), Collections.emptySet(), new HashSet<>(Arrays.asList(fieldNames)), + Collections.emptySet(), null, false, null, diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/FinalPoint.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/FinalPoint.java index ac3cb73de..41e081c18 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/FinalPoint.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/testhelpers/types/FinalPoint.java @@ -10,6 +10,14 @@ public FinalPoint(int x, int y) { this.y = y; } + public int getX() { + return x; + } + + public int getY() { + return y; + } + @Override public boolean equals(Object obj) { if (!(obj instanceof FinalPoint)) { From f515c7c8f38a4f4c717b18b2debe42388383dc7f Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 19 Sep 2024 11:03:24 +0200 Subject: [PATCH 60/74] Don't automatically suppresses Warning.ZERO_FIELDS when using #withPrefabValuesForField --- .../jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java | 4 ---- .../internal/checkers/fieldchecks/ReflexivityFieldCheck.java | 3 +++ .../jqno/equalsverifier/internal/reflection/FieldProbe.java | 5 ++++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index 3999234dd..940778c31 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -113,9 +113,6 @@ public SingleTypeEqualsVerifierApi withPrefabValues(Class otherType, S * Adds prefabricated values for instance fields with a given name (and only the fields with * the given name) that EqualsVerifier cannot instantiate by itself. * - * Automatically suppresses {@code Warning.ZERO_FIELDS}, because fields that get a specific - * prefabricated value should usually not be assigned to zero. - * * @param The class of the prefabricated values. * @param fieldName The name of the field that the prefabricated values are linked to. * @param red An instance of {@code S}. @@ -133,7 +130,6 @@ public SingleTypeEqualsVerifierApi withPrefabValuesForField( Validations.validateFieldNameExists(type, fieldName, actualFields); PrefabValuesApi.addPrefabValuesForField(fieldCache, type, fieldName, red, blue); withNonnullFields(fieldName); - suppress(Warning.ZERO_FIELDS); return this; } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index f22625ef8..716f40568 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -101,6 +101,9 @@ private void checkNullReflexivity(FieldProbe fieldProbe) { if (fieldProbe.isPrimitive() && warningsToSuppress.contains(Warning.ZERO_FIELDS)) { return; } + if (prefabbedFields.contains(fieldProbe.getName())) { + return; + } boolean nullWarningIsSuppressed = warningsToSuppress.contains(Warning.NULL_FIELDS); boolean fieldIsNonNull = fieldProbe.isAnnotatedNonnull(annotationCache); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java index 27f1c512e..41f9eb534 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java @@ -97,7 +97,10 @@ public boolean isEmptyOrSingleValueEnum() { */ public boolean canBeDefault(Configuration config) { if (isPrimitive()) { - return !config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS); + return ( + !config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS) && + !config.getPrefabbedFields().contains(getName()) + ); } boolean isAnnotated = isAnnotatedNonnull(config.getAnnotationCache()); From bba18177771a532358f47e61f224f2027f9d984e Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 19 Sep 2024 11:37:18 +0200 Subject: [PATCH 61/74] Deprecates Warning.ZERO_FIELDS --- .../extended_contract/RecordsTest.java | 9 -------- .../java/nl/jqno/equalsverifier/Warning.java | 5 ++++ .../fieldchecks/ReflexivityFieldCheck.java | 5 +--- .../internal/reflection/FieldProbe.java | 5 +--- .../internal/reflection/FieldProbeTest.java | 6 ++--- .../internal/util/ConfigurationHelper.java | 23 +++++++++++++++++++ 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/RecordsTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/RecordsTest.java index 36d6fb4c6..076a44c41 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/RecordsTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/RecordsTest.java @@ -51,15 +51,6 @@ public void fail_whenConstructorChecksValue() { .assertMessageContains("Record:", "failed to run constructor", "prefab values"); } - @Test - public void succeed_whenConstructorChecksValue_givenPrefabValues() { - EqualsVerifier - .forClass(ValueCheckingRecord.class) - .withPrefabValues(int.class, 10, 11) - .suppress(Warning.ZERO_FIELDS) - .verify(); - } - @Test public void fail_whenRecordInvariantIsViolated_givenIntFieldIsModifiedInConstructor() { ExpectedException diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java index ab67cf27a..eb0a37756 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java @@ -1,5 +1,7 @@ package nl.jqno.equalsverifier; +import nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi; + /** * Enum of warnings that can be suppressed in {@link nl.jqno.equalsverifier.EqualsVerifier}. * @@ -212,6 +214,9 @@ public enum Warning { *

Sometimes the constructor of a class makes sure no field can be 0. If this is the case, * and if the fields cannot be made 0 later in the lifecycle of the class by setters or other * methods, suppress this warning to disable the checks with fields that have value 0. + * + * @deprecated Use {@link SingleTypeEqualsVerifierApi#withPrefabValuesForField(String, Object, Object)} instead. */ + @Deprecated ZERO_FIELDS } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java index 716f40568..3d775008a 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/ReflexivityFieldCheck.java @@ -97,14 +97,11 @@ private void checkValueReflexivity(FieldProbe probe) { } private void checkNullReflexivity(FieldProbe fieldProbe) { - Field field = fieldProbe.getField(); - if (fieldProbe.isPrimitive() && warningsToSuppress.contains(Warning.ZERO_FIELDS)) { - return; - } if (prefabbedFields.contains(fieldProbe.getName())) { return; } + Field field = fieldProbe.getField(); boolean nullWarningIsSuppressed = warningsToSuppress.contains(Warning.NULL_FIELDS); boolean fieldIsNonNull = fieldProbe.isAnnotatedNonnull(annotationCache); boolean fieldIsMentionedExplicitly = nonnullFields.contains(field.getName()); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java index 41f9eb534..56cd194b6 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldProbe.java @@ -97,10 +97,7 @@ public boolean isEmptyOrSingleValueEnum() { */ public boolean canBeDefault(Configuration config) { if (isPrimitive()) { - return ( - !config.getWarningsToSuppress().contains(Warning.ZERO_FIELDS) && - !config.getPrefabbedFields().contains(getName()) - ); + return !config.getPrefabbedFields().contains(getName()); } boolean isAnnotated = isAnnotatedNonnull(config.getAnnotationCache()); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java index 8ba1caa77..8208b7839 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java @@ -3,7 +3,6 @@ import static org.junit.jupiter.api.Assertions.*; import java.lang.reflect.Field; -import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.ConfigurationHelper; import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.*; @@ -135,9 +134,10 @@ public void canBeDefault_primitive() { } @Test - public void canBeDefault_primitiveWithWarningSuppressed() { + public void canBeDefault_primitiveWithPrefabbedField() { PrimitiveContainer foo = new PrimitiveContainer(); - config = ConfigurationHelper.emptyConfiguration(foo.getClass(), Warning.ZERO_FIELDS); + config = + ConfigurationHelper.emptyConfigurationWithPrefabbedFields(foo.getClass(), FIELD_NAME); FieldProbe probe = getAccessorFor(foo, FIELD_NAME); assertFalse(probe.canBeDefault(config)); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java index d3e92c825..5480ed441 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/ConfigurationHelper.java @@ -54,4 +54,27 @@ public static final Configuration emptyConfigurationWithNonnullFields( Collections.emptyList() ); } + + public static final Configuration emptyConfigurationWithPrefabbedFields( + Class type, + String... fieldNames + ) { + return Configuration.build( + type, + Collections.emptySet(), + Collections.emptySet(), + Collections.emptySet(), + new HashSet<>(Arrays.asList(fieldNames)), + null, + false, + null, + false, + EnumSet.noneOf(Warning.class), + null, + Collections.emptySet(), + Collections.emptySet(), + Collections.emptyList(), + Collections.emptyList() + ); + } } From bd4eadd77a36b826de2c49bda747702deb175704 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 19 Sep 2024 13:46:59 +0200 Subject: [PATCH 62/74] Adds Javadoc --- .../java/nl/jqno/equalsverifier/Warning.java | 7 +- .../internal/reflection/FieldMutator.java | 14 +++ .../instantiation/InstanceCreator.java | 9 ++ .../instantiation/SubjectCreator.java | 89 +++++++++++++++++++ .../instantiation/ValueProvider.java | 16 ++++ .../instantiation/VintageValueProvider.java | 43 ++++----- .../VintageValueProviderTest.java | 12 +-- 7 files changed, 153 insertions(+), 37 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java index eb0a37756..7d151f2a9 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/Warning.java @@ -208,12 +208,7 @@ public enum Warning { BIGDECIMAL_EQUALITY, /** - * Disables checks with fields with value 0 within {@code equals}, {@code hashCode} and - * {@code toString} methods. - * - *

Sometimes the constructor of a class makes sure no field can be 0. If this is the case, - * and if the fields cannot be made 0 later in the lifecycle of the class by setters or other - * methods, suppress this warning to disable the checks with fields that have value 0. + * No longer does anything. * * @deprecated Use {@link SingleTypeEqualsVerifierApi#withPrefabValuesForField(String, Object, Object)} instead. */ diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldMutator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldMutator.java index 9086fb305..f27805935 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldMutator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/FieldMutator.java @@ -4,16 +4,30 @@ import java.lang.reflect.Field; +/** + * Allows for a field in an object reference to be set to another value. + */ public class FieldMutator { private final FieldProbe probe; private final Field field; + /** + * Constructor. + * + * @param probe A field probe pointing to the field to mutate. + */ public FieldMutator(FieldProbe probe) { this.probe = probe; this.field = probe.getField(); } + /** + * Assigns {@code newValue} to the current field in {@code object}. + * + * @param object The instance on which to re-assign the current field. + * @param newValue The value to assign to the field. + */ public void setNewValue(Object object, Object newValue) { rethrow(() -> { if (probe.canBeModifiedReflectively()) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java index b56f38d90..3b3b8223f 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java @@ -8,16 +8,25 @@ import nl.jqno.equalsverifier.internal.reflection.*; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; +/** + * Creates an instance of a class or record. + */ class InstanceCreator { private final Class type; private final ClassProbe probe; + /** Constructor. */ public InstanceCreator(ClassProbe probe) { this.type = probe.getType(); this.probe = probe; } + /** + * Creates an instance of the given type, with its field set to the given values. If no value + * is given for a specific field, the field will be set to its default value: null for object + * references, 0 for numbers, false for booleans. + */ public T instantiate(Map values) { return probe.isRecord() ? createRecordInstance(values) : createClassInstance(values); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java index 3799febf0..c239077b2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java @@ -9,6 +9,10 @@ import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Rethrow; +/** + * Creates a subject, i.e. an instance of the class that is currently being tested by + * EqualsVerifier. + */ public class SubjectCreator { private final TypeTag typeTag; @@ -18,6 +22,13 @@ public class SubjectCreator { private final ClassProbe classProbe; private final FieldCache fieldCache; + /** + * Constructor. + * + * @param config A configuration object. + * @param valueProvider To provide values for the fields of the subject. + * @param fieldCache Prepared values for the fields of the subject. + */ @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "A cache is inherently mutable") public SubjectCreator( Configuration config, @@ -32,14 +43,34 @@ public SubjectCreator( this.fieldCache = fieldCache; } + /** + * Creates an instance with all values set with prefab values assigned to their respective field + * names or types, or, if no prefab values are given, values created by the + * {@link ValueProvider}. + * + * @return A plain instance. + */ public T plain() { return createInstance(empty()); } + /** + * Creates a {@link #plain()} instance, but with the given field set to its type's default + * value: null for object references, 0 for numbers, false for booleans. + * + * @param field The field to default. + * @return A plain instance with a field defaulted. + */ public T withFieldDefaulted(Field field) { return createInstance(with(field, null)); } + /** + * Creates an instance with all values set to their type's default value: null for object + * references, 0 for numbers, false for booleans. + * + * @return An instance with all fields defaulted. + */ public T withAllFieldsDefaulted() { Map values = empty(); for (Field f : fields()) { @@ -48,6 +79,14 @@ public T withAllFieldsDefaulted() { return createInstance(values); } + /** + * Creates an instance with all values set to their type's default value: null for object + * references, 0 for numbers, false for booleans; except for the given field which is set + * to its {@link #plain()} value. + * + * @param field The field that should not be defaulted. + * @return An instance with all fields defaulted except for {@code field}. + */ public T withAllFieldsDefaultedExcept(Field field) { Map values = empty(); for (Field f : fields()) { @@ -58,10 +97,23 @@ public T withAllFieldsDefaultedExcept(Field field) { return createInstance(values); } + /** + * Creates a {@link #plain()} instance, but with the given field set to the given value. + * + * @param field The field to assign the given value. + * @param value The value to assign to the given field. + * @return A plain instance with one field assigned the given value. + */ public T withFieldSetTo(Field field, Object value) { return createInstance(with(field, value)); } + /** + * Creates a {@link #plain()} instance, but with the given field set to another value. + * + * @param field The field to change. + * @return A plain instance with a field changed. + */ public T withFieldChanged(Field field) { if (FieldProbe.of(field).isStatic()) { return plain(); @@ -70,6 +122,11 @@ public T withFieldChanged(Field field) { return createInstance(with(field, value)); } + /** + * Creates a {@link #plain()} instance, but with all fields set to another value. + * + * @return A plain instance with all fields changed. + */ public T withAllFieldsChanged() { Map values = empty(); for (Field f : fields()) { @@ -79,6 +136,13 @@ public T withAllFieldsChanged() { return createInstance(values); } + /** + * Creates a {@link #plain()} instance, but with all fields that are declared in the current + * class set to another value. Fields coming from the superclasses get their {@link #plain()} + * value. + * + * @return A plain instance with all non-inherited fields changed. + */ public T withAllFieldsShallowlyChanged() { Map values = empty(); for (Field f : nonSuperFields()) { @@ -88,6 +152,13 @@ public T withAllFieldsShallowlyChanged() { return createInstance(values); } + /** + * Creates a new instance with all fields set to the same value as their counterparts from + * {@code original}. + * + * @param original The instance to copy. + * @return A copy of the given original. + */ public T copy(T original) { Map values = empty(); for (Field f : fields()) { @@ -97,6 +168,13 @@ public T copy(T original) { return createInstance(values); } + /** + * Creates a new instance of the superclass of the current class, with all fields that exist + * within that superclass set to the same value as their counterparts from {@code original}. + * + * @param original The instance to copy. + * @return An instance of the givenoriginal's superclass, but otherwise a copy of the original. + */ public Object copyIntoSuperclass(T original) { Map values = empty(); for (Field f : superFields()) { @@ -110,6 +188,17 @@ public Object copyIntoSuperclass(T original) { return superCreator.instantiate(values); } + /** + * Creates a new instance of the given subclass of the current class, with all fields that also + * exist in the current class set to the same value as their counterparts from + * {@code original}. All fields declared in the subclass are set to their {@link #plain()} + * values. + * + * @param A subtype of original's type. + * @param original The instance to copy. + * @param subType A subtype of original's type. + * @return An instance of the given subType, but otherwise a copy of the given original. + */ public S copyIntoSubclass(T original, Class subType) { Map values = empty(); for (Field f : fields()) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java index 7a32b0f8e..eef125f5c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/ValueProvider.java @@ -3,6 +3,22 @@ import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.TypeTag; +/** + * Creator of prefabricated instances of classes. + * + *

These instances are intended to be used to populate a subject, i.e. the class that is + * currently being tested by EqualsVerifier. + * + *

Only creates values ones, and caches them once they've been created. Takes generics into + * account; i.e., {@code List} is different from {@code List}. + */ public interface ValueProvider { + /** + * Returns a tuple of two different prefabricated values of the specified type. + * + * @param The returned tuple will have this generic type. + * @param tag A description of the desired type, including generic parameters. + * @return A tuple of two different values of the given type. + */ Tuple provide(TypeTag tag); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java index d25dd520a..c1dea1ac9 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java @@ -12,6 +12,13 @@ import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; import nl.jqno.equalsverifier.internal.util.Rethrow; +/** + * Creator of prefabricated instances of classes, using a "vintage" strategy for doing so. + * + * Vintage in this case means that it employs the creation strategy that EqualsVerifier has been + * using since its inception. This strategy is quite hacky and messy, and other strategies might + * be preferable. + */ public class VintageValueProvider implements ValueProvider { // I'd like to remove this, but that affects recursion detection it a way I can't yet explain @@ -30,6 +37,7 @@ public VintageValueProvider(FactoryCache factoryCache) { this.factoryCache = factoryCache; } + /** {@inheritDoc} */ @Override public Tuple provide(TypeTag tag) { return Rethrow.rethrow(() -> giveTuple(tag)); @@ -74,31 +82,6 @@ public T giveRedCopy(TypeTag tag) { return this.giveTuple(tag).getRedCopy(); } - /** - * Returns a tuple of two different prefabricated values of the specified type. - * - * @param The returned tuple will have this generic type. - * @param tag A description of the desired type, including generic parameters. - * @return A tuple of two different values of the given type. - */ - public Tuple giveTuple(TypeTag tag) { - return giveTuple(tag, new LinkedHashSet<>()); - } - - /** - * Returns a tuple of two different prefabricated values of the specified type. - * - * @param The returned tuple will have this generic type. - * @param tag A description of the desired type, including generic parameters. - * @param typeStack Keeps track of recursion in the type. - * @return A tuple of two different values of the given type. - */ - @SuppressWarnings("unchecked") - public Tuple giveTuple(TypeTag tag, LinkedHashSet typeStack) { - realizeCacheFor(tag, typeStack); - return (Tuple) valueCache.get(tag); - } - /** * Returns a prefabricated value of the specified type, that is different from the specified * value. @@ -166,6 +149,16 @@ public void realizeCacheFor(TypeTag tag, LinkedHashSet typeStack) { } } + private Tuple giveTuple(TypeTag tag) { + return giveTuple(tag, new LinkedHashSet<>()); + } + + @SuppressWarnings("unchecked") + private Tuple giveTuple(TypeTag tag, LinkedHashSet typeStack) { + realizeCacheFor(tag, typeStack); + return (Tuple) valueCache.get(tag); + } + private Tuple createTuple(TypeTag tag, LinkedHashSet typeStack) { if (typeStack.contains(tag)) { throw new RecursionException(typeStack); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java index a39bbd787..0fb687430 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java @@ -43,6 +43,12 @@ public void sanityTestFactoryIncreasesStringLength() { assertEquals("rrr", f.createValues(null, null, null).getRed()); } + @Test + public void provide() { + Tuple actual = vp.provide(POINT_TAG); + assertEquals(Tuple.of(new Point(42, 42), new Point(1337, 1337), new Point(42, 42)), actual); + } + @Test public void giveRedFromFactory() { assertEquals("r", vp.giveRed(STRING_TAG)); @@ -97,12 +103,6 @@ public void giveRedCopyFromFallbackFactory() { assertNotSame(vp.giveRed(POINT_TAG), actual); } - @Test - public void giveTuple() { - Tuple actual = vp.giveTuple(POINT_TAG); - assertEquals(Tuple.of(new Point(42, 42), new Point(1337, 1337), new Point(42, 42)), actual); - } - @Test public void fallbackDoesNotAffectStaticFields() { int expected = StaticContainer.staticInt; From 2ce2a56a9f6141d5b5f34150c5171ab6fc013788 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 19 Sep 2024 14:19:42 +0200 Subject: [PATCH 63/74] Adds tests for FieldMutator --- .../internal/reflection/FieldMutatorTest.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldMutatorTest.java diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldMutatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldMutatorTest.java new file mode 100644 index 000000000..d6ec87c5d --- /dev/null +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldMutatorTest.java @@ -0,0 +1,65 @@ +package nl.jqno.equalsverifier.internal.reflection; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class FieldMutatorTest { + + private FieldProbe p; + private FieldMutator sut; + private Container o = new Container(); + + @Test + public void setPrimitive() throws NoSuchFieldException { + p = FieldProbe.of(Container.class.getDeclaredField("i")); + sut = new FieldMutator(p); + + assertEquals(10, o.i); + sut.setNewValue(o, 1337); + assertEquals(1337, o.i); + } + + @Test + public void setObject() throws NoSuchFieldException { + p = FieldProbe.of(Container.class.getDeclaredField("s")); + sut = new FieldMutator(p); + + assertEquals("NON-FINAL", o.s); + sut.setNewValue(o, "changed"); + assertEquals("changed", o.s); + } + + @Test + public void dontSetConstantPrimitive() throws NoSuchFieldException { + p = FieldProbe.of(Container.class.getDeclaredField("FINAL_INT")); + sut = new FieldMutator(p); + + assertEquals(42, Container.FINAL_INT); + sut.setNewValue(o, 1337); + assertEquals(42, Container.FINAL_INT); + } + + @Test + public void dontSetConstantObject() throws NoSuchFieldException { + p = FieldProbe.of(Container.class.getDeclaredField("FINAL_STRING")); + sut = new FieldMutator(p); + + assertEquals("FINAL", Container.FINAL_STRING); + sut.setNewValue(o, "changed"); + assertEquals("FINAL", Container.FINAL_STRING); + } + + static class Container { + + private static final int FINAL_INT = 42; + private static final String FINAL_STRING = "FINAL"; + private final int i; + private final String s; + + public Container() { + this.i = 10; + this.s = "NON-FINAL"; + } + } +} From acbc52ec504d028fd36344bae400905e2b57ef7e Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 19 Sep 2024 15:00:10 +0200 Subject: [PATCH 64/74] Adds tests for InstanceCreator --- .../RecordInstanceCreatorTest.java | 32 ++++++++++++++ .../instantiation/InstanceCreatorTest.java | 43 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/RecordInstanceCreatorTest.java create mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreatorTest.java diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/RecordInstanceCreatorTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/RecordInstanceCreatorTest.java new file mode 100644 index 000000000..1eeac75ad --- /dev/null +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/RecordInstanceCreatorTest.java @@ -0,0 +1,32 @@ +package nl.jqno.equalsverifier.internal.reflection.instantiation; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; +import org.junit.jupiter.api.Test; + +public class RecordInstanceCreatorTest { + + @Test + public void instanceCreator() throws NoSuchFieldException { + ClassProbe probe = new ClassProbe<>(SomeRecord.class); + InstanceCreator sut = new InstanceCreator<>(probe); + + Field x = SomeRecord.class.getDeclaredField("x"); + Field z = SomeRecord.class.getDeclaredField("z"); + Map values = new HashMap<>(); + values.put(x, 42); + values.put(z, "42"); + + SomeRecord actual = sut.instantiate(values); + + assertEquals(42, actual.x); + assertEquals(0, actual.y); + assertEquals("42", actual.z); + } + + record SomeRecord(int x, int y, String z) {} +} diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreatorTest.java new file mode 100644 index 000000000..ba7144957 --- /dev/null +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreatorTest.java @@ -0,0 +1,43 @@ +package nl.jqno.equalsverifier.internal.reflection.instantiation; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import nl.jqno.equalsverifier.internal.reflection.ClassProbe; +import org.junit.jupiter.api.Test; + +public class InstanceCreatorTest { + + @Test + public void instanceCreator() throws NoSuchFieldException { + ClassProbe probe = new ClassProbe<>(SomeClass.class); + InstanceCreator sut = new InstanceCreator<>(probe); + + Field x = SomeClass.class.getDeclaredField("x"); + Field z = SomeClass.class.getDeclaredField("z"); + Map values = new HashMap<>(); + values.put(x, 42); + values.put(z, "42"); + + SomeClass actual = sut.instantiate(values); + + assertEquals(42, actual.x); + assertEquals(0, actual.y); + assertEquals("42", actual.z); + } + + static class SomeClass { + + private final int x; + private final int y; + private final String z; + + public SomeClass(int x, int y, String z) { + this.x = x; + this.y = y; + this.z = z; + } + } +} From ca286c6a8be4037e18fda53ff3bf6c2eb762f602 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 19 Sep 2024 16:03:12 +0200 Subject: [PATCH 65/74] Adds tests for SubjectCreator --- .../instantiation/SubjectCreatorTest.java | 308 ++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreatorTest.java diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreatorTest.java new file mode 100644 index 000000000..d98d287e7 --- /dev/null +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreatorTest.java @@ -0,0 +1,308 @@ +package nl.jqno.equalsverifier.internal.reflection.instantiation; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; + +import java.lang.reflect.Field; +import java.util.Objects; +import nl.jqno.equalsverifier.internal.reflection.FieldCache; +import nl.jqno.equalsverifier.internal.reflection.Tuple; +import nl.jqno.equalsverifier.internal.reflection.TypeTag; +import nl.jqno.equalsverifier.internal.util.Configuration; +import nl.jqno.equalsverifier.internal.util.ConfigurationHelper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class SubjectCreatorTest { + + private static final int I_RED = 42; + private static final int I_BLUE = 1337; + private static final String S_RED = "abc"; + private static final String S_BLUE = "xyz"; + + private Configuration config = ConfigurationHelper.emptyConfiguration( + SomeClass.class + ); + private ValueProvider valueProvider = new SubjectCreatorTestValueProvider(); + private FieldCache fieldCache = new FieldCache(); + private SubjectCreator sut = new SubjectCreator<>(config, valueProvider, fieldCache); + + private Field fieldX; + private Field fieldI; + private Field fieldS; + + private SomeClass expected; + private SomeClass actual; + + @BeforeEach + public void setup() throws NoSuchFieldException { + fieldX = SomeSuper.class.getDeclaredField("x"); + fieldI = SomeClass.class.getDeclaredField("i"); + fieldS = SomeClass.class.getDeclaredField("s"); + } + + @Test + public void sanity() {} + + @Test + public void plain() { + expected = new SomeClass(I_RED, I_RED, S_RED); + actual = sut.plain(); + + assertEquals(expected, actual); + } + + @Test + public void withFieldDefaulted_super() { + expected = new SomeClass(0, I_RED, S_RED); + actual = sut.withFieldDefaulted(fieldX); + + assertEquals(expected, actual); + } + + @Test + public void withFieldDefaulted_primitive() { + expected = new SomeClass(I_RED, 0, S_RED); + actual = sut.withFieldDefaulted(fieldI); + + assertEquals(expected, actual); + } + + @Test + public void withFieldDefaulted_object() { + expected = new SomeClass(I_RED, I_RED, null); + actual = sut.withFieldDefaulted(fieldS); + + assertEquals(expected, actual); + } + + @Test + public void withAllFieldsDefaulted() { + expected = new SomeClass(0, 0, null); + actual = sut.withAllFieldsDefaulted(); + + assertEquals(expected, actual); + } + + @Test + public void withAllFieldsDefaultedExcept() { + expected = new SomeClass(0, I_RED, null); + actual = sut.withAllFieldsDefaultedExcept(fieldI); + + assertEquals(expected, actual); + } + + @Test + public void withFieldSetTo_super() { + expected = new SomeClass(99, I_RED, S_RED); + actual = sut.withFieldSetTo(fieldX, 99); + + assertEquals(expected, actual); + } + + @Test + public void withFieldSetTo_primitive() { + expected = new SomeClass(I_RED, 99, S_RED); + actual = sut.withFieldSetTo(fieldI, 99); + + assertEquals(expected, actual); + } + + @Test + public void withFieldSetTo_object() { + expected = new SomeClass(I_RED, I_RED, "value"); + actual = sut.withFieldSetTo(fieldS, "value"); + + assertEquals(expected, actual); + } + + @Test + public void withFieldChanged_super() { + expected = new SomeClass(I_BLUE, I_RED, S_RED); + actual = sut.withFieldChanged(fieldX); + + assertEquals(expected, actual); + } + + @Test + public void withFieldChanged_primitive() { + expected = new SomeClass(I_RED, I_BLUE, S_RED); + actual = sut.withFieldChanged(fieldI); + + assertEquals(expected, actual); + } + + @Test + public void withFieldChanged_object() { + expected = new SomeClass(I_RED, I_RED, S_BLUE); + actual = sut.withFieldChanged(fieldS); + + assertEquals(expected, actual); + } + + @Test + public void withAllFieldsChanged() { + expected = new SomeClass(I_BLUE, I_BLUE, S_BLUE); + actual = sut.withAllFieldsChanged(); + + assertEquals(expected, actual); + } + + @Test + public void withAllFieldsShallowlyChanged() { + expected = new SomeClass(I_RED, I_BLUE, S_BLUE); + actual = sut.withAllFieldsShallowlyChanged(); + + assertEquals(expected, actual); + } + + @Test + public void copy() { + expected = new SomeClass(I_RED, I_RED, S_RED); + SomeClass original = new SomeClass(I_RED, I_RED, S_RED); + actual = sut.copy(original); + + assertEquals(expected, actual); + assertNotSame(expected, actual); + } + + @Test + public void copyIntoSuperclass() { + SomeSuper superExpected = new SomeSuper(I_RED); + SomeClass original = new SomeClass(I_RED, I_RED, S_RED); + Object superActual = sut.copyIntoSuperclass(original); + + assertEquals(superExpected, superActual); + assertEquals(SomeSuper.class, superActual.getClass()); + } + + @Test + public void copyIntoSubclass() { + expected = new SomeSub(I_RED, I_RED, S_RED, null); + SomeClass original = new SomeClass(I_RED, I_RED, S_RED); + actual = sut.copyIntoSubclass(original, SomeSub.class); + + assertEquals(expected, actual); + assertEquals(SomeSub.class, actual.getClass()); + } + + static class SubjectCreatorTestValueProvider implements ValueProvider { + + public Tuple provide(TypeTag tag) { + if (int.class.equals(tag.getType())) { + return Tuple.of(I_RED, I_BLUE, I_RED); + } + if (String.class.equals(tag.getType())) { + return Tuple.of(S_RED, S_BLUE, new String(S_RED)); + } + throw new IllegalStateException(); + } + } + + static class SomeSuper { + + final int x; + + public SomeSuper(int x) { + this.x = x; + } + + public boolean canEqual(Object obj) { + return obj instanceof SomeSuper; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SomeSuper)) { + return false; + } + SomeSuper other = (SomeSuper) obj; + return other.canEqual(this) && x == other.x; + } + + @Override + public int hashCode() { + return Objects.hash(x); + } + + @Override + public String toString() { + return "SomeSuper: " + x; + } + } + + static class SomeClass extends SomeSuper { + + final int i; + final String s; + + public SomeClass(int x, int i, String s) { + super(x); + this.i = i; + this.s = s; + } + + @Override + public boolean canEqual(Object obj) { + return obj instanceof SomeClass; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SomeClass)) { + return false; + } + SomeClass other = (SomeClass) obj; + return ( + other.canEqual(this) && + super.equals(other) && + Objects.equals(i, other.i) && + Objects.equals(s, other.s) + ); + } + + @Override + public int hashCode() { + return Objects.hash(x, i, s); + } + + @Override + public String toString() { + return "SomeClass: " + x + "," + i + "," + s; + } + } + + static class SomeSub extends SomeClass { + + final String q; + + public SomeSub(int x, int i, String s, String q) { + super(x, i, s); + this.q = q; + } + + @Override + public boolean canEqual(Object obj) { + return obj instanceof SomeSub; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SomeSub)) { + return false; + } + SomeSub other = (SomeSub) obj; + return other.canEqual(this) && super.equals(other) && Objects.equals(q, other.q); + } + + @Override + public int hashCode() { + return Objects.hash(x, i, s, q); + } + + @Override + public String toString() { + return "SomeSub: " + x + "," + i + "," + s + "," + q; + } + } +} From e4ae447c37e70ff77fe110ba88663747eb0e7331 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Thu, 19 Sep 2024 16:14:26 +0200 Subject: [PATCH 66/74] Mentions withPrefabValuesForField, ZERO_FIELDS deprecation, and internal refactorings in CHANGELOG --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfdec83db..ff7d0cc53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- #withPrefabValuesForField method, where you can assign prefab values to a field instead of to a class. The values will then be used for that field only. ([Issue 747](https://github.com/jqno/equalsverifier/issues/747)) + +### Changed + +- The internal instantiation logic has been heavily refactored. + +### Deprecated + +- `Warning.ZERO_FIELDS`: the use case for this Warning is better handled by the new `#withPrefabValuesForField` method. + ## [3.16.2] - 2024-08-23 ### Changed From adee6eacc8ae911f6ec5ade6c5ab9ad7fa2c20f9 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 20 Sep 2024 08:00:45 +0200 Subject: [PATCH 67/74] Enables verbose logging for PITest troubleshooting --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 4a5a69a64..e04567481 100644 --- a/pom.xml +++ b/pom.xml @@ -335,6 +335,7 @@ + true ${argline.preview} From f02dd32687e5dfbbd8aea6c9bb3419b7b8d85e08 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 20 Sep 2024 15:50:07 +0200 Subject: [PATCH 68/74] Moves dependencies to main pom for the benefit of PITest --- equalsverifier-core/pom.xml | 12 ------------ pom.xml | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/equalsverifier-core/pom.xml b/equalsverifier-core/pom.xml index 5e4c670bc..32ab9bf1b 100644 --- a/equalsverifier-core/pom.xml +++ b/equalsverifier-core/pom.xml @@ -93,18 +93,6 @@ ${version.spotbugs} provided - - joda-time - joda-time - ${version.joda-time} - provided - - - com.google.guava - guava - ${version.guava} - provided - diff --git a/pom.xml b/pom.xml index e04567481..9e504c3e6 100644 --- a/pom.xml +++ b/pom.xml @@ -214,6 +214,18 @@ ${version.bytebuddy} test + + joda-time + joda-time + ${version.joda-time} + provided + + + com.google.guava + guava + ${version.guava} + provided + From 673c82ff326d2f543c68d741273be35f3950f681 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Fri, 20 Sep 2024 15:59:25 +0200 Subject: [PATCH 69/74] Disables verbose logging for PITest troubleshooting --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9e504c3e6..ca94acb02 100644 --- a/pom.xml +++ b/pom.xml @@ -347,7 +347,6 @@ - true ${argline.preview} From d526128ddb6a7bd5371c9994c2a3b03de891526b Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sat, 21 Sep 2024 09:59:17 +0200 Subject: [PATCH 70/74] Makes improvements suggested by PITest --- .../api/SingleTypeEqualsVerifierApi.java | 1 - .../extra_features/JpaLazyEntityTest.java | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index 940778c31..cd28c31cd 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -127,7 +127,6 @@ public SingleTypeEqualsVerifierApi withPrefabValuesForField( S red, S blue ) { - Validations.validateFieldNameExists(type, fieldName, actualFields); PrefabValuesApi.addPrefabValuesForField(fieldCache, type, fieldName, red, blue); withNonnullFields(fieldName); return this; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java index 4c926eae1..e1a98e78a 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java @@ -17,6 +17,13 @@ public void gettersAreUsed() { EqualsVerifier.forClass(CorrectJpaLazyFieldContainer.class).verify(); } + @Test + public void basicGetterAbsent() { + ExpectedException + .when(() -> EqualsVerifier.forClass(LazyFieldWithoutGetterContainer.class).verify()) + .assertFailure(); + } + @Test public void basicGetterNotUsed_givenEagerLoading() { EqualsVerifier.forClass(CorrectBasicJpaEagerFieldContainer.class).verify(); @@ -260,6 +267,27 @@ public int hashCode() { } } + @Entity + static class LazyFieldWithoutGetterContainer { + + @OneToMany + private String basic; + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LazyFieldWithoutGetterContainer)) { + return false; + } + LazyFieldWithoutGetterContainer other = (LazyFieldWithoutGetterContainer) obj; + return Objects.equals(basic, other.basic); + } + + @Override + public int hashCode() { + return Objects.hash(basic); + } + } + @Entity static class CorrectBasicJpaEagerFieldContainer { From 0ff8a8ee54be5613f809e7fd88720476707077ac Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sun, 22 Sep 2024 19:48:40 +0200 Subject: [PATCH 71/74] Adds tests for FieldProbe --- .../internal/reflection/FieldProbeTest.java | 123 +++++++++++------- 1 file changed, 78 insertions(+), 45 deletions(-) diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java index 8208b7839..c7f23c7a1 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/FieldProbeTest.java @@ -8,6 +8,9 @@ import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.*; import org.junit.jupiter.api.Test; +/* + * FieldProbe.isAnnotatedNonnull() is tested in AnnotationNonnullTest + */ public class FieldProbeTest { private static final String FIELD_NAME = "field"; @@ -23,153 +26,183 @@ public void getField() throws NoSuchFieldException { @Test public void getType() { - ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(ObjectContainer.class, FIELD_NAME); assertEquals(Object.class, probe.getType()); } @Test public void getName() { - ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(ObjectContainer.class, FIELD_NAME); assertEquals(FIELD_NAME, probe.getName()); } @Test public void isNotPrimitive() { - ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(ObjectContainer.class, FIELD_NAME); assertFalse(probe.isPrimitive()); } @Test public void isPrimitive() { - PrimitiveContainer foo = new PrimitiveContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(PrimitiveContainer.class, FIELD_NAME); assertTrue(probe.isPrimitive()); } @Test public void isNotFinal() { - ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(ObjectContainer.class, FIELD_NAME); assertFalse(probe.isFinal()); } @Test public void isFinal() { - FinalContainer foo = new FinalContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(FinalContainer.class, FIELD_NAME); assertTrue(probe.isFinal()); } @Test public void isNotStatic() { - ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(ObjectContainer.class, FIELD_NAME); assertFalse(probe.isStatic()); } @Test public void isStatic() { - StaticContainer foo = new StaticContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(StaticContainer.class, FIELD_NAME); assertTrue(probe.isStatic()); } @Test public void isNotTransient() { - ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(ObjectContainer.class, FIELD_NAME); assertFalse(probe.isTransient()); } @Test public void isTransient() { - TransientContainer foo = new TransientContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(TransientContainer.class, FIELD_NAME); assertTrue(probe.isTransient()); } @Test public void isNotEnum() { - PrimitiveContainer foo = new PrimitiveContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(PrimitiveContainer.class, FIELD_NAME); assertFalse(probe.isEmptyOrSingleValueEnum()); } @Test public void isEnumButNotSingleValue() { - EnumContainer foo = new EnumContainer(); - FieldProbe probe = getProbeFor(foo, "twoElementEnum"); + FieldProbe probe = getProbeFor(EnumContainer.class, "twoElementEnum"); assertFalse(probe.isEmptyOrSingleValueEnum()); } @Test public void isSingleValueEnum() { - EnumContainer foo = new EnumContainer(); - FieldProbe probe = getProbeFor(foo, "oneElementEnum"); + FieldProbe probe = getProbeFor(EnumContainer.class, "oneElementEnum"); assertTrue(probe.isEmptyOrSingleValueEnum()); } @Test public void isEmptyEnum() { - EnumContainer foo = new EnumContainer(); - FieldProbe probe = getProbeFor(foo, "emptyEnum"); + FieldProbe probe = getProbeFor(EnumContainer.class, "emptyEnum"); assertTrue(probe.isEmptyOrSingleValueEnum()); } @Test public void canBeDefault_forObject() { - ObjectContainer foo = new ObjectContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(ObjectContainer.class, FIELD_NAME); assertTrue(probe.canBeDefault(config)); } @Test public void canBeDefault_primitive() { - PrimitiveContainer foo = new PrimitiveContainer(); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + FieldProbe probe = getProbeFor(PrimitiveContainer.class, FIELD_NAME); assertTrue(probe.canBeDefault(config)); } @Test public void canBeDefault_primitiveWithPrefabbedField() { - PrimitiveContainer foo = new PrimitiveContainer(); config = - ConfigurationHelper.emptyConfigurationWithPrefabbedFields(foo.getClass(), FIELD_NAME); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + ConfigurationHelper.emptyConfigurationWithPrefabbedFields( + PrimitiveContainer.class, + FIELD_NAME + ); + FieldProbe probe = getProbeFor(PrimitiveContainer.class, FIELD_NAME); assertFalse(probe.canBeDefault(config)); } @Test public void canBeDefault_isMentionedExplicitly() { - ObjectContainer foo = new ObjectContainer(); config = - ConfigurationHelper.emptyConfigurationWithNonnullFields(foo.getClass(), FIELD_NAME); - FieldProbe probe = getAccessorFor(foo, FIELD_NAME); + ConfigurationHelper.emptyConfigurationWithNonnullFields( + ObjectContainer.class, + FIELD_NAME + ); + FieldProbe probe = getProbeFor(ObjectContainer.class, FIELD_NAME); assertFalse(probe.canBeDefault(config)); } @Test public void canBeDefault_annotated() { - NonNullContainer foo = new NonNullContainer(); config = - ConfigurationHelper.emptyConfigurationWithNonnullFields(foo.getClass(), FIELD_NAME); - FieldProbe probe = getProbeFor(foo, FIELD_NAME); + ConfigurationHelper.emptyConfigurationWithNonnullFields( + NonNullContainer.class, + FIELD_NAME + ); + FieldProbe probe = getProbeFor(NonNullContainer.class, FIELD_NAME); assertFalse(probe.canBeDefault(config)); } - private FieldProbe getProbeFor(Object object, String fieldName) { - return getAccessorFor(object, fieldName); + @Test + public void canBeModifiedReflectively_synthetic() { + FieldProbe probe = getProbeFor(NonStaticInner.class, "this$0"); + assertFalse(probe.canBeModifiedReflectively()); } - private FieldProbe getAccessorFor(Object object, String fieldName) { + @Test + public void canBeModifiedReflectively_staticFinal() { + FieldProbe publicStaticFinal = getProbeFor(ModifierMix.class, "PUBLIC_STATIC_FINAL"); + assertFalse(publicStaticFinal.canBeModifiedReflectively()); + } + + @Test + public void canBeModifiedReflectively_static() { + FieldProbe publicStatic = getProbeFor(ModifierMix.class, "publicStatic"); + assertTrue(publicStatic.canBeModifiedReflectively()); + } + + @Test + public void canBeModifiedReflectively_final() { + FieldProbe publicFinal = getProbeFor(ModifierMix.class, "publicFinal"); + assertTrue(publicFinal.canBeModifiedReflectively()); + } + + @Test + public void canBeModifiedReflectively_noModifiers() { + FieldProbe publicNothingElse = getProbeFor(ModifierMix.class, "publicNothingElse"); + assertTrue(publicNothingElse.canBeModifiedReflectively()); + } + + private FieldProbe getProbeFor(Class type, String fieldName) { try { - Field field = object.getClass().getDeclaredField(fieldName); + Field field = type.getDeclaredField(fieldName); return FieldProbe.of(field); } catch (NoSuchFieldException e) { throw new IllegalArgumentException("fieldName: " + fieldName); } } + + class NonStaticInner {} + + static class ModifierMix { + + public static final int PUBLIC_STATIC_FINAL = -1; + public static int publicStatic = 1; + public final int publicFinal; + public int publicNothingElse; + + public ModifierMix(int alsoYes) { + this.publicFinal = alsoYes; + } + } } From 60cb1e600ead151a68cb564699d6f74eb8e7f072 Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Sun, 22 Sep 2024 19:48:54 +0200 Subject: [PATCH 72/74] Removes NonnullAnnotationVerifier --- .../NonnullAnnotationVerifier.java | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/annotations/NonnullAnnotationVerifier.java diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/annotations/NonnullAnnotationVerifier.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/annotations/NonnullAnnotationVerifier.java deleted file mode 100644 index f51469ffb..000000000 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/annotations/NonnullAnnotationVerifier.java +++ /dev/null @@ -1,35 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.annotations; - -import static nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations.*; - -import java.lang.reflect.Field; - -/** Utility class that checks whether a field is marked with an Nonnull annotation of some sort. */ -public final class NonnullAnnotationVerifier { - - private NonnullAnnotationVerifier() {} - - /** - * Checks whether the given field is marked with an Nonnull annotation, whether directly, or - * through some default annotation mechanism. - * - * @param field The field to be checked. - * @param annotationCache To provide access to the annotations on the field and the field's - * class - * @return True if the field is to be treated as Nonnull. - */ - public static boolean fieldIsNonnull(Field field, AnnotationCache annotationCache) { - Class type = field.getDeclaringClass(); - if (annotationCache.hasFieldAnnotation(type, field.getName(), NONNULL)) { - return true; - } - if (annotationCache.hasFieldAnnotation(type, field.getName(), NULLABLE)) { - return false; - } - return ( - annotationCache.hasClassAnnotation(type, FINDBUGS1X_DEFAULT_ANNOTATION_NONNULL) || - annotationCache.hasClassAnnotation(type, JSR305_DEFAULT_ANNOTATION_NONNULL) || - annotationCache.hasClassAnnotation(type, DEFAULT_ANNOTATION_NONNULL) - ); - } -} From 000d5fbe0b2d3fb59b08bf5992c88a23fc5611ed Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Mon, 23 Sep 2024 16:05:19 +0200 Subject: [PATCH 73/74] Makes Objenesis dependency explicit --- .../reflection/RecordInstantiatorTest.java | 3 +- .../RecordInstanceCreatorTest.java | 3 +- .../RecordObjectAccessorCopyingTest.java | 8 +++- .../RecordObjectAccessorScramblingTest.java | 3 +- .../vintage/RecordObjectAccessorTest.java | 22 ++++++--- .../ConfiguredEqualsVerifier.java | 6 ++- .../api/SingleTypeEqualsVerifierApi.java | 29 +++++++++--- .../internal/reflection/Instantiator.java | 19 ++++---- .../instantiation/InstanceCreator.java | 45 ++++++++++++++----- .../instantiation/SubjectCreator.java | 42 ++++++----------- .../instantiation/VintageValueProvider.java | 7 ++- .../reflection/vintage/ClassAccessor.java | 16 +++++-- .../vintage/InPlaceObjectAccessor.java | 5 ++- .../reflection/vintage/ObjectAccessor.java | 4 +- .../vintage/RecordObjectAccessor.java | 3 +- .../factories/FallbackFactory.java | 9 +++- .../equalsverifier/internal/util/Context.java | 9 ++-- .../internal/util/ObjenesisWrapper.java | 29 ------------ .../internal/util/PrefabValuesApi.java | 7 ++- .../operational/WithResetCachesTest.java | 20 --------- .../internal/reflection/InstantiatorTest.java | 28 +++++++----- .../AnnotationCacheBuilderTest.java | 3 +- .../instantiation/InstanceCreatorTest.java | 38 +++++++++++++--- .../instantiation/SubjectCreatorTest.java | 10 ++++- .../VintageValueProviderCreatorTest.java | 14 +++--- .../VintageValueProviderTest.java | 13 +++--- .../reflection/vintage/ClassAccessorTest.java | 34 +++++++++----- .../InPlaceObjectAccessorCopyingTest.java | 8 +++- .../InPlaceObjectAccessorScramblingTest.java | 8 +++- .../factories/FallbackFactoryTest.java | 7 ++- .../factories/MapFactoryTest.java | 3 +- .../factories/SimpleGenericFactoryTest.java | 3 +- .../JavaFxFactoryProviderTest.java | 3 +- .../internal/util/FormatterTest.java | 19 +++++--- 34 files changed, 296 insertions(+), 184 deletions(-) delete mode 100644 equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/ObjenesisWrapper.java delete mode 100644 equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithResetCachesTest.java diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordInstantiatorTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordInstantiatorTest.java index 63b3f010a..be0c04dcf 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordInstantiatorTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/RecordInstantiatorTest.java @@ -3,12 +3,13 @@ import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; +import org.objenesis.ObjenesisStd; public class RecordInstantiatorTest { @Test public void instantiateRecord() { - Instantiator instantiator = Instantiator.of(SimpleRecord.class); + Instantiator instantiator = Instantiator.of(SimpleRecord.class, new ObjenesisStd()); Object simpleRecord = instantiator.instantiate(); assertEquals(SimpleRecord.class, simpleRecord.getClass()); } diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/RecordInstanceCreatorTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/RecordInstanceCreatorTest.java index 1eeac75ad..8bced9fd4 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/RecordInstanceCreatorTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/RecordInstanceCreatorTest.java @@ -7,13 +7,14 @@ import java.util.Map; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import org.junit.jupiter.api.Test; +import org.objenesis.ObjenesisStd; public class RecordInstanceCreatorTest { @Test public void instanceCreator() throws NoSuchFieldException { ClassProbe probe = new ClassProbe<>(SomeRecord.class); - InstanceCreator sut = new InstanceCreator<>(probe); + InstanceCreator sut = new InstanceCreator<>(probe, new ObjenesisStd()); Field x = SomeRecord.class.getDeclaredField("x"); Field z = SomeRecord.class.getDeclaredField("z"); diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java index bec1a8f20..25c904414 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorCopyingTest.java @@ -8,9 +8,13 @@ import nl.jqno.equalsverifier.internal.reflection.FieldIterable; import nl.jqno.equalsverifier.internal.reflection.Instantiator; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class RecordObjectAccessorCopyingTest { + private Objenesis objenesis = new ObjenesisStd(); + @Test public void copyHappyPath() { Object original = instantiate(SimpleRecord.class); @@ -41,11 +45,11 @@ private RecordObjectAccessor create(T object) { } private T instantiate(Class type) { - return Instantiator.of(type).instantiate(); + return Instantiator.of(type, objenesis).instantiate(); } private T copyOf(T from) { - return create(from).copy(); + return create(from).copy(objenesis); } record SimpleRecord(int i, String s) {} diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java index 80afbd8e8..830186672 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorScramblingTest.java @@ -12,6 +12,7 @@ import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.ObjenesisStd; public class RecordObjectAccessorScramblingTest { @@ -22,7 +23,7 @@ public class RecordObjectAccessorScramblingTest { @BeforeEach public void setup() throws Exception { factoryCache = JavaApiPrefabValues.build(); - valueProvider = new VintageValueProvider(factoryCache); + valueProvider = new VintageValueProvider(factoryCache, new ObjenesisStd()); } @Test diff --git a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java index b09f96b92..dbcbb904f 100644 --- a/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java +++ b/equalsverifier-16/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessorTest.java @@ -14,10 +14,13 @@ import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class RecordObjectAccessorTest { private static final LinkedHashSet EMPTY_TYPE_STACK = new LinkedHashSet<>(); + private Objenesis objenesis; private Object recordInstance; @BeforeEach @@ -25,6 +28,7 @@ public void setUp() throws Exception { Constructor constructor = SimpleRecord.class.getDeclaredConstructor(int.class, String.class); constructor.setAccessible(true); + objenesis = new ObjenesisStd(); recordInstance = constructor.newInstance(42, "hello"); } @@ -42,29 +46,35 @@ public void get() { @Test public void fail_whenConstructorThrowsNpe() { - Object instance = Instantiator.of(NpeThrowingConstructorRecord.class).instantiate(); + Object instance = Instantiator + .of(NpeThrowingConstructorRecord.class, objenesis) + .instantiate(); ExpectedException - .when(() -> accessorFor(instance).copy()) + .when(() -> accessorFor(instance).copy(objenesis)) .assertThrows(ReflectionException.class) .assertMessageContains("Record:", "failed to run constructor", "Warning.NULL_FIELDS"); } @Test public void fail_whenConstructorThrowsOnZero() { - Object instance = Instantiator.of(ZeroThrowingConstructorRecord.class).instantiate(); + Object instance = Instantiator + .of(ZeroThrowingConstructorRecord.class, objenesis) + .instantiate(); ExpectedException - .when(() -> accessorFor(instance).copy()) + .when(() -> accessorFor(instance).copy(objenesis)) .assertThrows(ReflectionException.class) .assertMessageContains("Record:", "failed to run constructor", "Warning.ZERO_FIELDS"); } @Test public void fail_whenConstructorThrowsOnSomethingElse() { - Object instance = Instantiator.of(OtherThrowingConstructorRecord.class).instantiate(); + Object instance = Instantiator + .of(OtherThrowingConstructorRecord.class, objenesis) + .instantiate(); - VintageValueProvider vp = new VintageValueProvider(JavaApiPrefabValues.build()); + VintageValueProvider vp = new VintageValueProvider(JavaApiPrefabValues.build(), objenesis); ExpectedException .when(() -> accessorFor(instance).scramble(vp, TypeTag.NULL, EMPTY_TYPE_STACK)) .assertThrows(ReflectionException.class) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java index fb500d9ff..5574cfb43 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java @@ -14,6 +14,8 @@ import nl.jqno.equalsverifier.internal.util.ListBuilders; import nl.jqno.equalsverifier.internal.util.PrefabValuesApi; import nl.jqno.equalsverifier.internal.util.Validations; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public final class ConfiguredEqualsVerifier implements EqualsVerifierApi { @@ -21,6 +23,7 @@ public final class ConfiguredEqualsVerifier implements EqualsVerifierApi { private final FactoryCache factoryCache; private boolean usingGetClass; private Function fieldnameToGetter; + private final Objenesis objenesis = new ObjenesisStd(); /** Constructor. */ public ConfiguredEqualsVerifier() { @@ -64,7 +67,7 @@ public ConfiguredEqualsVerifier suppress(Warning... warnings) { /** {@inheritDoc} */ @Override public ConfiguredEqualsVerifier withPrefabValues(Class otherType, S red, S blue) { - PrefabValuesApi.addPrefabValues(factoryCache, otherType, red, blue); + PrefabValuesApi.addPrefabValues(factoryCache, objenesis, otherType, red, blue); return this; } @@ -125,6 +128,7 @@ public SingleTypeEqualsVerifierApi forClass(Class type) { type, EnumSet.copyOf(warningsToSuppress), factoryCache, + objenesis, usingGetClass, fieldnameToGetter ); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java index cd28c31cd..c09b94d68 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/api/SingleTypeEqualsVerifierApi.java @@ -13,6 +13,8 @@ import nl.jqno.equalsverifier.internal.reflection.FieldCache; import nl.jqno.equalsverifier.internal.util.*; import nl.jqno.equalsverifier.internal.util.Formatter; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; /** * Helps to construct an {@link EqualsVerifier} test with a fluent API. @@ -39,6 +41,7 @@ public class SingleTypeEqualsVerifierApi implements EqualsVerifierApi { private Set ignoredAnnotationClassNames = new HashSet<>(); private List equalExamples = new ArrayList<>(); private List unequalExamples = new ArrayList<>(); + private final Objenesis objenesis; /** * Constructor. @@ -46,8 +49,19 @@ public class SingleTypeEqualsVerifierApi implements EqualsVerifierApi { * @param type The class for which the {@code equals} method should be tested. */ public SingleTypeEqualsVerifierApi(Class type) { + this(type, new ObjenesisStd()); + } + + /** + * Constructor. + * + * @param type The class for which the {@code equals} method should be tested. + * @param objenesis To instantiate non-record classes. + */ + public SingleTypeEqualsVerifierApi(Class type, Objenesis objenesis) { this.type = type; - actualFields = FieldNameExtractor.extractFieldNames(type); + this.actualFields = FieldNameExtractor.extractFieldNames(type); + this.objenesis = objenesis; } /** @@ -56,6 +70,7 @@ public SingleTypeEqualsVerifierApi(Class type) { * @param type The class for which the {@code equals} method should be tested. * @param warningsToSuppress A list of warnings to suppress in {@code EqualsVerifier}. * @param factoryCache Factories that can be used to create values. + * @param objenesis To instantiate non-record classes. * @param usingGetClass Whether {@code getClass} is used in the implementation of the {@code * equals} method, instead of an {@code instanceof} check. * @param converter A function that converts from field name to getter name. @@ -64,10 +79,11 @@ public SingleTypeEqualsVerifierApi( Class type, EnumSet warningsToSuppress, FactoryCache factoryCache, + Objenesis objenesis, boolean usingGetClass, Function converter ) { - this(type); + this(type, objenesis); this.warningsToSuppress = EnumSet.copyOf(warningsToSuppress); this.factoryCache = this.factoryCache.merge(factoryCache); this.usingGetClass = usingGetClass; @@ -83,7 +99,7 @@ public SingleTypeEqualsVerifierApi( List equalExamples, List unequalExamples ) { - this(type); + this(type, new ObjenesisStd()); this.equalExamples = equalExamples; this.unequalExamples = unequalExamples; } @@ -105,7 +121,7 @@ public SingleTypeEqualsVerifierApi suppress(Warning... warnings) { /** {@inheritDoc} */ @Override public SingleTypeEqualsVerifierApi withPrefabValues(Class otherType, S red, S blue) { - PrefabValuesApi.addPrefabValues(factoryCache, otherType, red, blue); + PrefabValuesApi.addPrefabValues(factoryCache, objenesis, otherType, red, blue); return this; } @@ -127,7 +143,7 @@ public SingleTypeEqualsVerifierApi withPrefabValuesForField( S red, S blue ) { - PrefabValuesApi.addPrefabValuesForField(fieldCache, type, fieldName, red, blue); + PrefabValuesApi.addPrefabValuesForField(fieldCache, objenesis, type, fieldName, red, blue); withNonnullFields(fieldName); return this; } @@ -409,14 +425,13 @@ private String buildErrorMessage(String description, boolean showUrl) { } private void performVerification() { - ObjenesisWrapper.reset(); if (type.isEnum() || type.isInterface()) { return; } Validations.validateClassCanBeVerified(type); Configuration config = buildConfig(); - Context context = new Context<>(config, factoryCache, fieldCache); + Context context = new Context<>(config, factoryCache, fieldCache, objenesis); Validations.validateProcessedAnnotations( type, config.getAnnotationCache(), diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Instantiator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Instantiator.java index bd89aa77d..894fd53c2 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Instantiator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/Instantiator.java @@ -13,7 +13,7 @@ import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; import net.bytebuddy.dynamic.scaffold.TypeValidation; -import nl.jqno.equalsverifier.internal.util.ObjenesisWrapper; +import org.objenesis.Objenesis; /** * Instantiates objects of a given class. @@ -33,10 +33,12 @@ public final class Instantiator { private static final String FALLBACK_PACKAGE_NAME = getPackageName(Instantiator.class); private final Class type; + private final Objenesis objenesis; /** Private constructor. Call {@link #of(Class)} to instantiate. */ - private Instantiator(Class type) { + private Instantiator(Class type, Objenesis objenesis) { this.type = type; + this.objenesis = objenesis; } /** @@ -44,17 +46,18 @@ private Instantiator(Class type) { * * @param The class on which {@link Instantiator} operates. * @param type The class on which {@link Instantiator} operates. Should be the same as T. + * @param objenesis To instantiate non-record classes. * @return An {@link Instantiator} for {@link #type}. */ - public static Instantiator of(Class type) { + public static Instantiator of(Class type, Objenesis objenesis) { if (SealedTypesHelper.isSealed(type)) { Class concrete = SealedTypesHelper.findInstantiableSubclass(type).get(); - return Instantiator.of(concrete); + return Instantiator.of(concrete, objenesis); } if (Modifier.isAbstract(type.getModifiers())) { - return new Instantiator<>(giveDynamicSubclass(type, "", b -> b)); + return new Instantiator<>(giveDynamicSubclass(type, "", b -> b), objenesis); } - return new Instantiator<>(type); + return new Instantiator<>(type, objenesis); } /** @@ -66,7 +69,7 @@ public static Instantiator of(Class type) { * @return An object of type T. */ public T instantiate() { - return ObjenesisWrapper.getObjenesis().newInstance(type); + return objenesis.newInstance(type); } /** @@ -76,7 +79,7 @@ public T instantiate() { */ public T instantiateAnonymousSubclass() { Class proxyClass = giveDynamicSubclass(type); - return ObjenesisWrapper.getObjenesis().newInstance(proxyClass); + return objenesis.newInstance(proxyClass); } public static Class giveDynamicSubclass(Class superclass) { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java index 3b3b8223f..b26966398 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreator.java @@ -1,36 +1,61 @@ package nl.jqno.equalsverifier.internal.reflection.instantiation; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.BiConsumer; import nl.jqno.equalsverifier.internal.reflection.*; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; +import org.objenesis.Objenesis; /** * Creates an instance of a class or record. */ -class InstanceCreator { +public class InstanceCreator { private final Class type; private final ClassProbe probe; + private final Objenesis objenesis; - /** Constructor. */ - public InstanceCreator(ClassProbe probe) { + /** + * Constructor. + * + * @param probe Represents the class to instantiate. + * @param objenesis To instantiate non-record classes. + */ + public InstanceCreator(ClassProbe probe, Objenesis objenesis) { this.type = probe.getType(); this.probe = probe; + this.objenesis = objenesis; } /** * Creates an instance of the given type, with its field set to the given values. If no value * is given for a specific field, the field will be set to its default value: null for object * references, 0 for numbers, false for booleans. + * + * @param values Values to assign to the instance's fields. + * @return An instance with assigned values. */ public T instantiate(Map values) { return probe.isRecord() ? createRecordInstance(values) : createClassInstance(values); } + /** + * Creates a new instance with all fields set to the same value as their counterparts from + * {@code original}. + * + * @param original The instance to copy. + * @return A copy of the given original. + */ + public T copy(Object original) { + Map values = new HashMap<>(); + for (Field f : fields(original.getClass())) { + Object value = FieldProbe.of(f).getValue(original); + values.put(f, value); + } + return instantiate(values); + } + private T createRecordInstance(Map values) { List params = new ArrayList<>(); traverseFields(values, (f, v) -> params.add(v)); @@ -39,7 +64,7 @@ private T createRecordInstance(Map values) { } private T createClassInstance(Map values) { - T instance = Instantiator.of(type).instantiate(); + T instance = Instantiator.of(type, objenesis).instantiate(); traverseFields( values, (f, v) -> new FieldMutator(FieldProbe.of(f)).setNewValue(instance, v) @@ -48,7 +73,7 @@ private T createClassInstance(Map values) { } private void traverseFields(Map values, BiConsumer setValue) { - for (Field f : fields()) { + for (Field f : fields(type)) { Object value = values.get(f); if (value == null) { value = PrimitiveMappers.DEFAULT_VALUE_MAPPER.get(f.getType()); @@ -57,7 +82,7 @@ private void traverseFields(Map values, BiConsumer } } - private FieldIterable fields() { - return FieldIterable.ofIgnoringStatic(type); + private FieldIterable fields(Class typeWithFields) { + return FieldIterable.ofIgnoringStatic(typeWithFields); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java index c239077b2..f77ca14a0 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreator.java @@ -8,6 +8,7 @@ import nl.jqno.equalsverifier.internal.reflection.*; import nl.jqno.equalsverifier.internal.util.Configuration; import nl.jqno.equalsverifier.internal.util.Rethrow; +import org.objenesis.Objenesis; /** * Creates a subject, i.e. an instance of the class that is currently being tested by @@ -21,6 +22,7 @@ public class SubjectCreator { private final ValueProvider valueProvider; private final ClassProbe classProbe; private final FieldCache fieldCache; + private final Objenesis objenesis; /** * Constructor. @@ -28,12 +30,14 @@ public class SubjectCreator { * @param config A configuration object. * @param valueProvider To provide values for the fields of the subject. * @param fieldCache Prepared values for the fields of the subject. + * @param objenesis Needed by InstanceCreator to instantiate non-record classes. */ @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "A cache is inherently mutable") public SubjectCreator( Configuration config, ValueProvider valueProvider, - FieldCache fieldCache + FieldCache fieldCache, + Objenesis objenesis ) { this.typeTag = config.getTypeTag(); this.type = typeTag.getType(); @@ -41,6 +45,7 @@ public SubjectCreator( this.valueProvider = valueProvider; this.classProbe = new ClassProbe<>(type); this.fieldCache = fieldCache; + this.objenesis = objenesis; } /** @@ -160,12 +165,8 @@ public T withAllFieldsShallowlyChanged() { * @return A copy of the given original. */ public T copy(T original) { - Map values = empty(); - for (Field f : fields()) { - Object value = FieldProbe.of(f).getValue(original); - values.put(f, value); - } - return createInstance(values); + InstanceCreator instanceCreator = new InstanceCreator<>(classProbe, objenesis); + return Rethrow.rethrow(() -> instanceCreator.copy(original)); } /** @@ -176,16 +177,11 @@ public T copy(T original) { * @return An instance of the givenoriginal's superclass, but otherwise a copy of the original. */ public Object copyIntoSuperclass(T original) { - Map values = empty(); - for (Field f : superFields()) { - Object value = FieldProbe.of(f).getValue(original); - values.put(f, value); - } - InstanceCreator superCreator = new InstanceCreator<>( - new ClassProbe<>(type.getSuperclass()) + new ClassProbe<>(type.getSuperclass()), + objenesis ); - return superCreator.instantiate(values); + return superCreator.copy(original); } /** @@ -200,19 +196,13 @@ public Object copyIntoSuperclass(T original) { * @return An instance of the given subType, but otherwise a copy of the given original. */ public S copyIntoSubclass(T original, Class subType) { - Map values = empty(); - for (Field f : fields()) { - Object value = FieldProbe.of(f).getValue(original); - values.put(f, value); - } - - InstanceCreator subCreator = new InstanceCreator<>(new ClassProbe<>(subType)); - return subCreator.instantiate(values); + InstanceCreator subCreator = new InstanceCreator<>(new ClassProbe<>(subType), objenesis); + return subCreator.copy(original); } private T createInstance(Map givens) { Map values = determineValues(givens); - InstanceCreator instanceCreator = new InstanceCreator<>(classProbe); + InstanceCreator instanceCreator = new InstanceCreator<>(classProbe, objenesis); return Rethrow.rethrow(() -> instanceCreator.instantiate(values)); } @@ -244,10 +234,6 @@ private FieldIterable fields() { return FieldIterable.ofIgnoringStatic(type); } - private FieldIterable superFields() { - return FieldIterable.ofIgnoringStatic(type.getSuperclass()); - } - private FieldIterable nonSuperFields() { return FieldIterable.ofIgnoringSuperAndStatic(type); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java index c1dea1ac9..4af2fbd1b 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProvider.java @@ -11,6 +11,7 @@ import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; import nl.jqno.equalsverifier.internal.util.PrimitiveMappers; import nl.jqno.equalsverifier.internal.util.Rethrow; +import org.objenesis.Objenesis; /** * Creator of prefabricated instances of classes, using a "vintage" strategy for doing so. @@ -25,16 +26,18 @@ public class VintageValueProvider implements ValueProvider { private final Map> valueCache = new HashMap<>(); private final FactoryCache factoryCache; - private final PrefabValueFactory fallbackFactory = new FallbackFactory<>(); + private final PrefabValueFactory fallbackFactory; /** * Constructor. * * @param factoryCache The factories that can be used to create values. + * @param objenesis To instantiate non-record classes. */ @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "A cache is inherently mutable.") - public VintageValueProvider(FactoryCache factoryCache) { + public VintageValueProvider(FactoryCache factoryCache, Objenesis objenesis) { this.factoryCache = factoryCache; + this.fallbackFactory = new FallbackFactory<>(objenesis); } /** {@inheritDoc} */ diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java index 387f8fe7c..e19fde95d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessor.java @@ -4,6 +4,7 @@ import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; +import org.objenesis.Objenesis; /** * Instantiates and populates objects of a given class. {@link ClassAccessor} can create two @@ -16,11 +17,13 @@ public class ClassAccessor { private final Class type; private final VintageValueProvider valueProvider; + private final Objenesis objenesis; /** Private constructor. Call {@link #of(Class, PrefabValues)} instead. */ - ClassAccessor(Class type, VintageValueProvider valueProvider) { + ClassAccessor(Class type, VintageValueProvider valueProvider, Objenesis objenesis) { this.type = type; this.valueProvider = valueProvider; + this.objenesis = objenesis; } /** @@ -29,10 +32,15 @@ public class ClassAccessor { * @param The class on which {@link ClassAccessor} operates. * @param type The class on which {@link ClassAccessor} operates. Should be the same as T. * @param valueProvider Prefabricated values with which to fill instantiated objects. + * @param objenesis To instantiate non-record classes. * @return A {@link ClassAccessor} for T. */ - public static ClassAccessor of(Class type, VintageValueProvider valueProvider) { - return new ClassAccessor<>(type, valueProvider); + public static ClassAccessor of( + Class type, + VintageValueProvider valueProvider, + Objenesis objenesis + ) { + return new ClassAccessor<>(type, valueProvider, objenesis); } /** @@ -94,7 +102,7 @@ public ObjectAccessor getBlueAccessor( } private ObjectAccessor buildObjectAccessor() { - T object = Instantiator.of(type).instantiate(); + T object = Instantiator.of(type, objenesis).instantiate(); return ObjectAccessor.of(object); } } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java index b991efc3f..c9cf1c573 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessor.java @@ -6,6 +6,7 @@ import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; +import org.objenesis.Objenesis; /** * Implementation of ObjectAccessor that modifies its wrapped object in-place through reflection. @@ -21,8 +22,8 @@ final class InPlaceObjectAccessor extends ObjectAccessor { /** {@inheritDoc} */ @Override - public T copy() { - T copy = Instantiator.of(type()).instantiate(); + public T copy(Objenesis objenesis) { + T copy = Instantiator.of(type(), objenesis).instantiate(); for (Field field : FieldIterable.of(type())) { fieldModifierFor(field).copyTo(copy); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java index 72b031683..480e30224 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/ObjectAccessor.java @@ -4,6 +4,7 @@ import nl.jqno.equalsverifier.internal.reflection.RecordsHelper; import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; +import org.objenesis.Objenesis; /** * Wraps an object to provide access to it. ObjectAccessor can copy and scramble the wrapped object. @@ -73,9 +74,10 @@ public Class type() { * *

Note: it does a "shallow" copy. Reference fields are not copied recursively. * + * @param objenesis Needed to instantiate the copy. * @return A shallow copy. */ - public abstract T copy(); + public abstract T copy(Objenesis objenesis); /** * Modifies all fields of the wrapped object that are declared in T and in its superclasses. It diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java index 459f50b66..c1f63ea44 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/RecordObjectAccessor.java @@ -9,6 +9,7 @@ import nl.jqno.equalsverifier.internal.reflection.RecordProbe; import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; +import org.objenesis.Objenesis; /** * Implementation of ObjectAccessor that returns modified copies of its wrapped object, through @@ -29,7 +30,7 @@ final class RecordObjectAccessor extends ObjectAccessor { /** {@inheritDoc} */ @Override - public T copy() { + public T copy(Objenesis objenesis) { List params = probe.fields().map(this::getField).collect(Collectors.toList()); return callRecordConstructor(params); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java index 3c673dc91..eb69ea6b3 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactory.java @@ -9,6 +9,7 @@ import nl.jqno.equalsverifier.internal.reflection.TypeTag; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.ClassAccessor; +import org.objenesis.Objenesis; /** * Implementation of {@link PrefabValueFactory} that instantiates types "by force". @@ -18,6 +19,12 @@ */ public class FallbackFactory implements PrefabValueFactory { + private final Objenesis objenesis; + + public FallbackFactory(Objenesis objenesis) { + this.objenesis = objenesis; + } + @Override public Tuple createValues( TypeTag tag, @@ -95,7 +102,7 @@ private Tuple giveInstances( VintageValueProvider valueProvider, LinkedHashSet typeStack ) { - ClassAccessor accessor = ClassAccessor.of(tag.getType(), valueProvider); + ClassAccessor accessor = ClassAccessor.of(tag.getType(), valueProvider, objenesis); T red = accessor.getRedObject(tag, typeStack); T blue = accessor.getBlueObject(tag, typeStack); T redCopy = accessor.getRedObject(tag, typeStack); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java index 456b45704..e70f1620d 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/Context.java @@ -5,6 +5,7 @@ import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; +import org.objenesis.Objenesis; public final class Context { @@ -23,7 +24,8 @@ public final class Context { public Context( Configuration configuration, FactoryCache factoryCache, - FieldCache fieldCache + FieldCache fieldCache, + Objenesis objenesis ) { this.type = configuration.getType(); this.configuration = configuration; @@ -31,8 +33,9 @@ public Context( this.fieldCache = fieldCache; FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); - this.valueProvider = new VintageValueProvider(cache); - this.subjectCreator = new SubjectCreator<>(configuration, valueProvider, fieldCache); + this.valueProvider = new VintageValueProvider(cache, objenesis); + this.subjectCreator = + new SubjectCreator<>(configuration, valueProvider, fieldCache, objenesis); } public Class getType() { diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/ObjenesisWrapper.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/ObjenesisWrapper.java deleted file mode 100644 index 9b4e55942..000000000 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/ObjenesisWrapper.java +++ /dev/null @@ -1,29 +0,0 @@ -package nl.jqno.equalsverifier.internal.util; - -import org.objenesis.Objenesis; -import org.objenesis.ObjenesisStd; - -/** - * A wrapper around Objenesis. Objenesis keeps caches of objects it has instantiated, so we want a - * way to easily re-use the same instance of `Objenesis`. This class reflects the usage in - * {@link org.objenesis.ObjenesisHelper}, but with the added benefit that now we can reset the - * caches if needed (for instance if the test framework used does some "clever" tricks with - * ClassLoaders) by re-initializing the Objenesis instance. - * - * Note: I realise that a wrapper around a static reference is not very architecturally sound; - * however, doing it properly would require major re-writes. Maybe some other time. - */ -public final class ObjenesisWrapper { - - private static Objenesis objenesis = new ObjenesisStd(); - - private ObjenesisWrapper() {} - - public static Objenesis getObjenesis() { - return objenesis; - } - - public static void reset() { - objenesis = new ObjenesisStd(); - } -} diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java index 8493682e6..8bc5c9c0c 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/PrefabValuesApi.java @@ -10,6 +10,7 @@ import nl.jqno.equalsverifier.internal.reflection.Tuple; import nl.jqno.equalsverifier.internal.reflection.vintage.ObjectAccessor; import nl.jqno.equalsverifier.internal.reflection.vintage.prefabvalues.factories.PrefabValueFactory; +import org.objenesis.Objenesis; public final class PrefabValuesApi { @@ -17,6 +18,7 @@ private PrefabValuesApi() {} public static void addPrefabValues( FactoryCache factoryCache, + Objenesis objenesis, Class otherType, T red, T blue @@ -27,7 +29,7 @@ public static void addPrefabValues( factoryCache.put(otherType, values(red, blue, red)); } else { try { - T redCopy = ObjectAccessor.of(red).copy(); + T redCopy = ObjectAccessor.of(red).copy(objenesis); factoryCache.put(otherType, values(red, blue, redCopy)); } catch (RuntimeException ignored) { /* specifically, on Java 9+: InacessibleObjectException */ @@ -39,6 +41,7 @@ public static void addPrefabValues( @SuppressWarnings("unchecked") public static void addPrefabValuesForField( FieldCache fieldCache, + Objenesis objenesis, Class type, String fieldName, T red, @@ -51,7 +54,7 @@ public static void addPrefabValuesForField( fieldCache.put(fieldName, new Tuple<>(red, blue, red)); } else { try { - T redCopy = ObjectAccessor.of(red).copy(); + T redCopy = ObjectAccessor.of(red).copy(objenesis); fieldCache.put(fieldName, new Tuple<>(red, blue, redCopy)); } catch (RuntimeException ignored) { /* specifically, on Java 9+: InacessibleObjectException */ diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithResetCachesTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithResetCachesTest.java deleted file mode 100644 index 8803c0a40..000000000 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithResetCachesTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package nl.jqno.equalsverifier.integration.operational; - -import static org.junit.jupiter.api.Assertions.assertNotEquals; - -import nl.jqno.equalsverifier.EqualsVerifier; -import nl.jqno.equalsverifier.internal.util.ObjenesisWrapper; -import nl.jqno.equalsverifier.testhelpers.packages.correct.A; -import org.junit.jupiter.api.Test; -import org.objenesis.Objenesis; - -public class WithResetCachesTest { - - @Test - public void resetObjenesisCacheOnEachRun() { - Objenesis original = ObjenesisWrapper.getObjenesis(); - EqualsVerifier.forClass(A.class).verify(); - Objenesis reset = ObjenesisWrapper.getObjenesis(); - assertNotEquals(original, reset); - } -} diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InstantiatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InstantiatorTest.java index 95c1f5376..be7a5357a 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InstantiatorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/InstantiatorTest.java @@ -17,51 +17,57 @@ import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.ArrayContainer; import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.Interface; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; import org.w3c.dom.Element; public class InstantiatorTest { + private Objenesis objenesis = new ObjenesisStd(); + @Test public void instantiateClass() { - Instantiator instantiator = Instantiator.of(Point.class); + Instantiator instantiator = Instantiator.of(Point.class, objenesis); Point p = instantiator.instantiate(); assertEquals(Point.class, p.getClass()); } @Test public void fieldsOfInstantiatedObjectHaveDefaultValues() { - ColorBlindColorPoint p = Instantiator.of(ColorBlindColorPoint.class).instantiate(); + ColorBlindColorPoint p = Instantiator + .of(ColorBlindColorPoint.class, objenesis) + .instantiate(); assertEquals(0, p.x); assertEquals(null, p.color); } @Test public void instantiateInterface() { - Instantiator instantiator = Instantiator.of(Interface.class); + Instantiator instantiator = Instantiator.of(Interface.class, objenesis); Interface i = instantiator.instantiate(); assertTrue(Interface.class.isAssignableFrom(i.getClass())); } @Test public void instantiateFinalClass() { - Instantiator.of(FinalPoint.class); + Instantiator.of(FinalPoint.class, objenesis); } @Test public void instantiateArrayContainer() { - Instantiator.of(ArrayContainer.class); + Instantiator.of(ArrayContainer.class, objenesis); } @Test public void instantiateAbstractClass() { - Instantiator instantiator = Instantiator.of(AbstractClass.class); + Instantiator instantiator = Instantiator.of(AbstractClass.class, objenesis); AbstractClass ac = instantiator.instantiate(); assertTrue(AbstractClass.class.isAssignableFrom(ac.getClass())); } @Test public void instantiateSubclass() { - Instantiator instantiator = Instantiator.of(Point.class); + Instantiator instantiator = Instantiator.of(Point.class, objenesis); Point p = instantiator.instantiateAnonymousSubclass(); assertFalse(p.getClass() == Point.class); assertTrue(Point.class.isAssignableFrom(p.getClass())); @@ -70,26 +76,26 @@ public void instantiateSubclass() { @Test public void instantiateAnNonToplevelClass() { class Something {} - Instantiator instantiator = Instantiator.of(Something.class); + Instantiator instantiator = Instantiator.of(Something.class, objenesis); instantiator.instantiateAnonymousSubclass(); } @Test @SuppressWarnings("rawtypes") public void instantiateJavaApiClassWhichHasBootstrapClassLoader() { - Instantiator instantiator = Instantiator.of(List.class); + Instantiator instantiator = Instantiator.of(List.class, objenesis); instantiator.instantiateAnonymousSubclass(); } @Test public void instantiateOrgW3cDomClassWhichHasBootstrapClassLoader() { - Instantiator instantiator = Instantiator.of(Element.class); + Instantiator instantiator = Instantiator.of(Element.class, objenesis); instantiator.instantiateAnonymousSubclass(); } @Test public void instantiateTheSameSubclass() { - Instantiator instantiator = Instantiator.of(Point.class); + Instantiator instantiator = Instantiator.of(Point.class, objenesis); Class expected = instantiator.instantiateAnonymousSubclass().getClass(); Class actual = instantiator.instantiateAnonymousSubclass().getClass(); assertEquals(expected, actual); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/annotations/AnnotationCacheBuilderTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/annotations/AnnotationCacheBuilderTest.java index 20d227c10..6eb8fcce7 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/annotations/AnnotationCacheBuilderTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/annotations/AnnotationCacheBuilderTest.java @@ -20,6 +20,7 @@ import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.ObjenesisStd; public class AnnotationCacheBuilderTest { @@ -407,7 +408,7 @@ public void loadedBySystemClassLoaderDoesNotThrowNullPointerException() { @Test public void dynamicClassDoesntGetProcessed_butDoesntThrowEither() { Class type = Instantiator - .of(AnnotatedWithRuntime.class) + .of(AnnotatedWithRuntime.class, new ObjenesisStd()) .instantiateAnonymousSubclass() .getClass(); build(type); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreatorTest.java index ba7144957..4cd563b6f 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreatorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/InstanceCreatorTest.java @@ -7,13 +7,16 @@ import java.util.Map; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class InstanceCreatorTest { @Test - public void instanceCreator() throws NoSuchFieldException { + public void instantiate() throws NoSuchFieldException { ClassProbe probe = new ClassProbe<>(SomeClass.class); - InstanceCreator sut = new InstanceCreator<>(probe); + Objenesis objenesis = new ObjenesisStd(); + InstanceCreator sut = new InstanceCreator<>(probe, objenesis); Field x = SomeClass.class.getDeclaredField("x"); Field z = SomeClass.class.getDeclaredField("z"); @@ -28,11 +31,26 @@ public void instanceCreator() throws NoSuchFieldException { assertEquals("42", actual.z); } + @Test + public void copy() throws NoSuchFieldException { + ClassProbe probe = new ClassProbe<>(SomeSubClass.class); + Objenesis objenesis = new ObjenesisStd(); + InstanceCreator sut = new InstanceCreator<>(probe, objenesis); + + SomeClass original = new SomeClass(42, 1337, "yeah"); + SomeSubClass copy = sut.copy(original); + + assertEquals(original.x, copy.x); + assertEquals(original.y, copy.y); + assertEquals(original.z, copy.z); + assertEquals(0, copy.a); + } + static class SomeClass { - private final int x; - private final int y; - private final String z; + final int x; + final int y; + final String z; public SomeClass(int x, int y, String z) { this.x = x; @@ -40,4 +58,14 @@ public SomeClass(int x, int y, String z) { this.z = z; } } + + static class SomeSubClass extends SomeClass { + + final int a; + + public SomeSubClass(int x, int y, String z, int a) { + super(x, y, z); + this.a = a; + } + } } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreatorTest.java index d98d287e7..d9e9ba8cd 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreatorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/SubjectCreatorTest.java @@ -12,6 +12,8 @@ import nl.jqno.equalsverifier.internal.util.ConfigurationHelper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class SubjectCreatorTest { @@ -25,7 +27,13 @@ public class SubjectCreatorTest { ); private ValueProvider valueProvider = new SubjectCreatorTestValueProvider(); private FieldCache fieldCache = new FieldCache(); - private SubjectCreator sut = new SubjectCreator<>(config, valueProvider, fieldCache); + private Objenesis objenesis = new ObjenesisStd(); + private SubjectCreator sut = new SubjectCreator<>( + config, + valueProvider, + fieldCache, + objenesis + ); private Field fieldX; private Field fieldI; diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderCreatorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderCreatorTest.java index d95680d10..45bba76bc 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderCreatorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderCreatorTest.java @@ -15,6 +15,8 @@ import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.OneElementEnum; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class VintageValueProviderCreatorTest { @@ -27,13 +29,15 @@ public class VintageValueProviderCreatorTest { private static final TypeTag TWOSTEP_NODE_A_TAG = new TypeTag(TwoStepNodeA.class); private static final TypeTag TWOSTEP_NODE_ARRAY_A_TAG = new TypeTag(TwoStepNodeArrayA.class); + private Objenesis objenesis; private FactoryCache factoryCache; private VintageValueProvider valueProvider; @BeforeEach public void setup() { + objenesis = new ObjenesisStd(); factoryCache = FactoryCacheFactory.withPrimitiveFactories(); - valueProvider = new VintageValueProvider(factoryCache); + valueProvider = new VintageValueProvider(factoryCache, objenesis); } @Test @@ -73,7 +77,7 @@ public void createEmptyEnum() { @Test public void oneStepRecursiveType() { factoryCache.put(Node.class, values(new Node(), new Node(), new Node())); - valueProvider = new VintageValueProvider(factoryCache); + valueProvider = new VintageValueProvider(factoryCache, objenesis); valueProvider.giveRed(NODE_TAG); } @@ -90,7 +94,7 @@ public void oneStepRecursiveArrayType() { NodeArray.class, values(new NodeArray(), new NodeArray(), new NodeArray()) ); - valueProvider = new VintageValueProvider(factoryCache); + valueProvider = new VintageValueProvider(factoryCache, objenesis); valueProvider.giveRed(NODE_ARRAY_TAG); } @@ -107,7 +111,7 @@ public void addTwoStepRecursiveType() { TwoStepNodeB.class, values(new TwoStepNodeB(), new TwoStepNodeB(), new TwoStepNodeB()) ); - valueProvider = new VintageValueProvider(factoryCache); + valueProvider = new VintageValueProvider(factoryCache, objenesis); valueProvider.giveRed(TWOSTEP_NODE_A_TAG); } @@ -124,7 +128,7 @@ public void twoStepRecursiveArrayType() { TwoStepNodeArrayB.class, values(new TwoStepNodeArrayB(), new TwoStepNodeArrayB(), new TwoStepNodeArrayB()) ); - valueProvider = new VintageValueProvider(factoryCache); + valueProvider = new VintageValueProvider(factoryCache, objenesis); valueProvider.giveRed(TWOSTEP_NODE_ARRAY_A_TAG); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java index 0fb687430..2fa15353e 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/VintageValueProviderTest.java @@ -18,6 +18,8 @@ import nl.jqno.equalsverifier.testhelpers.types.ThrowingInitializer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class VintageValueProviderTest { @@ -25,6 +27,7 @@ public class VintageValueProviderTest { private static final TypeTag POINT_TAG = new TypeTag(Point.class); private static final TypeTag INT_TAG = new TypeTag(int.class); + private Objenesis objenesis = new ObjenesisStd(); private FactoryCache factoryCache = new FactoryCache(); private VintageValueProvider vp; @@ -32,7 +35,7 @@ public class VintageValueProviderTest { public void setUp() { factoryCache.put(String.class, new AppendingStringTestFactory()); factoryCache.put(int.class, values(42, 1337, 42)); - vp = new VintageValueProvider(factoryCache); + vp = new VintageValueProvider(factoryCache, objenesis); } @Test @@ -113,7 +116,7 @@ public void fallbackDoesNotAffectStaticFields() { @Test public void stringListIsSeparateFromIntegerList() { factoryCache.put(List.class, new ListTestFactory()); - vp = new VintageValueProvider(factoryCache); + vp = new VintageValueProvider(factoryCache, objenesis); List strings = vp.giveRed(new TypeTag(List.class, STRING_TAG)); List ints = vp.giveRed(new TypeTag(List.class, INT_TAG)); @@ -130,7 +133,7 @@ public void addingNullDoesntBreakAnything() { @Test public void addingATypeTwiceOverrulesTheExistingOne() { factoryCache.put(int.class, values(-1, -2, -1)); - vp = new VintageValueProvider(factoryCache); + vp = new VintageValueProvider(factoryCache, objenesis); assertEquals(-1, (int) vp.giveRed(INT_TAG)); assertEquals(-2, (int) vp.giveBlue(INT_TAG)); } @@ -139,7 +142,7 @@ public void addingATypeTwiceOverrulesTheExistingOne() { public void addLazyFactoryWorks() { TypeTag lazyTag = new TypeTag(Lazy.class); factoryCache.put(Lazy.class.getName(), values(Lazy.X, Lazy.Y, Lazy.X)); - vp = new VintageValueProvider(factoryCache); + vp = new VintageValueProvider(factoryCache, objenesis); assertEquals(Lazy.X, vp.giveRed(lazyTag)); assertEquals(Lazy.Y, vp.giveBlue(lazyTag)); assertEquals(Lazy.X, vp.giveRedCopy(lazyTag)); @@ -155,7 +158,7 @@ public void addLazyFactoryIsLazy() { (t, p, ts) -> Tuple.of(ThrowingInitializer.X, ThrowingInitializer.Y, ThrowingInitializer.X) ); - vp = new VintageValueProvider(factoryCache); + vp = new VintageValueProvider(factoryCache, objenesis); // Should throw, because `giveRed` does instantiate objects: try { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java index 5c588b924..3fbfcb6cb 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/ClassAccessorTest.java @@ -16,10 +16,13 @@ import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class ClassAccessorTest { private LinkedHashSet empty; + private Objenesis objenesis; private FactoryCache factoryCache; private VintageValueProvider valueProvider; private ClassAccessor pointContainerAccessor; @@ -27,9 +30,10 @@ public class ClassAccessorTest { @BeforeEach public void setup() { empty = new LinkedHashSet<>(); + objenesis = new ObjenesisStd(); factoryCache = JavaApiPrefabValues.build(); - valueProvider = new VintageValueProvider(factoryCache); - pointContainerAccessor = ClassAccessor.of(PointContainer.class, valueProvider); + valueProvider = new VintageValueProvider(factoryCache, objenesis); + pointContainerAccessor = ClassAccessor.of(PointContainer.class, valueProvider, objenesis); } @Test @@ -42,7 +46,8 @@ public void getRedObject() { public void getRedObjectGeneric() { ClassAccessor accessor = ClassAccessor.of( GenericTypeVariableListContainer.class, - valueProvider + valueProvider, + objenesis ); GenericTypeVariableListContainer foo = accessor.getRedObject( new TypeTag(GenericTypeVariableListContainer.class, new TypeTag(String.class)), @@ -71,7 +76,8 @@ public void getBlueObject() { public void getBlueObjectGeneric() { ClassAccessor accessor = ClassAccessor.of( GenericTypeVariableListContainer.class, - valueProvider + valueProvider, + objenesis ); GenericTypeVariableListContainer foo = accessor.getBlueObject( new TypeTag(GenericTypeVariableListContainer.class, new TypeTag(String.class)), @@ -99,13 +105,15 @@ public void redAndBlueNotEqual() { @Test public void instantiateAllTypes() { - ClassAccessor.of(AllTypesContainer.class, valueProvider).getRedObject(TypeTag.NULL, empty); + ClassAccessor + .of(AllTypesContainer.class, valueProvider, objenesis) + .getRedObject(TypeTag.NULL, empty); } @Test public void instantiateArrayTypes() { ClassAccessor - .of(AllArrayTypesContainer.class, valueProvider) + .of(AllArrayTypesContainer.class, valueProvider, objenesis) .getRedObject(TypeTag.NULL, empty); } @@ -115,25 +123,29 @@ public void instantiateRecursiveTypeUsingPrefabValue() { TwoStepNodeB.class, values(new TwoStepNodeB(), new TwoStepNodeB(), new TwoStepNodeB()) ); - valueProvider = new VintageValueProvider(factoryCache); - ClassAccessor.of(TwoStepNodeA.class, valueProvider).getRedObject(TypeTag.NULL, empty); + valueProvider = new VintageValueProvider(factoryCache, objenesis); + ClassAccessor + .of(TwoStepNodeA.class, valueProvider, objenesis) + .getRedObject(TypeTag.NULL, empty); } @Test public void instantiateInterfaceField() { - ClassAccessor.of(InterfaceContainer.class, valueProvider).getRedObject(TypeTag.NULL, empty); + ClassAccessor + .of(InterfaceContainer.class, valueProvider, objenesis) + .getRedObject(TypeTag.NULL, empty); } @Test public void instantiateAbstractClassField() { ClassAccessor - .of(AbstractClassContainer.class, valueProvider) + .of(AbstractClassContainer.class, valueProvider, objenesis) .getRedObject(TypeTag.NULL, empty); } @Test public void anInvalidTypeShouldNotThrowAnExceptionUponCreation() { - ClassAccessor.of(null, valueProvider); + ClassAccessor.of(null, valueProvider, objenesis); } private void assertObjectHasNoNullFields(PointContainer foo) { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java index 60b6c7b1f..a224280df 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorCopyingTest.java @@ -11,9 +11,13 @@ import nl.jqno.equalsverifier.testhelpers.types.PointContainer; import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.StaticFinalContainer; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class InPlaceObjectAccessorCopyingTest { + private Objenesis objenesis = new ObjenesisStd(); + @Test public void copyHappyPath() { Point original = new Point(2, 3); @@ -61,11 +65,11 @@ private InPlaceObjectAccessor create(T object) { } private T copyOf(T from) { - return create(from).copy(); + return create(from).copy(objenesis); } private T copyOf(T from, Class type) { - return new InPlaceObjectAccessor(from, type).copy(); + return new InPlaceObjectAccessor(from, type).copy(objenesis); } private static void assertAllFieldsEqual(T original, T copy, Class type) { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java index 04e7668a0..a6775ab59 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/InPlaceObjectAccessorScramblingTest.java @@ -20,17 +20,21 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledForJreRange; import org.junit.jupiter.api.condition.JRE; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class InPlaceObjectAccessorScramblingTest { private static final LinkedHashSet EMPTY_TYPE_STACK = new LinkedHashSet<>(); + private Objenesis objenesis; private VintageValueProvider valueProviderTest; @BeforeEach public void setup() { FactoryCache factoryCache = JavaApiPrefabValues.build(); factoryCache.put(Point.class, values(new Point(1, 2), new Point(2, 3), new Point(1, 2))); - valueProviderTest = new VintageValueProvider(factoryCache); + objenesis = new ObjenesisStd(); + valueProviderTest = new VintageValueProvider(factoryCache, objenesis); } @Test @@ -146,7 +150,7 @@ private InPlaceObjectAccessor create(T object) { } private T copy(T object) { - return create(object).copy(); + return create(object).copy(objenesis); } private ObjectAccessor doScramble(Object object) { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java index 2af38cf09..ff91709c4 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/FallbackFactoryTest.java @@ -21,6 +21,8 @@ import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.TwoElementEnum; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class FallbackFactoryTest { @@ -30,10 +32,11 @@ public class FallbackFactoryTest { @BeforeEach public void setUp() { - factory = new FallbackFactory<>(); + Objenesis objenesis = new ObjenesisStd(); + factory = new FallbackFactory<>(objenesis); FactoryCache factoryCache = new FactoryCache(); factoryCache.put(int.class, values(42, 1337, 42)); - valueProvider = new VintageValueProvider(factoryCache); + valueProvider = new VintageValueProvider(factoryCache, objenesis); typeStack = new LinkedHashSet<>(); } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java index 5b67f1674..afd23e9d7 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/MapFactoryTest.java @@ -12,6 +12,7 @@ import nl.jqno.equalsverifier.testhelpers.types.TypeHelper.OneElementEnum; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.ObjenesisStd; @SuppressWarnings("rawtypes") public class MapFactoryTest { @@ -48,7 +49,7 @@ public class MapFactoryTest { @BeforeEach public void setUp() { - valueProvider = new VintageValueProvider(JavaApiPrefabValues.build()); + valueProvider = new VintageValueProvider(JavaApiPrefabValues.build(), new ObjenesisStd()); red = valueProvider.giveRed(STRING_TYPETAG); blue = valueProvider.giveBlue(STRING_TYPETAG); redObject = valueProvider.giveRed(OBJECT_TYPETAG); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java index e7d69dc49..ff5f32d6e 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factories/SimpleGenericFactoryTest.java @@ -11,6 +11,7 @@ import nl.jqno.equalsverifier.testhelpers.types.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.ObjenesisStd; @SuppressWarnings("rawtypes") public class SimpleGenericFactoryTest { @@ -50,7 +51,7 @@ public class SimpleGenericFactoryTest { @BeforeEach public void setUp() { - valueProvider = new VintageValueProvider(JavaApiPrefabValues.build()); + valueProvider = new VintageValueProvider(JavaApiPrefabValues.build(), new ObjenesisStd()); redString = valueProvider.giveRed(STRING_TYPETAG); blueString = valueProvider.giveBlue(STRING_TYPETAG); redInt = valueProvider.giveRed(INTEGER_TYPETAG); diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java index f3612ccf7..06681caeb 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/vintage/prefabvalues/factoryproviders/JavaFxFactoryProviderTest.java @@ -14,6 +14,7 @@ import nl.jqno.equalsverifier.testhelpers.types.Point; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.objenesis.ObjenesisStd; @SuppressWarnings("rawtypes") public class JavaFxFactoryProviderTest { @@ -22,7 +23,7 @@ public class JavaFxFactoryProviderTest { @BeforeEach public void setUp() { - valueProvider = new VintageValueProvider(JavaApiPrefabValues.build()); + valueProvider = new VintageValueProvider(JavaApiPrefabValues.build(), new ObjenesisStd()); } @Test diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/FormatterTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/FormatterTest.java index 8570afd0b..ac26e1721 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/FormatterTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/util/FormatterTest.java @@ -8,9 +8,13 @@ import nl.jqno.equalsverifier.internal.reflection.Instantiator; import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException; import org.junit.jupiter.api.Test; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; public class FormatterTest { + private final Objenesis objenesis = new ObjenesisStd(); + @Test public void noParameters() { Formatter f = Formatter.of("No parameters"); @@ -69,35 +73,38 @@ public void oneParameterWithNoFieldsAndThrowsWithNullMessage() { @Test public void oneAbstractParameter() { - Instantiator i = Instantiator.of(Abstract.class); + Instantiator i = Instantiator.of(Abstract.class, objenesis); Formatter f = Formatter.of("Abstract: %%", i.instantiate()); assertThat(f.format(), containsString("Abstract: [Abstract x=0]")); } @Test public void oneConcreteSubclassParameter() { - Instantiator i = Instantiator.of(AbstractImpl.class); + Instantiator i = Instantiator.of(AbstractImpl.class, objenesis); Formatter f = Formatter.of("Concrete: %%", i.instantiate()); assertThat(f.format(), containsString("Concrete: something concrete")); } @Test public void oneDelegatedAbstractParameter() { - Instantiator i = Instantiator.of(AbstractDelegation.class); + Instantiator i = Instantiator.of(AbstractDelegation.class, objenesis); Formatter f = Formatter.of("Abstract: %%", i.instantiate()); assertThat(f.format(), containsString("Abstract: [AbstractDelegation y=0]")); } @Test public void oneDelegatedConcreteSubclassParameter() { - Instantiator i = Instantiator.of(AbstractDelegationImpl.class); + Instantiator i = Instantiator.of( + AbstractDelegationImpl.class, + objenesis + ); Formatter f = Formatter.of("Concrete: %%", i.instantiate()); assertThat(f.format(), containsString("Concrete: something concrete")); } @Test public void oneThrowingContainerParameter() { - Instantiator i = Instantiator.of(Throwing.class); + Instantiator i = Instantiator.of(Throwing.class, objenesis); ThrowingContainer tc = new ThrowingContainer(i.instantiate()); Formatter f = Formatter.of("TC: %%", tc); String expected = @@ -107,7 +114,7 @@ public void oneThrowingContainerParameter() { @Test public void oneAbstractContainerParameter() { - Instantiator i = Instantiator.of(AbstractDelegation.class); + Instantiator i = Instantiator.of(AbstractDelegation.class, objenesis); AbstractContainer ac = new AbstractContainer(i.instantiate()); Formatter f = Formatter.of("AC: %%", ac); From 2efc52ab5e506d8020454bfc551bb0f0430bb86d Mon Sep 17 00:00:00 2001 From: Jan Ouwens Date: Tue, 24 Sep 2024 13:28:00 +0200 Subject: [PATCH 74/74] Makes more improvements suggested by PITest --- .../fieldchecks/JpaLazyGetterFieldCheck.java | 10 +++++++- .../fieldchecks/SymmetryFieldCheck.java | 2 -- .../extra_features/JpaLazyEntityTest.java | 3 ++- .../WithPrefabValuesForFieldTest.java | 25 +++++++++++++++---- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java index 96e0110bc..9727744bf 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/JpaLazyGetterFieldCheck.java @@ -57,7 +57,15 @@ public void execute(FieldProbe fieldProbe) { return; } - assertEntity(fieldName, "equals", getterName, classProbe.hasMethod(getterName)); + assertTrue( + Formatter.of( + "Class %% doesn't contain getter %%() for field %%.", + classProbe.getType().getSimpleName(), + getterName, + fieldName + ), + classProbe.hasMethod(getterName) + ); Class sub = throwingGetterCreator(getterName); Tuple tuple = valueProvider.provide(new TypeTag(sub)); diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java index 5e15749b9..c3611eebc 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/checkers/fieldchecks/SymmetryFieldCheck.java @@ -23,12 +23,10 @@ public SymmetryFieldCheck(SubjectCreator subjectCreator) { public void execute(FieldProbe fieldProbe) { T left = subjectCreator.plain(); T right = subjectCreator.plain(); - T changedLeft = subjectCreator.withFieldChanged(fieldProbe.getField()); T changedRight = subjectCreator.withFieldChanged(fieldProbe.getField()); checkSymmetry(left, right); checkSymmetry(left, changedRight); - checkSymmetry(changedLeft, changedRight); } private void checkSymmetry(T left, T right) { diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java index e1a98e78a..e55f2c3eb 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/extra_features/JpaLazyEntityTest.java @@ -21,7 +21,8 @@ public void gettersAreUsed() { public void basicGetterAbsent() { ExpectedException .when(() -> EqualsVerifier.forClass(LazyFieldWithoutGetterContainer.class).verify()) - .assertFailure(); + .assertFailure() + .assertMessageContains("doesn't contain getter getBasic() for field basic"); } @Test diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithPrefabValuesForFieldTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithPrefabValuesForFieldTest.java index 2ade8be58..0d39f7c59 100644 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithPrefabValuesForFieldTest.java +++ b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/integration/operational/WithPrefabValuesForFieldTest.java @@ -17,7 +17,7 @@ public class WithPrefabValuesForFieldTest { private final int iBlue = 142; @Test - public void fail_whenRecordHasSinglePrecondition() { + public void fail_whenClassHasSinglePrecondition() { ExpectedException .when(() -> EqualsVerifier @@ -30,7 +30,7 @@ public void fail_whenRecordHasSinglePrecondition() { } @Test - public void succeed_whenRecordHasSinglePrecondition_givenPrefabValuesForField() { + public void succeed_whenClassHasSinglePrecondition_givenPrefabValuesForField() { EqualsVerifier .forClass(SinglePrecondition.class) .withPrefabValuesForField("point", pRed, pBlue) @@ -38,7 +38,7 @@ public void succeed_whenRecordHasSinglePrecondition_givenPrefabValuesForField() } @Test - public void fail_whenRecordHasDualPrecondition() { + public void fail_whenClassHasDualPrecondition() { ExpectedException .when(() -> EqualsVerifier.forClass(DualPrecondition.class).verify()) .assertFailure() @@ -46,7 +46,7 @@ public void fail_whenRecordHasDualPrecondition() { } @Test - public void fail_whenRecordHasDualPrecondition_givenPrefabValuesForOnlyOneField() { + public void fail_whenClassHasDualPrecondition_givenPrefabValuesForOnlyOneField() { ExpectedException .when(() -> EqualsVerifier @@ -59,7 +59,7 @@ public void fail_whenRecordHasDualPrecondition_givenPrefabValuesForOnlyOneField( } @Test - public void succeed_whenRecordHasDualPrecondition_givenPrefabValueForBothFields() { + public void succeed_whenClassHasDualPrecondition_givenPrefabValueForBothFields() { EqualsVerifier .forClass(DualPrecondition.class) .withPrefabValuesForField("x", iRed, iBlue) @@ -134,6 +134,21 @@ public void throw_whenThePrefabValuesAreEqual() { ); } + @Test + public void throw_whenFieldsDontMatch() { + ExpectedException + .when(() -> + EqualsVerifier + .forClass(SinglePrecondition.class) + .withPrefabValuesForField("point", 1, 2) + ) + .assertThrows(IllegalStateException.class) + .assertMessageContains( + "Precondition", + "for field point should be of type FinalPoint but are" + ); + } + @Test public void dontThrow_whenAddingPrefabValuesFromAnotherModuleAndThereforeARedCopyCantBeMade() { EqualsVerifier