use void type instead of null type

This commit is contained in:
金戟 2021-04-24 11:47:41 +08:00
parent af409a65a8
commit 78d7ee21a6
3 changed files with 14 additions and 56 deletions

View File

@ -18,8 +18,7 @@ import static com.alibaba.testable.core.constant.ConstPool.THIS_REF;
*/ */
public class OmniClassHandler extends BaseClassHandler { public class OmniClassHandler extends BaseClassHandler {
private static final String TESTABLE_NULL_TYPE = "com.alibaba.testable.core.model.TestableNull"; private static final String VOID_TYPE = "java/lang/Void";
private static final String NULL_TYPE = "javax.lang.model.type.NullType";
private static final String IGNORE = "ignore"; private static final String IGNORE = "ignore";
private static final String METHOD_START = "("; private static final String METHOD_START = "(";
private static final String VOID_METHOD_END = ")V"; private static final String VOID_METHOD_END = ")V";
@ -35,12 +34,12 @@ public class OmniClassHandler extends BaseClassHandler {
if (isInterface(cn) || isJunitTestClass(cn) || isUninstantiableClass(cn) || hasSpecialAnnotation(cn)) { if (isInterface(cn) || isJunitTestClass(cn) || isUninstantiableClass(cn) || hasSpecialAnnotation(cn)) {
return; return;
} }
addConstructorWithNullTypeParameter(cn); addConstructorWithVoidTypeParameter(cn);
} }
private void addConstructorWithNullTypeParameter(ClassNode cn) { private void addConstructorWithVoidTypeParameter(ClassNode cn) {
MethodNode constructor = new MethodNode(ACC_PUBLIC, CONSTRUCTOR, MethodNode constructor = new MethodNode(ACC_PUBLIC, CONSTRUCTOR,
METHOD_START + ClassUtil.toByteCodeClassName(NULL_TYPE) + VOID_METHOD_END, null, null); METHOD_START + ClassUtil.toByteCodeClassName(VOID_TYPE) + VOID_METHOD_END, null, null);
LabelNode start = new LabelNode(new Label()); LabelNode start = new LabelNode(new Label());
LabelNode end = new LabelNode(new Label()); LabelNode end = new LabelNode(new Label());
if (cn.superName.equals(CLASS_OBJECT)) { if (cn.superName.equals(CLASS_OBJECT)) {
@ -48,7 +47,7 @@ public class OmniClassHandler extends BaseClassHandler {
constructor.localVariables = createLocalVariables(cn, start, end); constructor.localVariables = createLocalVariables(cn, start, end);
constructor.maxStack = 1; constructor.maxStack = 1;
} else { } else {
constructor.instructions = invokeSuperWithTestableNullParameter(cn, start, end); constructor.instructions = invokeSuperWithTestableVoidParameter(cn, start, end);
constructor.localVariables = createLocalVariables(cn, start, end); constructor.localVariables = createLocalVariables(cn, start, end);
constructor.maxStack = 3; constructor.maxStack = 3;
} }
@ -79,8 +78,8 @@ public class OmniClassHandler extends BaseClassHandler {
} }
private boolean isInterface(ClassNode cn) { private boolean isInterface(ClassNode cn) {
// is interface or the object class // is interface, Object class or Void class
return (cn.access & ACC_INTERFACE) != 0 || cn.superName == null; return (cn.access & ACC_INTERFACE) != 0 || cn.superName == null || VOID_TYPE.equals(cn.name);
} }
private boolean isJunitTestClass(ClassNode cn) { private boolean isJunitTestClass(ClassNode cn) {
@ -110,16 +109,13 @@ public class OmniClassHandler extends BaseClassHandler {
return il; return il;
} }
private InsnList invokeSuperWithTestableNullParameter(ClassNode cn, LabelNode start, LabelNode end) { private InsnList invokeSuperWithTestableVoidParameter(ClassNode cn, LabelNode start, LabelNode end) {
InsnList il = new InsnList(); InsnList il = new InsnList();
il.add(start); il.add(start);
il.add(new VarInsnNode(ALOAD, 0)); il.add(new VarInsnNode(ALOAD, 0));
il.add(new TypeInsnNode(NEW, ClassUtil.toSlashSeparatedName(TESTABLE_NULL_TYPE))); il.add(new VarInsnNode(ALOAD, 1));
il.add(new InsnNode(DUP));
il.add(new MethodInsnNode(INVOKESPECIAL, ClassUtil.toSlashSeparatedName(TESTABLE_NULL_TYPE), CONSTRUCTOR,
VOID_METHOD, false));
il.add(new MethodInsnNode(INVOKESPECIAL, cn.superName, CONSTRUCTOR, il.add(new MethodInsnNode(INVOKESPECIAL, cn.superName, CONSTRUCTOR,
METHOD_START + ClassUtil.toByteCodeClassName(NULL_TYPE) + VOID_METHOD_END, false)); METHOD_START + ClassUtil.toByteCodeClassName(VOID_TYPE) + VOID_METHOD_END, false));
il.add(new InsnNode(RETURN)); il.add(new InsnNode(RETURN));
il.add(end); il.add(end);
return il; return il;
@ -128,7 +124,7 @@ public class OmniClassHandler extends BaseClassHandler {
private List<LocalVariableNode> createLocalVariables(ClassNode cn, LabelNode start, LabelNode end) { private List<LocalVariableNode> createLocalVariables(ClassNode cn, LabelNode start, LabelNode end) {
return CollectionUtil.listOf( return CollectionUtil.listOf(
new LocalVariableNode(THIS_REF, ClassUtil.toByteCodeClassName(cn.name), null, start, end, 0), new LocalVariableNode(THIS_REF, ClassUtil.toByteCodeClassName(cn.name), null, start, end, 0),
new LocalVariableNode(IGNORE, ClassUtil.toByteCodeClassName(NULL_TYPE), null, start, end, 1) new LocalVariableNode(IGNORE, ClassUtil.toByteCodeClassName(VOID_TYPE), null, start, end, 1)
); );
} }

View File

@ -1,36 +0,0 @@
package com.alibaba.testable.core.model;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.NullType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeVisitor;
import java.lang.annotation.Annotation;
import java.util.List;
/**
* @author flin
*/
public class TestableNull implements NullType {
@Override
public TypeKind getKind() {
return TypeKind.NULL;
}
@Override
public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return v.visitNull(this, p);
}
public List<? extends AnnotationMirror> getAnnotationMirrors() {
return null;
}
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
return null;
}
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
return null;
}
}

View File

@ -1,11 +1,9 @@
package com.alibaba.testable.core.tool; package com.alibaba.testable.core.tool;
import com.alibaba.testable.core.exception.ClassConstructionException; import com.alibaba.testable.core.exception.ClassConstructionException;
import com.alibaba.testable.core.model.TestableNull;
import com.alibaba.testable.core.util.LogUtil; import com.alibaba.testable.core.util.LogUtil;
import com.alibaba.testable.core.util.TypeUtil; import com.alibaba.testable.core.util.TypeUtil;
import javax.lang.model.type.NullType;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
@ -193,8 +191,8 @@ public class OmniConstructor {
throws InstantiationException, IllegalAccessException, InvocationTargetException { throws InstantiationException, IllegalAccessException, InvocationTargetException {
constructor.setAccessible(true); constructor.setAccessible(true);
Class<?>[] types = constructor.getParameterTypes(); Class<?>[] types = constructor.getParameterTypes();
if (types.length == 1 && types[0].equals(NullType.class)) { if (types.length == 1 && types[0].equals(Void.class)) {
return constructor.newInstance(new TestableNull()); return constructor.newInstance(OmniConstructor.newInstance(Void.class));
} else { } else {
Object[] args = new Object[types.length]; Object[] args = new Object[types.length];
for (int i = 0; i < types.length; i++) { for (int i = 0; i < types.length; i++) {
@ -209,7 +207,7 @@ public class OmniConstructor {
int minimalParametersSize = 999; int minimalParametersSize = 999;
for (Constructor<?> constructor : clazz.getDeclaredConstructors()) { for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
Class<?>[] types = constructor.getParameterTypes(); Class<?>[] types = constructor.getParameterTypes();
if (types.length == 1 && types[0].equals(NullType.class)) { if (types.length == 1 && types[0].equals(Void.class)) {
return constructor; return constructor;
} else if (types.length < minimalParametersSize && !anyMatch(types, clazz)) { } else if (types.length < minimalParametersSize && !anyMatch(types, clazz)) {
minimalParametersSize = types.length; minimalParametersSize = types.length;