fix case of using member method invocation as invoker

This commit is contained in:
金戟 2020-05-29 19:18:54 +08:00
parent df0e6766aa
commit 4f7fb190db
2 changed files with 42 additions and 29 deletions

View File

@ -3,7 +3,6 @@ package com.alibaba.testable.translator;
import com.alibaba.testable.model.TestableContext; import com.alibaba.testable.model.TestableContext;
import com.alibaba.testable.util.ConstPool; import com.alibaba.testable.util.ConstPool;
import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Name;
@ -49,8 +48,8 @@ public class EnableTestableInjectTranslator extends BaseTranslator {
} }
/** /**
* Case: new Demo() * new Demo() -> n.e.w(Demo.class)
* Case: member() * member() -> n.e.f(this, "member")
*/ */
@Override @Override
public void visitExec(JCExpressionStatement jcExpressionStatement) { public void visitExec(JCExpressionStatement jcExpressionStatement) {
@ -59,18 +58,8 @@ public class EnableTestableInjectTranslator extends BaseTranslator {
} }
/** /**
* For member method invocation break point * return new Demo() -> return n.e.w(Demo.class)
* Case: call(new Demo()) * return member() -> return n.e.f(this, "member")
*/
@Override
public void visitApply(JCMethodInvocation tree) {
tree.args = checkAndExchange(tree.args);
super.visitApply(tree);
}
/**
* Case: return new Demo()
* Case: return member()
*/ */
@Override @Override
public void visitReturn(JCReturn jcReturn) { public void visitReturn(JCReturn jcReturn) {
@ -80,8 +69,8 @@ public class EnableTestableInjectTranslator extends BaseTranslator {
/** /**
* Record all private fields * Record all private fields
* Case: Demo d = new Demo() * Demo d = new Demo() -> Demo d = n.e.w(Demo.class)
* Case: Demo d = member() * Demo d = member() -> Demo d = n.e.f(this, "member")
*/ */
@Override @Override
public void visitVarDef(JCVariableDecl jcVariableDecl) { public void visitVarDef(JCVariableDecl jcVariableDecl) {
@ -93,8 +82,8 @@ public class EnableTestableInjectTranslator extends BaseTranslator {
} }
/** /**
* Case: new Demo().call() * new Demo().call() -> n.e.w(Demo.class).call()
* Case: member().call() * member().call() -> n.e.f(this, "member").call()
*/ */
@Override @Override
public void visitSelect(JCFieldAccess jcFieldAccess) { public void visitSelect(JCFieldAccess jcFieldAccess) {
@ -102,6 +91,16 @@ public class EnableTestableInjectTranslator extends BaseTranslator {
super.visitSelect(jcFieldAccess); super.visitSelect(jcFieldAccess);
} }
/**
* For member method invocation break point
* call(new Demo()) -> call(n.e.w(Demo.class))
*/
@Override
public void visitApply(JCMethodInvocation tree) {
tree.args = checkAndExchange(tree.args);
super.visitApply(tree);
}
/** /**
* For new operation break point * For new operation break point
*/ */
@ -150,7 +149,7 @@ public class EnableTestableInjectTranslator extends BaseTranslator {
return expr != null && expr.getClass().equals(JCNewClass.class); return expr != null && expr.getClass().equals(JCNewClass.class);
} }
private JCMethodInvocation getGlobalNewInvocation(JCNewClass newClassExpr, Name className) { private JCExpression getGlobalNewInvocation(JCNewClass newClassExpr, Name className) {
JCFieldAccess snClass = cx.treeMaker.Select(cx.treeMaker.Ident(cx.names.fromString(ConstPool.NE_PKG)), JCFieldAccess snClass = cx.treeMaker.Select(cx.treeMaker.Ident(cx.names.fromString(ConstPool.NE_PKG)),
cx.names.fromString(ConstPool.NE_CLS)); cx.names.fromString(ConstPool.NE_CLS));
JCFieldAccess snMethod = cx.treeMaker.Select(snClass, cx.names.fromString(ConstPool.NE_NEW)); JCFieldAccess snMethod = cx.treeMaker.Select(snClass, cx.names.fromString(ConstPool.NE_NEW));
@ -161,7 +160,7 @@ public class EnableTestableInjectTranslator extends BaseTranslator {
return cx.treeMaker.Apply(List.<JCExpression>nil(), snMethod, args.toList()); return cx.treeMaker.Apply(List.<JCExpression>nil(), snMethod, args.toList());
} }
private JCMethodInvocation getGlobalMemberInvocation(Name methodName, List<JCExpression> param) { private JCExpression getGlobalMemberInvocation(Name methodName, List<JCExpression> param) {
JCFieldAccess snClass = cx.treeMaker.Select(cx.treeMaker.Ident(cx.names.fromString(ConstPool.NE_PKG)), JCFieldAccess snClass = cx.treeMaker.Select(cx.treeMaker.Ident(cx.names.fromString(ConstPool.NE_PKG)),
cx.names.fromString(ConstPool.NE_CLS)); cx.names.fromString(ConstPool.NE_CLS));
JCFieldAccess snMethod = cx.treeMaker.Select(snClass, cx.names.fromString(ConstPool.NE_FUN)); JCFieldAccess snMethod = cx.treeMaker.Select(snClass, cx.names.fromString(ConstPool.NE_FUN));
@ -169,6 +168,23 @@ public class EnableTestableInjectTranslator extends BaseTranslator {
args.add(cx.treeMaker.Ident(cx.names.fromString(ConstPool.REF_THIS))); args.add(cx.treeMaker.Ident(cx.names.fromString(ConstPool.REF_THIS)));
args.add(cx.treeMaker.Literal(methodName.toString())); args.add(cx.treeMaker.Literal(methodName.toString()));
args.addAll(param); args.addAll(param);
return cx.treeMaker.Apply(List.<JCExpression>nil(), snMethod, args.toList()); JCMethodInvocation apply = cx.treeMaker.Apply(List.<JCExpression>nil(), snMethod, args.toList());
for (JCMethodDecl m : methods) {
if (m.restype != null && m.name.equals(methodName) && paramEquals(m.params, param)) {
JCTypeCast cast = cx.treeMaker.TypeCast(m.restype, apply);
return cx.treeMaker.Parens(cast);
}
}
return apply;
}
private boolean paramEquals(List<JCVariableDecl> p1, List<JCExpression> p2) {
if (p1.length() != p2.length()) {
return false;
}
for (int i = 0; i < p1.length(); i++) {
// TODO: Compare parameters type
}
return true;
} }
} }

View File

@ -5,17 +5,14 @@ package com.alibaba.testable.util;
*/ */
public final class ConstPool { public final class ConstPool {
public static final String CONSTRUCTOR_NAME = "<init>";
public static final String TYPE_VOID = "void";
public static final String TESTABLE = "Testable";
public static final String NE_PKG = "n"; public static final String NE_PKG = "n";
public static final String NE_CLS = "e"; public static final String NE_CLS = "e";
public static final String NE_NEW = "w"; public static final String NE_NEW = "w";
public static final String NE_FUN = "f"; public static final String NE_FUN = "f";
public static final String NE_PKG_CLS = "n.e"; public static final String NE_PKG_CLS = NE_PKG + ".e";
public static final String NE_POOL = "n.e.p"; public static final String NE_POOL = NE_PKG_CLS + ".p";
public static final String NE_ADD_W = "n.e.aw"; public static final String NE_ADD_W = NE_PKG_CLS + ".aw";
public static final String NE_ADD_F = "n.e.af"; public static final String NE_ADD_F = NE_PKG_CLS + ".af";
public static final String TYPE_TO_CLASS = "class"; public static final String TYPE_TO_CLASS = "class";
public static final String REF_THIS = "this"; public static final String REF_THIS = "this";
public static final String TESTABLE_PRIVATE_ACCESSOR = "com.alibaba.testable.accessor.PrivateAccessor"; public static final String TESTABLE_PRIVATE_ACCESSOR = "com.alibaba.testable.accessor.PrivateAccessor";