diff --git a/testable-core/src/main/java/com/alibaba/testable/core/util/ConstructionUtil.java b/testable-core/src/main/java/com/alibaba/testable/core/util/ConstructionUtil.java index c99defe..1fcbc3f 100644 --- a/testable-core/src/main/java/com/alibaba/testable/core/util/ConstructionUtil.java +++ b/testable-core/src/main/java/com/alibaba/testable/core/util/ConstructionUtil.java @@ -5,7 +5,8 @@ import com.alibaba.testable.core.tool.OmniConstructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.Parameter; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; import static com.alibaba.testable.core.constant.ConstPool.DOLLAR; import static com.alibaba.testable.core.constant.ConstPool.DOT; @@ -19,13 +20,32 @@ public class ConstructionUtil { sourceCode.append("package ").append(clazz.getPackage().getName()).append(";\n") .append("public class ").append(getSubclassName(clazz)) .append(clazz.isInterface() ? " implements " : " extends ") - .append(clazz.getName().replace(DOLLAR, DOT)) + .append(getClassName(clazz)) .append(" {\n"); for (Method m : clazz.getMethods()) { if (!Modifier.isStatic(m.getModifiers()) && !Modifier.isFinal(m.getModifiers())) { - sourceCode.append("\tpublic ").append(m.getReturnType().getName().replace(DOLLAR, DOT)).append(" ") + sourceCode.append("\tpublic "); + TypeVariable[] typeParameters = m.getTypeParameters(); + if (typeParameters.length > 0) { + sourceCode.append("<"); + for (int i = 0; i < typeParameters.length; i++) { + sourceCode.append(typeParameters[i].getName()).append(" extends "); + Type[] bounds = typeParameters[i].getBounds(); + for (int j = 0; j < bounds.length; j++) { + sourceCode.append(getClassName(bounds[j])); + if (j < bounds.length - 1) { + sourceCode.append(" & "); + } + } + if (i < typeParameters.length - 1) { + sourceCode.append(", "); + } + } + sourceCode.append("> "); + } + sourceCode.append(getClassName(m.getGenericReturnType())).append(" ") .append(m.getName()).append("("); - Class[] parameters = m.getParameterTypes(); + Type[] parameters = m.getGenericParameterTypes(); for (int i = 0; i < parameters.length; i++) { sourceCode.append(getParameterName(parameters[i])).append(" p").append(i); if (i < parameters.length - 1) { @@ -34,8 +54,9 @@ public class ConstructionUtil { } sourceCode.append(") {\n"); if (!m.getReturnType().equals(void.class)) { - sourceCode.append("\t\treturn ").append(OmniConstructor.class.getName().replace(DOLLAR, DOT)).append(".") - .append("newInstance(").append(m.getReturnType().getName().replace(DOLLAR, DOT)).append(".class);\n"); + sourceCode.append("\t\treturn (").append(getClassName(m.getGenericReturnType())).append(") ") + .append(getClassName(OmniConstructor.class)).append(".") + .append("newInstance(").append(getClassName(m.getReturnType())).append(".class);\n"); } sourceCode.append("\t}\n"); } @@ -45,6 +66,8 @@ public class ConstructionUtil { try { return (T) InMemoryJavaCompiler.newInstance() .useParentClassLoader(clazz.getClassLoader()) + .useOptions("-Xlint:unchecked") + .ignoreWarnings() .compile(clazz.getPackage().getName() + DOT + getSubclassName(clazz), sourceCode.toString()) .newInstance(); } catch (Exception e) { @@ -52,11 +75,20 @@ public class ConstructionUtil { } } - private static String getParameterName(Class parameter) { - if (parameter.isArray()) { - return getParameterName(parameter.getComponentType()) + "[]"; + private static String getClassName(Type clazz) { + if (clazz instanceof Class) { + return ((Class)clazz).getName().replace(DOLLAR, DOT); + } else if (clazz instanceof TypeVariable) { + return ((TypeVariable)clazz).getName(); } - return parameter.getName().replace(DOLLAR, DOT); + return clazz.toString().replaceAll("@.*$", "").replaceAll("^.* ", ""); + } + + private static String getParameterName(Type parameter) { + if (parameter instanceof Class && ((Class)parameter).isArray()) { + return getParameterName(((Class)parameter).getComponentType()) + "[]"; + } + return getClassName(parameter); } private static String getSubclassName(Class clazz) { diff --git a/testable-core/src/test/java/com/alibaba/testable/core/util/ConstructionUtilTest.java b/testable-core/src/test/java/com/alibaba/testable/core/util/ConstructionUtilTest.java index 862117a..e84a52f 100644 --- a/testable-core/src/test/java/com/alibaba/testable/core/util/ConstructionUtilTest.java +++ b/testable-core/src/test/java/com/alibaba/testable/core/util/ConstructionUtilTest.java @@ -13,6 +13,7 @@ class ConstructionUtilTest { int func2(double d, boolean b); String fun3(String s, byte[] b); EmptyInterface fun4(RealInterface i); + T fun5(T i); } public static abstract class AbstractClazz implements RealInterface {