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 9b9a03943..9370d2189 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java @@ -10,7 +10,6 @@ import nl.jqno.equalsverifier.api.MultipleTypeEqualsVerifierApi; import nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi; import nl.jqno.equalsverifier.internal.reflection.PackageScanner; -import nl.jqno.equalsverifier.internal.reflection.instantiation.GenericPrefabValueProvider.GenericFactories; import nl.jqno.equalsverifier.internal.reflection.vintage.FactoryCache; import nl.jqno.equalsverifier.internal.util.ListBuilders; import nl.jqno.equalsverifier.internal.util.PrefabValuesApi; @@ -22,33 +21,24 @@ public final class ConfiguredEqualsVerifier implements EqualsVerifierApi { private final EnumSet warningsToSuppress; private final FactoryCache factoryCache; - private final GenericFactories genericFactories; private boolean usingGetClass; private Function fieldnameToGetter; private final Objenesis objenesis = new ObjenesisStd(); /** Constructor. */ public ConfiguredEqualsVerifier() { - this( - EnumSet.noneOf(Warning.class), - new FactoryCache(), - new GenericFactories(), - false, - null - ); + this(EnumSet.noneOf(Warning.class), new FactoryCache(), false, null); } /** Private constructor. For internal use only. */ private ConfiguredEqualsVerifier( EnumSet warningsToSuppress, FactoryCache factoryCache, - GenericFactories genericFactories, boolean usingGetClass, Function fieldnameToGetter ) { this.warningsToSuppress = warningsToSuppress; this.factoryCache = factoryCache; - this.genericFactories = genericFactories; this.usingGetClass = usingGetClass; this.fieldnameToGetter = fieldnameToGetter; } @@ -62,7 +52,6 @@ public ConfiguredEqualsVerifier copy() { return new ConfiguredEqualsVerifier( EnumSet.copyOf(warningsToSuppress), new FactoryCache().merge(factoryCache), - genericFactories.copy(), usingGetClass, fieldnameToGetter ); @@ -88,7 +77,7 @@ public ConfiguredEqualsVerifier withGenericPrefabValues( Class otherType, Func1 factory ) { - PrefabValuesApi.addGenericPrefabValues(genericFactories, otherType, factory); + PrefabValuesApi.addGenericPrefabValues(factoryCache, otherType, factory); return this; } @@ -98,7 +87,7 @@ public ConfiguredEqualsVerifier withGenericPrefabValues( Class otherType, Func2 factory ) { - PrefabValuesApi.addGenericPrefabValues(genericFactories, otherType, factory); + PrefabValuesApi.addGenericPrefabValues(factoryCache, otherType, factory); return this; } @@ -139,7 +128,6 @@ public SingleTypeEqualsVerifierApi forClass(Class type) { type, EnumSet.copyOf(warningsToSuppress), new FactoryCache().merge(factoryCache), - genericFactories.copy(), 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 9712c29df..9d99721be 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,7 +10,6 @@ import nl.jqno.equalsverifier.Warning; import nl.jqno.equalsverifier.internal.checkers.*; import nl.jqno.equalsverifier.internal.exceptions.MessagingException; -import nl.jqno.equalsverifier.internal.reflection.instantiation.GenericPrefabValueProvider.GenericFactories; import nl.jqno.equalsverifier.internal.reflection.vintage.FactoryCache; import nl.jqno.equalsverifier.internal.util.*; import nl.jqno.equalsverifier.internal.util.Formatter; @@ -32,7 +31,6 @@ public class SingleTypeEqualsVerifierApi implements EqualsVerifierApi { private boolean hasRedefinedSuperclass = false; private Class redefinedSubclass = null; private FactoryCache factoryCache = new FactoryCache(); - private GenericFactories genericFactories = new GenericFactories(); private CachedHashCodeInitializer cachedHashCodeInitializer = CachedHashCodeInitializer.passthrough(); private Function fieldnameToGetter = null; @@ -72,7 +70,6 @@ public SingleTypeEqualsVerifierApi(Class type, Objenesis objenesis) { * @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 genericFactories ValueProvider that records generic prefab 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. @@ -86,7 +83,6 @@ public SingleTypeEqualsVerifierApi( Class type, EnumSet warningsToSuppress, FactoryCache factoryCache, - GenericFactories genericFactories, Objenesis objenesis, boolean usingGetClass, Function converter @@ -94,7 +90,6 @@ public SingleTypeEqualsVerifierApi( this(type, objenesis); this.warningsToSuppress = EnumSet.copyOf(warningsToSuppress); this.factoryCache = factoryCache; - this.genericFactories = genericFactories; this.usingGetClass = usingGetClass; this.fieldnameToGetter = converter; } @@ -171,7 +166,7 @@ public SingleTypeEqualsVerifierApi withGenericPrefabValues( Class otherType, Func1 factory ) { - PrefabValuesApi.addGenericPrefabValues(genericFactories, otherType, factory); + PrefabValuesApi.addGenericPrefabValues(factoryCache, otherType, factory); return this; } @@ -181,7 +176,7 @@ public SingleTypeEqualsVerifierApi withGenericPrefabValues( Class otherType, Func2 factory ) { - PrefabValuesApi.addGenericPrefabValues(genericFactories, otherType, factory); + PrefabValuesApi.addGenericPrefabValues(factoryCache, otherType, factory); return this; } @@ -448,7 +443,7 @@ private void performVerification() { Validations.validateClassCanBeVerified(type); Configuration config = buildConfig(); - Context context = new Context<>(config, factoryCache, genericFactories, objenesis); + Context context = new Context<>(config, factoryCache, objenesis); Validations.validateProcessedAnnotations( type, config.getAnnotationCache(), diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/GenericPrefabValueProvider.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/GenericPrefabValueProvider.java deleted file mode 100644 index e5d33a434..000000000 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/reflection/instantiation/GenericPrefabValueProvider.java +++ /dev/null @@ -1,120 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.instantiation; - -import java.util.*; -import nl.jqno.equalsverifier.Func; -import nl.jqno.equalsverifier.Func.Func1; -import nl.jqno.equalsverifier.Func.Func2; -import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException; -import nl.jqno.equalsverifier.internal.reflection.Tuple; -import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.util.Context; - -/** - * Provider of instances of generic types; factories of which have been provided by the user. - * - * Needs to be constructed by means of a GenericFactories instance, because of dependencies that - * would otherwise be cyclic, in the {@link Context} class. - */ -public class GenericPrefabValueProvider implements ValueProvider { - - private final Map> cache; - private final ValueProvider provider; - - /** - * Private constructor. - * - * @param factories The {@link GenericFactories} to use the cache from. - * @param provider A ValueProvider to use to provide instances for generic type parameters. - */ - public GenericPrefabValueProvider(GenericFactories factories, ValueProvider provider) { - this.cache = factories.cache; - this.provider = provider; - } - - /** - * Container for a cache that will be assigned to the GenericPrefabValueProvider when it is constructed. - */ - public static class GenericFactories { - - private final Map> cache = new HashMap<>(); - - /** - * Registers a prefab value with a single generic type argument. - * - * @param type The class of the prefabricated values. - * @param factory A factory that can produce instances for {@code type}. - * @param The type of the instances. - */ - public void register(Class type, Func1 factory) { - Key key = new Key(type, null); - cache.put(key, factory); - } - - /** - * Registers a prefab value with two generic type arguments. - * - * @param type The class of the prefabricated values. - * @param factory A factory that can produce instances for {@code type}. - * @param The type of the instances. - */ - public void register(Class type, Func2 factory) { - Key key = new Key(type, null); - cache.put(key, factory); - } - - /** - * Copies the cache of this GenericFactories into a new instance. - * - * @return A copy of this GenericFactories. - */ - public GenericFactories copy() { - GenericFactories copy = new GenericFactories(); - copy.cache.putAll(this.cache); - return copy; - } - } - - /** {@inheritDoc} */ - @Override - public Optional> provide(TypeTag tag, String label) { - Class type = tag.getType(); - Optional> maybeFactory = findFactory(type, label); - if (!maybeFactory.isPresent()) { - return Optional.empty(); - } - return findValue(tag, maybeFactory.get()); - } - - @SuppressWarnings("unchecked") - private Optional> findFactory(Class type, String label) { - Func result = (Func) cache.get(new Key(type, label)); - if (result == null) { - result = (Func) cache.get(new Key(type, null)); - } - return Optional.ofNullable(result); - } - - private Optional> findValue(TypeTag tag, Func factory) { - if (provider == null) { - throw new EqualsVerifierInternalBugException( - "valueProvider not initialized in GenericPrefabValueProvider" - ); - } - List redValues = new ArrayList<>(); - List blueValues = new ArrayList<>(); - List redCopyValues = new ArrayList<>(); - - for (TypeTag generic : tag.getGenericTypes()) { - Tuple tuple = provider.provideOrThrow(generic, null); - redValues.add(tuple.getRed()); - blueValues.add(tuple.getBlue()); - redCopyValues.add(tuple.getRedCopy()); - } - - T red = factory.apply(redValues); - T blue = factory.apply(blueValues); - T redCopy = factory.apply(redCopyValues); - - return Optional.of(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 a05e2b0e9..969f96277 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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import nl.jqno.equalsverifier.internal.reflection.ClassProbe; import nl.jqno.equalsverifier.internal.reflection.JavaApiPrefabValues; -import nl.jqno.equalsverifier.internal.reflection.instantiation.GenericPrefabValueProvider.GenericFactories; import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator; import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.FactoryCache; @@ -22,18 +21,13 @@ public final class Context { value = "EI_EXPOSE_REP2", justification = "FieldCache is inherently mutable" ) - public Context( - Configuration configuration, - FactoryCache factoryCache, - GenericFactories genericFactories, - Objenesis objenesis - ) { + public Context(Configuration configuration, FactoryCache factoryCache, Objenesis objenesis) { this.type = configuration.getType(); this.configuration = configuration; this.classProbe = new ClassProbe<>(configuration.getType()); FactoryCache cache = JavaApiPrefabValues.build().merge(factoryCache); - this.valueProvider = DefaultValueProviders.create(cache, genericFactories, objenesis); + this.valueProvider = DefaultValueProviders.create(cache, objenesis); this.subjectCreator = new SubjectCreator<>(configuration, valueProvider, objenesis); } diff --git a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/DefaultValueProviders.java b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/DefaultValueProviders.java index 7084e03e2..867ccf5ee 100644 --- a/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/DefaultValueProviders.java +++ b/equalsverifier-core/src/main/java/nl/jqno/equalsverifier/internal/util/DefaultValueProviders.java @@ -1,7 +1,8 @@ package nl.jqno.equalsverifier.internal.util; -import nl.jqno.equalsverifier.internal.reflection.instantiation.*; -import nl.jqno.equalsverifier.internal.reflection.instantiation.GenericPrefabValueProvider.GenericFactories; +import nl.jqno.equalsverifier.internal.reflection.instantiation.ChainedValueProvider; +import nl.jqno.equalsverifier.internal.reflection.instantiation.ValueProvider; +import nl.jqno.equalsverifier.internal.reflection.instantiation.VintageValueProvider; import nl.jqno.equalsverifier.internal.reflection.vintage.FactoryCache; import org.objenesis.Objenesis; @@ -9,19 +10,13 @@ public final class DefaultValueProviders { private DefaultValueProviders() {} - public static ValueProvider create( - FactoryCache factoryCache, - GenericFactories genericFactories, - Objenesis objenesis - ) { + public static ValueProvider create(FactoryCache factoryCache, Objenesis objenesis) { ChainedValueProvider mainChain = new ChainedValueProvider(); ChainedValueProvider vintageChain = new ChainedValueProvider(); ValueProvider vintage = new VintageValueProvider(vintageChain, factoryCache, objenesis); - ValueProvider genericPrefab = new GenericPrefabValueProvider(genericFactories, mainChain); - mainChain.register(genericPrefab, vintage); - vintageChain.register(genericPrefab); + mainChain.register(vintage); return mainChain; } 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 10a247e6e..529ec513c 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,14 +1,15 @@ package nl.jqno.equalsverifier.internal.util; +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 java.lang.reflect.Field; import nl.jqno.equalsverifier.Func.Func1; import nl.jqno.equalsverifier.Func.Func2; import nl.jqno.equalsverifier.internal.reflection.SuperclassIterable; -import nl.jqno.equalsverifier.internal.reflection.instantiation.GenericPrefabValueProvider.GenericFactories; import nl.jqno.equalsverifier.internal.reflection.vintage.FactoryCache; 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 { @@ -83,22 +84,30 @@ private static Field findField(Class type, String fieldName) { } public static void addGenericPrefabValues( - GenericFactories factories, + FactoryCache factoryCache, Class otherType, Func1 factory ) { Validations.validateNotNull(factory, "factory is null."); - Validations.validateGenericPrefabValues(otherType, 1); - factories.register(otherType, factory); + addGenericPrefabValueFactory(factoryCache, otherType, simple(factory, null), 1); } public static void addGenericPrefabValues( - GenericFactories factories, + FactoryCache factoryCache, Class otherType, Func2 factory ) { Validations.validateNotNull(factory, "factory is null."); - Validations.validateGenericPrefabValues(otherType, 2); - factories.register(otherType, factory); + addGenericPrefabValueFactory(factoryCache, otherType, simple(factory, null), 2); + } + + private static void addGenericPrefabValueFactory( + FactoryCache factoryCache, + Class otherType, + PrefabValueFactory factory, + int arity + ) { + Validations.validateGenericPrefabValues(otherType, arity); + factoryCache.put(otherType, factory); } } diff --git a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/GenericPrefabValueProviderTest.java b/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/GenericPrefabValueProviderTest.java deleted file mode 100644 index c644f9bc6..000000000 --- a/equalsverifier-core/src/test/java/nl/jqno/equalsverifier/internal/reflection/instantiation/GenericPrefabValueProviderTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package nl.jqno.equalsverifier.internal.reflection.instantiation; - -import static nl.jqno.equalsverifier.internal.testhelpers.TestValueProviders.INTS; -import static nl.jqno.equalsverifier.internal.testhelpers.TestValueProviders.STRINGS; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.*; -import nl.jqno.equalsverifier.internal.reflection.Tuple; -import nl.jqno.equalsverifier.internal.reflection.TypeTag; -import nl.jqno.equalsverifier.internal.reflection.instantiation.GenericPrefabValueProvider.GenericFactories; -import nl.jqno.equalsverifier.internal.testhelpers.TestValueProviders; -import org.junit.jupiter.api.Test; - -public class GenericPrefabValueProviderTest { - - private static final TypeTag INTEGER = new TypeTag(Integer.class); - private static final TypeTag STRING = new TypeTag(String.class); - private static final TypeTag LIST = new TypeTag(List.class, new TypeTag(String.class)); - private static final TypeTag SET = new TypeTag(Set.class, new TypeTag(String.class)); - private static final TypeTag MAP = new TypeTag(Map.class, INTEGER, STRING); - private static final TypeTag ENTRY = new TypeTag(Map.Entry.class, INTEGER, STRING); - - private ValueProvider prefab = TestValueProviders.simple(); - private GenericFactories factories = new GenericFactories(); - private GenericPrefabValueProvider sut = new GenericPrefabValueProvider(factories, prefab); - - @Test - public void generic1_aRegisteredValueCanBeFound() { - factories.register(LIST.getType(), (String s) -> list(s)); - assertEquals(STRINGS.map(this::list), sut.provide(LIST, null).get()); - } - - @Test - public void generic2_aRegisteredValueCanBeFound() { - factories.register(MAP.getType(), (Integer k, String v) -> map(k, v)); - assertEquals(Tuple.combine(INTS, STRINGS, this::map), sut.provide(MAP, null).get()); - } - - @Test - public void generic1_anUnregisteredValueCanNotBeFound() { - assertEquals(Optional.empty(), sut.provide(LIST, null)); - } - - @Test - public void generic2_anUnregisteredValueCanNotBeFound() { - assertEquals(Optional.empty(), sut.provide(MAP, null)); - } - - @Test - public void generic1_copy() { - // CHECKSTYLE OFF: VariableDeclarationUsageDistance - factories.register(LIST.getType(), (String s) -> list(s + "x")); - GenericFactories otherFactories = factories.copy(); - factories.register(SET.getType(), (String s) -> set(s + "y")); - - assertEquals(STRINGS.map(s -> set(s + "y")), sut.provideOrThrow(SET, null)); - - GenericPrefabValueProvider anotherSut = new GenericPrefabValueProvider( - otherFactories, - TestValueProviders.simple() - ); - assertEquals(STRINGS.map(s -> list(s + "x")), anotherSut.provideOrThrow(LIST, null)); - assertEquals(Optional.empty(), anotherSut.provide(SET, null)); - // CHECKSTYLE ON: VariableDeclarationUsageDistance - } - - @Test - public void generic2_copy() { - // CHECKSTYLE OFF: VariableDeclarationUsageDistance - factories.register(MAP.getType(), (Integer k, String v) -> map(k - 1, v + "x")); - GenericFactories otherFactories = factories.copy(); - factories.register(ENTRY.getType(), (Integer k, String v) -> entry(k + 1, v + "y")); - - assertEquals( - Tuple.combine(INTS, STRINGS, (k, v) -> entry(k + 1, v + "y")), - sut.provideOrThrow(ENTRY, null) - ); - - GenericPrefabValueProvider anotherSut = new GenericPrefabValueProvider( - otherFactories, - TestValueProviders.simple() - ); - assertEquals( - Tuple.combine(INTS, STRINGS, (k, v) -> map(k - 1, v + "x")), - anotherSut.provide(MAP, "original").get() - ); - assertEquals(Optional.empty(), anotherSut.provide(ENTRY, null)); - // CHECKSTYLE ON: VariableDeclarationUsageDistance - } - - private List list(String s) { - List result = new ArrayList<>(); - result.add(s); - return result; - } - - private Set set(String s) { - Set result = new HashSet<>(); - result.add(s); - return result; - } - - private Map map(Integer k, String v) { - Map result = new HashMap<>(); - result.put(k, v); - return result; - } - - private Map.Entry entry(Integer k, String v) { - return new AbstractMap.SimpleEntry<>(k, v); - } -}