Make class instances with type parameter info equal to equivalent parameterized types. (#1542)

* Make class instances with type parameter info equal to equivalent parameterized types.

* Add test for flipped version.

* Clean up unnecessary collection calls, do some housekeeping.

* Spotless

---------

Co-authored-by: Zac Sweers <pandanomic@gmail.com>
This commit is contained in:
Nicholas DeLello
2023-05-05 18:19:21 -04:00
committed by GitHub
parent c11f0e168c
commit ef99a13bb7
2 changed files with 30 additions and 0 deletions

View File

@@ -215,11 +215,18 @@ public object Types {
is Class<*> -> {
return if (b is GenericArrayType) {
equals(a.componentType, b.genericComponentType)
} else if (b is ParameterizedType && a.rawType == b.rawType) {
// Class instance with generic info, from method return types
return a.typeParameters.flatMap { it.bounds.toList() } == b.actualTypeArguments.toList()
} else {
a == b // Class already specifies equals().
}
}
is ParameterizedType -> {
// Class instance with generic info, from method return types
if (b is Class<*> && a.rawType == b.rawType) {
return b.typeParameters.map { it.bounds }.toTypedArray().flatten() == a.actualTypeArguments.toList()
}
if (b !is ParameterizedType) return false
val aTypeArguments = if (a is ParameterizedTypeImpl) a.typeArguments else a.actualTypeArguments
val bTypeArguments = if (b is ParameterizedTypeImpl) b.typeArguments else b.actualTypeArguments

View File

@@ -24,6 +24,7 @@ import static org.junit.Assert.fail;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -33,6 +34,7 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import kotlin.NotImplementedError;
import org.junit.Test;
public final class TypesTest {
@@ -204,6 +206,8 @@ public final class TypesTest {
private static final class D<T> {}
private static final class E<T extends A, T2 extends B> {}
/**
* Given a parameterized type {@code A<B, C>}, returns B. If the specified type is not a generic
* type, returns null.
@@ -292,6 +296,25 @@ public final class TypesTest {
assertThat(Types.equals(Types.arrayOf(String.class), String[].class)).isTrue();
}
private E<A, B> methodReturningE() {
throw new NotImplementedError(); // Intentionally not implemented
}
@Test
public void parameterizedTypeMatchesClassWithGenericInfoFromReturn() {
Type type = Types.newParameterizedTypeWithOwner(TypesTest.class, E.class, A.class, B.class);
Method returningE = null;
for (Method method : TypesTest.class.getDeclaredMethods()) {
if (method.getName().contains("methodReturningE")) {
returningE = method;
break;
}
}
Type rawType = Types.getRawType(returningE.getGenericReturnType());
assertThat(Types.equals(type, rawType)).isTrue();
assertThat(Types.equals(rawType, type)).isTrue();
}
@Test
public void parameterizedAndWildcardTypesCannotHavePrimitiveArguments() throws Exception {
try {