|
@@ -9,6 +9,7 @@ package net.ranides.assira.junit;
|
|
|
|
|
|
|
|
import java.lang.reflect.Array;
|
|
import java.lang.reflect.Array;
|
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Field;
|
|
|
|
|
+import java.lang.reflect.Member;
|
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Method;
|
|
|
import java.lang.reflect.ParameterizedType;
|
|
import java.lang.reflect.ParameterizedType;
|
|
|
import java.lang.reflect.Type;
|
|
import java.lang.reflect.Type;
|
|
@@ -55,47 +56,55 @@ final class TestUtils {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public static Class<?> typeof(Function<?,?> function) {
|
|
public static Class<?> typeof(Function<?,?> function) {
|
|
|
-// if(!function.getClass().isSynthetic()) {
|
|
|
|
|
-// return typeof_generic(function);
|
|
|
|
|
-// } else {
|
|
|
|
|
- return typeof_lambda(function);
|
|
|
|
|
-// }
|
|
|
|
|
|
|
+ Class<?> clazz = function.getClass();
|
|
|
|
|
+ if(!clazz.isSynthetic()) {
|
|
|
|
|
+ return typeof_generic(clazz);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return typeof_lambda(clazz);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static Class<?> typeof_lambda(Function<?,?> function) {
|
|
|
|
|
- // Masakra, jeśli lambda jest closure'm, to jej "metoda" pobiera więcej niż 1 argument.
|
|
|
|
|
- // Te argumenty są "bindowane" przez inne metody-gettery pomocnicze.
|
|
|
|
|
- //
|
|
|
|
|
- // Dałoby się te argumenty ignorować "mądrze", bo są listowane w ConstantPool,
|
|
|
|
|
- // ale na razie po prostu weźmy pierwsze "coś", które ma więcej niż 1 argument
|
|
|
|
|
- // i módlmy się, żeby to nie było żadne syntetyczne gówno.
|
|
|
|
|
-
|
|
|
|
|
- ConstantPool cp = Li.get(function.getClass());
|
|
|
|
|
-
|
|
|
|
|
- for(int i=0; i<cp.getSize(); i++) {
|
|
|
|
|
- String[] info;
|
|
|
|
|
- try {
|
|
|
|
|
- info = cp.getMemberRefInfoAt(i);
|
|
|
|
|
- } catch(Exception ex) {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- String parent = info[0];
|
|
|
|
|
- String name = info[1];
|
|
|
|
|
- if("java/lang/Object".equals(parent) || "java/lang/Class".equals(parent) || "<init>".equals(name)) {
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
+ private static Class<?> typeof_generic(Class<?> clazz) {
|
|
|
|
|
+ ParameterizedType it = getGenericInterface(clazz, Function.class);
|
|
|
|
|
+ java.lang.reflect.Type pt = it.getActualTypeArguments()[1];
|
|
|
|
|
+ if(pt instanceof Class<?>) {
|
|
|
|
|
+ return (Class<?>)pt;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(pt instanceof ParameterizedType) {
|
|
|
|
|
+ return (Class<?>)(((ParameterizedType)pt).getRawType());
|
|
|
|
|
+ }
|
|
|
|
|
+ throw new AssertionError("Deduction of return type failed. Unsupported function: " + clazz);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static ParameterizedType getGenericInterface(Class<?> type, Class<?> intface) {
|
|
|
|
|
+ for(java.lang.reflect.Type t : type.getGenericInterfaces()) {
|
|
|
|
|
+ ParameterizedType pt = (ParameterizedType)t;
|
|
|
|
|
+ if( intface.equals(pt.getRawType()) ) {
|
|
|
|
|
+ return pt;
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
+ throw new AssertionError(type.getName() + " does not implement " + intface.getName());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static Class<?> typeof_lambda(Class<?> clazz) {
|
|
|
|
|
+ // dość generyczne filtrowanie, które chyba eliminuje różne cuda
|
|
|
|
|
+ // związane z wewnętrzną implementacją lambdy. uwaga! to działa TYLKO
|
|
|
|
|
+ // dla lambdy.
|
|
|
|
|
+
|
|
|
|
|
+ ConstantPool cp = Li.get(clazz);
|
|
|
|
|
+
|
|
|
|
|
+ for(int i=0, n=cp.getSize(); i<n; i++) {
|
|
|
try {
|
|
try {
|
|
|
- if(net.ranides.asm.Type.getArgumentTypes(info[2]).length < 1) {
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
+ Member member = cp.getMethodAt(i);
|
|
|
|
|
+ if(member instanceof Method) {
|
|
|
|
|
+ Method method = (Method)member;
|
|
|
|
|
+ return method.getReturnType();
|
|
|
}
|
|
}
|
|
|
- } catch(Exception ex) {
|
|
|
|
|
|
|
+ } catch(IllegalArgumentException $0) {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- return vm2class(function.getClass().getClassLoader(), net.ranides.asm.Type.getReturnType(info[2]).getDescriptor());
|
|
|
|
|
}
|
|
}
|
|
|
- throw new AssertionError("Deduction of return type failed. Unsupported lambda: " + function);
|
|
|
|
|
|
|
+ throw new AssertionError("Deduction of return type failed. Unsupported lambda: " + clazz);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static Class<?> typeof_supplier(Method method) throws AssertionError {
|
|
private static Class<?> typeof_supplier(Method method) throws AssertionError {
|
|
@@ -123,48 +132,6 @@ final class TestUtils {
|
|
|
throw new AssertionError("You can't use wildcard generic types in method: " + method, cause4method(method, "Invalid declaration"));
|
|
throw new AssertionError("You can't use wildcard generic types in method: " + method, cause4method(method, "Invalid declaration"));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @SuppressWarnings("PMD")
|
|
|
|
|
- private static Class<?> vm2class(ClassLoader loader, String vmtype) {
|
|
|
|
|
- try {
|
|
|
|
|
- if(vmtype.startsWith("[")) {
|
|
|
|
|
- return Array.newInstance(vm2class(loader, vmtype.substring(1)), 0).getClass();
|
|
|
|
|
- }
|
|
|
|
|
- if(vmtype.startsWith("L") && vmtype.endsWith(";")) {
|
|
|
|
|
- return Class.forName(vmtype.substring(1,vmtype.length()-1).replace('/', '.'), false, loader);
|
|
|
|
|
- }
|
|
|
|
|
- if("Z".equals(vmtype)) {
|
|
|
|
|
- return boolean.class;
|
|
|
|
|
- }
|
|
|
|
|
- if("B".equals(vmtype)) {
|
|
|
|
|
- return byte.class;
|
|
|
|
|
- }
|
|
|
|
|
- if("C".equals(vmtype)) {
|
|
|
|
|
- return char.class;
|
|
|
|
|
- }
|
|
|
|
|
- if("S".equals(vmtype)) {
|
|
|
|
|
- return short.class;
|
|
|
|
|
- }
|
|
|
|
|
- if("I".equals(vmtype)) {
|
|
|
|
|
- return int.class;
|
|
|
|
|
- }
|
|
|
|
|
- if("J".equals(vmtype)) {
|
|
|
|
|
- return long.class;
|
|
|
|
|
- }
|
|
|
|
|
- if("F".equals(vmtype)) {
|
|
|
|
|
- return float.class;
|
|
|
|
|
- }
|
|
|
|
|
- if("D".equals(vmtype)) {
|
|
|
|
|
- return double.class;
|
|
|
|
|
- }
|
|
|
|
|
- if("V".equals(vmtype)) {
|
|
|
|
|
- return void.class;
|
|
|
|
|
- }
|
|
|
|
|
- } catch(ClassNotFoundException cause) {
|
|
|
|
|
- throw rethrow(cause);
|
|
|
|
|
- }
|
|
|
|
|
- throw new AssertionError("Unknown type: " + vmtype);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
public static Exception cause4method(Method method, String message) {
|
|
public static Exception cause4method(Method method, String message) {
|
|
|
Exception e = new Exception(message); // NOPMD
|
|
Exception e = new Exception(message); // NOPMD
|
|
|
e.setStackTrace(new StackTraceElement[]{
|
|
e.setStackTrace(new StackTraceElement[]{
|