mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-03-14 11:50:28 +08:00
feat: support generate method with template types
This commit is contained in:
parent
038ae8dba0
commit
b654a3cfaa
@ -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<Method>[] 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) {
|
||||
|
@ -13,6 +13,7 @@ class ConstructionUtilTest {
|
||||
int func2(double d, boolean b);
|
||||
String fun3(String s, byte[] b);
|
||||
EmptyInterface fun4(RealInterface i);
|
||||
<T> T fun5(T i);
|
||||
}
|
||||
|
||||
public static abstract class AbstractClazz implements RealInterface {
|
||||
|
Loading…
Reference in New Issue
Block a user