mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-10 20:30:11 +08:00
use global setter replace testable class setter
This commit is contained in:
parent
35a29aa95c
commit
229477a336
@ -0,0 +1,47 @@
|
||||
package com.alibaba.testable.accessor;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author flin
|
||||
*/
|
||||
public class PrivateAccessor {
|
||||
|
||||
public static <T> T get(Object ref, String field) {
|
||||
try {
|
||||
Field declaredField = ref.getClass().getDeclaredField(field);
|
||||
declaredField.setAccessible(true);
|
||||
return (T)declaredField.get(ref);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void set(Object ref, String field, T value) {
|
||||
try {
|
||||
Field declaredField = ref.getClass().getDeclaredField(field);
|
||||
declaredField.setAccessible(true);
|
||||
declaredField.set(ref, value);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T invoke(Object ref, String method, Object... args) {
|
||||
try {
|
||||
Class[] cls = new Class[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
cls[i] = args[i].getClass();
|
||||
}
|
||||
Method declaredMethod = ref.getClass().getDeclaredMethod(method, cls);
|
||||
declaredMethod.setAccessible(true);
|
||||
return (T)declaredMethod.invoke(ref, args);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.alibaba.testable.generator;
|
||||
|
||||
import com.alibaba.testable.model.TestableContext;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
|
||||
/**
|
||||
* @author flin
|
||||
*/
|
||||
public abstract class BaseGenerator {
|
||||
|
||||
protected final TestableContext cx;
|
||||
|
||||
protected BaseGenerator(TestableContext cx) {
|
||||
this.cx = cx;
|
||||
}
|
||||
|
||||
protected JCExpression nameToExpression(String dotName) {
|
||||
String[] nameParts = dotName.split("\\.");
|
||||
JCExpression e = cx.treeMaker.Ident(cx.names.fromString(nameParts[0]));
|
||||
for (int i = 1; i < nameParts.length; i++) {
|
||||
e = cx.treeMaker.Select(e, cx.names.fromString(nameParts[i]));
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.alibaba.testable.generator;
|
||||
|
||||
import com.alibaba.testable.model.TestableContext;
|
||||
import com.alibaba.testable.util.ConstPool;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.util.List;
|
||||
|
||||
/**
|
||||
* @author flin
|
||||
*/
|
||||
public class PrivateAccessStatementGenerator extends BaseGenerator {
|
||||
|
||||
public PrivateAccessStatementGenerator(TestableContext cx) {
|
||||
super(cx);
|
||||
}
|
||||
|
||||
public JCExpression fetchSetterStatement(JCExpressionStatement jcExpressionStatement) {
|
||||
JCAssign assign = (JCAssign)jcExpressionStatement.expr;
|
||||
JCFieldAccess setter = cx.treeMaker.Select(nameToExpression(ConstPool.TESTABLE_PRIVATE_ACCESSOR),
|
||||
cx.names.fromString("set"));
|
||||
return cx.treeMaker.Apply(List.<JCExpression>nil(), setter, List.of(((JCFieldAccess)assign.lhs).selected,
|
||||
cx.treeMaker.Literal(((JCFieldAccess)assign.lhs).name.toString()), assign.rhs));
|
||||
}
|
||||
}
|
@ -11,12 +11,10 @@ import java.nio.file.Files;
|
||||
*
|
||||
* @author flin
|
||||
*/
|
||||
public class StaticNewClassGenerator {
|
||||
|
||||
private final TestableContext cx;
|
||||
public class StaticNewClassGenerator extends BaseGenerator {
|
||||
|
||||
public StaticNewClassGenerator(TestableContext cx) {
|
||||
this.cx = cx;
|
||||
super(cx);
|
||||
}
|
||||
|
||||
public String fetch() {
|
||||
|
@ -18,10 +18,9 @@ import java.lang.reflect.Modifier;
|
||||
*
|
||||
* @author flin
|
||||
*/
|
||||
public class TestSetupMethodGenerator {
|
||||
public class TestSetupMethodGenerator extends BaseGenerator {
|
||||
|
||||
private static final String TYPE_CLASS = "Class";
|
||||
private final TestableContext cx;
|
||||
|
||||
/**
|
||||
* MethodName -> (ResultType -> ParameterTypes)
|
||||
@ -32,7 +31,7 @@ public class TestSetupMethodGenerator {
|
||||
public final ListBuffer<Method> memberMethods = new ListBuffer<>();
|
||||
|
||||
public TestSetupMethodGenerator(TestableContext cx) {
|
||||
this.cx = cx;
|
||||
super(cx);
|
||||
}
|
||||
|
||||
public JCMethodDecl fetch() {
|
||||
@ -63,14 +62,6 @@ public class TestSetupMethodGenerator {
|
||||
return cx.treeMaker.Block(0, statements.toList());
|
||||
}
|
||||
|
||||
private JCExpression nameToExpression(String dotName) {
|
||||
String[] nameParts = dotName.split("\\.");
|
||||
JCExpression e = cx.treeMaker.Ident(cx.names.fromString(nameParts[0]));
|
||||
for (int i = 1; i < nameParts.length; i++) {
|
||||
e = cx.treeMaker.Select(e, cx.names.fromString(nameParts[i]));
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
private boolean isMemberMethod(Pair<Name, Pair<JCExpression, List<JCExpression>>> m) {
|
||||
for (Method method : memberMethods) {
|
||||
|
@ -9,10 +9,13 @@ import com.squareup.javapoet.*;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCModifiers;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -37,7 +40,7 @@ public class TestableClassGenerator {
|
||||
tree.accept(translator);
|
||||
|
||||
List<MethodSpec> methodSpecs = new ArrayList<>();
|
||||
for (JCTree.JCMethodDecl method : translator.getMethods()) {
|
||||
for (JCMethodDecl method : translator.getMethods()) {
|
||||
if (isNoncallableMethod(method)) {
|
||||
continue;
|
||||
}
|
||||
@ -47,10 +50,6 @@ public class TestableClassGenerator {
|
||||
methodSpecs.add(buildMemberMethod(clazz, method));
|
||||
}
|
||||
}
|
||||
for (JCTree.JCVariableDecl field : translator.getFields()) {
|
||||
methodSpecs.add(buildFieldGetter(clazz, field));
|
||||
methodSpecs.add(buildFieldSetter(clazz, field));
|
||||
}
|
||||
|
||||
TypeSpec.Builder builder = TypeSpec.classBuilder(className)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||
@ -63,50 +62,18 @@ public class TestableClassGenerator {
|
||||
return javaFile.toString();
|
||||
}
|
||||
|
||||
private MethodSpec buildFieldGetter(Symbol.ClassSymbol classElement, JCTree.JCVariableDecl field) {
|
||||
String fieldName = field.name.toString();
|
||||
return MethodSpec.methodBuilder(fieldName + ConstPool.TESTABLE_GET_METHOD_PREFIX)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.returns(TypeName.get(field.vartype.type))
|
||||
.beginControlFlow("try")
|
||||
.addStatement("$T field = $T.class.getDeclaredField(\"$N\")", Field.class, classElement.type, fieldName)
|
||||
.addStatement("field.setAccessible(true)")
|
||||
.addStatement("return ($T)field.get(this)", field.vartype.type)
|
||||
.nextControlFlow("catch ($T e)", Exception.class)
|
||||
.addStatement("e.printStackTrace()")
|
||||
.addStatement("return null")
|
||||
.endControlFlow()
|
||||
.build();
|
||||
}
|
||||
|
||||
private MethodSpec buildFieldSetter(Symbol.ClassSymbol classElement, JCTree.JCVariableDecl field) {
|
||||
String fieldName = field.name.toString();
|
||||
return MethodSpec.methodBuilder(fieldName + ConstPool.TESTABLE_SET_METHOD_PREFIX)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addParameter(getParameterSpec(field))
|
||||
.returns(TypeName.VOID)
|
||||
.beginControlFlow("try")
|
||||
.addStatement("$T field = $T.class.getDeclaredField(\"$N\")", Field.class, classElement.type, fieldName)
|
||||
.addStatement("field.setAccessible(true)")
|
||||
.addStatement("field.set(this, $N)", fieldName)
|
||||
.nextControlFlow("catch ($T e)", Exception.class)
|
||||
.addStatement("e.printStackTrace()")
|
||||
.endControlFlow()
|
||||
.build();
|
||||
}
|
||||
|
||||
private MethodSpec buildMemberMethod(Element classElement, JCTree.JCMethodDecl method) {
|
||||
private MethodSpec buildMemberMethod(Element classElement, JCMethodDecl method) {
|
||||
MethodSpec.Builder builder = MethodSpec.methodBuilder(method.name.toString())
|
||||
.addModifiers(toPublicFlags(method.getModifiers()))
|
||||
.returns(TypeName.get(((Type.MethodType)method.sym.type).restype));
|
||||
for (JCTree.JCVariableDecl p : method.getParameters()) {
|
||||
for (JCVariableDecl p : method.getParameters()) {
|
||||
builder.addParameter(getParameterSpec(p));
|
||||
}
|
||||
if (method.getModifiers().getFlags().contains(Modifier.PRIVATE)) {
|
||||
builder.addException(Exception.class);
|
||||
} else {
|
||||
builder.addAnnotation(Override.class);
|
||||
for (JCTree.JCExpression exception : method.getThrows()) {
|
||||
for (JCExpression exception : method.getThrows()) {
|
||||
builder.addException(TypeName.get(exception.type));
|
||||
}
|
||||
}
|
||||
@ -114,16 +81,16 @@ public class TestableClassGenerator {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private MethodSpec buildConstructorMethod(Element classElement, JCTree.JCMethodDecl method) {
|
||||
private MethodSpec buildConstructorMethod(Element classElement, JCMethodDecl method) {
|
||||
MethodSpec.Builder builder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
|
||||
for (JCTree.JCVariableDecl p : method.getParameters()) {
|
||||
for (JCVariableDecl p : method.getParameters()) {
|
||||
builder.addParameter(getParameterSpec(p));
|
||||
}
|
||||
addCallSuperStatements(builder, classElement, method);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void addCallSuperStatements(MethodSpec.Builder builder, Element classElement, JCTree.JCMethodDecl method) {
|
||||
private void addCallSuperStatements(MethodSpec.Builder builder, Element classElement, JCMethodDecl method) {
|
||||
String className = classElement.getSimpleName().toString();
|
||||
Statement[] statements = new CallSuperMethodStatementGenerator().fetch(className, method);
|
||||
for (Statement s : statements) {
|
||||
@ -131,15 +98,15 @@ public class TestableClassGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isConstructorMethod(JCTree.JCMethodDecl method) {
|
||||
private boolean isConstructorMethod(JCMethodDecl method) {
|
||||
return method.name.toString().equals(ConstPool.CONSTRUCTOR_NAME);
|
||||
}
|
||||
|
||||
private boolean isNoncallableMethod(JCTree.JCMethodDecl method) {
|
||||
private boolean isNoncallableMethod(JCMethodDecl method) {
|
||||
return method.getModifiers().getFlags().contains(Modifier.ABSTRACT);
|
||||
}
|
||||
|
||||
private Set<Modifier> toPublicFlags(JCTree.JCModifiers modifiers) {
|
||||
private Set<Modifier> toPublicFlags(JCModifiers modifiers) {
|
||||
Set<Modifier> flags = new HashSet<>(modifiers.getFlags());
|
||||
flags.remove(Modifier.PRIVATE);
|
||||
flags.remove(Modifier.PROTECTED);
|
||||
@ -147,7 +114,7 @@ public class TestableClassGenerator {
|
||||
return flags;
|
||||
}
|
||||
|
||||
private ParameterSpec getParameterSpec(JCTree.JCVariableDecl type) {
|
||||
private ParameterSpec getParameterSpec(JCVariableDecl type) {
|
||||
return ParameterSpec.builder(TypeName.get(type.sym.type), type.name.toString()).build();
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ package com.alibaba.testable.generator.statement;
|
||||
import com.alibaba.testable.generator.model.Statement;
|
||||
import com.alibaba.testable.util.ConstPool;
|
||||
import com.alibaba.testable.util.StringUtil;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import java.util.ArrayList;
|
||||
@ -16,7 +16,7 @@ import java.util.List;
|
||||
*/
|
||||
public class CallSuperMethodStatementGenerator {
|
||||
|
||||
public Statement[] fetch(String className, JCTree.JCMethodDecl method) {
|
||||
public Statement[] fetch(String className, JCMethodDecl method) {
|
||||
if (method.getModifiers().getFlags().contains(Modifier.PRIVATE)) {
|
||||
return reflectCall(className, method);
|
||||
} else {
|
||||
@ -24,11 +24,11 @@ public class CallSuperMethodStatementGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private Statement[] commonCall(JCTree.JCMethodDecl method) {
|
||||
private Statement[] commonCall(JCMethodDecl method) {
|
||||
List<Object> args = new ArrayList<>();
|
||||
StringBuilder code = new StringBuilder();
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
for (JCTree.JCVariableDecl p : method.params) {
|
||||
for (JCVariableDecl p : method.params) {
|
||||
args.add(p.name.toString());
|
||||
placeholders.add("$N");
|
||||
}
|
||||
@ -40,7 +40,7 @@ public class CallSuperMethodStatementGenerator {
|
||||
return new Statement[] { returnStatement(method, new Statement(code.toString(), args.toArray())) };
|
||||
}
|
||||
|
||||
private Statement[] reflectCall(String className, JCTree.JCMethodDecl method) {
|
||||
private Statement[] reflectCall(String className, JCMethodDecl method) {
|
||||
List<Statement> statements = new ArrayList<>();
|
||||
statements.add(getMethodStatement(className, method));
|
||||
statements.add(setAccessibleStatement());
|
||||
@ -48,20 +48,20 @@ public class CallSuperMethodStatementGenerator {
|
||||
return statements.toArray(new Statement[0]);
|
||||
}
|
||||
|
||||
private Statement returnStatement(JCTree.JCMethodDecl method, Statement statement) {
|
||||
private Statement returnStatement(JCMethodDecl method, Statement statement) {
|
||||
if (method.restype != null && !method.restype.toString().equals(ConstPool.TYPE_VOID)) {
|
||||
statement.setLine("return " + statement.getLine());
|
||||
}
|
||||
return statement;
|
||||
}
|
||||
|
||||
private Statement getMethodStatement(String className, JCTree.JCMethodDecl method) {
|
||||
private Statement getMethodStatement(String className, JCMethodDecl method) {
|
||||
List<Object> args = new ArrayList<>();
|
||||
StringBuilder code = new StringBuilder();
|
||||
code.append("$T m = ");
|
||||
args.add(Method.class);
|
||||
code.append(className).append(".class.getDeclaredMethod(\"").append(method.name).append("\"");
|
||||
for (JCTree.JCVariableDecl p : method.params) {
|
||||
for (JCVariableDecl p : method.params) {
|
||||
code.append(", $T.class");
|
||||
args.add(p.sym.type);
|
||||
}
|
||||
@ -73,13 +73,13 @@ public class CallSuperMethodStatementGenerator {
|
||||
return new Statement("m.setAccessible(true)", new Object[0]);
|
||||
}
|
||||
|
||||
private Statement invokeStatement(JCTree.JCMethodDecl method) {
|
||||
private Statement invokeStatement(JCMethodDecl method) {
|
||||
StringBuilder code = new StringBuilder();
|
||||
if (!method.restype.toString().equals(ConstPool.TYPE_VOID)) {
|
||||
code.append("(").append(method.restype).append(")");
|
||||
}
|
||||
code.append("m.invoke(this");
|
||||
for (JCTree.JCVariableDecl p : method.params) {
|
||||
for (JCVariableDecl p : method.params) {
|
||||
code.append(", ").append(p.name);
|
||||
}
|
||||
code.append(")");
|
||||
|
@ -2,8 +2,7 @@ package com.alibaba.testable.translator;
|
||||
|
||||
import com.alibaba.testable.model.TestableContext;
|
||||
import com.alibaba.testable.util.ConstPool;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
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.ListBuffer;
|
||||
@ -26,13 +25,13 @@ public class EnableTestableInjectTranslator extends TreeTranslator {
|
||||
/**
|
||||
* Fields to wrap
|
||||
*/
|
||||
private List<JCTree.JCVariableDecl> fields = List.nil();
|
||||
private List<JCVariableDecl> fields = List.nil();
|
||||
|
||||
public List<JCMethodDecl> getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public List<JCTree.JCVariableDecl> getFields() {
|
||||
public List<JCVariableDecl> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
@ -54,7 +53,7 @@ public class EnableTestableInjectTranslator extends TreeTranslator {
|
||||
* Case: member()
|
||||
*/
|
||||
@Override
|
||||
public void visitExec(JCTree.JCExpressionStatement jcExpressionStatement) {
|
||||
public void visitExec(JCExpressionStatement jcExpressionStatement) {
|
||||
jcExpressionStatement.expr = checkAndExchange(jcExpressionStatement.expr);
|
||||
super.visitExec(jcExpressionStatement);
|
||||
}
|
||||
@ -64,7 +63,7 @@ public class EnableTestableInjectTranslator extends TreeTranslator {
|
||||
* Case: call(new Demo())
|
||||
*/
|
||||
@Override
|
||||
public void visitApply(JCTree.JCMethodInvocation tree) {
|
||||
public void visitApply(JCMethodInvocation tree) {
|
||||
tree.args = checkAndExchange(tree.args);
|
||||
super.visitApply(tree);
|
||||
}
|
||||
@ -74,7 +73,7 @@ public class EnableTestableInjectTranslator extends TreeTranslator {
|
||||
* Case: return member()
|
||||
*/
|
||||
@Override
|
||||
public void visitReturn(JCTree.JCReturn jcReturn) {
|
||||
public void visitReturn(JCReturn jcReturn) {
|
||||
jcReturn.expr = checkAndExchange(jcReturn.expr);
|
||||
super.visitReturn(jcReturn);
|
||||
}
|
||||
@ -85,7 +84,7 @@ public class EnableTestableInjectTranslator extends TreeTranslator {
|
||||
* Case: Demo d = member()
|
||||
*/
|
||||
@Override
|
||||
public void visitVarDef(JCTree.JCVariableDecl jcVariableDecl) {
|
||||
public void visitVarDef(JCVariableDecl jcVariableDecl) {
|
||||
if (isStubbornField(jcVariableDecl.mods)) {
|
||||
fields = fields.append(jcVariableDecl);
|
||||
}
|
||||
@ -98,7 +97,7 @@ public class EnableTestableInjectTranslator extends TreeTranslator {
|
||||
* Case: member().call()
|
||||
*/
|
||||
@Override
|
||||
public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) {
|
||||
public void visitSelect(JCFieldAccess jcFieldAccess) {
|
||||
jcFieldAccess.selected = checkAndExchange(jcFieldAccess.selected);
|
||||
super.visitSelect(jcFieldAccess);
|
||||
}
|
||||
@ -107,7 +106,7 @@ public class EnableTestableInjectTranslator extends TreeTranslator {
|
||||
* For new operation break point
|
||||
*/
|
||||
@Override
|
||||
public void visitNewClass(JCTree.JCNewClass jcNewClass) {
|
||||
public void visitNewClass(JCNewClass jcNewClass) {
|
||||
super.visitNewClass(jcNewClass);
|
||||
}
|
||||
|
||||
@ -115,18 +114,18 @@ public class EnableTestableInjectTranslator extends TreeTranslator {
|
||||
* For new operation break point
|
||||
*/
|
||||
@Override
|
||||
public void visitNewArray(JCTree.JCNewArray jcNewArray) {
|
||||
public void visitNewArray(JCNewArray jcNewArray) {
|
||||
super.visitNewArray(jcNewArray);
|
||||
}
|
||||
|
||||
private boolean isStubbornField(JCTree.JCModifiers mods) {
|
||||
private boolean isStubbornField(JCModifiers mods) {
|
||||
return mods.getFlags().contains(javax.lang.model.element.Modifier.PRIVATE) ||
|
||||
mods.getFlags().contains(javax.lang.model.element.Modifier.FINAL);
|
||||
}
|
||||
|
||||
private List<JCTree.JCExpression> checkAndExchange(List<JCTree.JCExpression> args) {
|
||||
private List<JCExpression> checkAndExchange(List<JCExpression> args) {
|
||||
if (args != null) {
|
||||
JCTree.JCExpression[] es = new JCTree.JCExpression[args.length()];
|
||||
JCExpression[] es = new JCExpression[args.length()];
|
||||
for (int i = 0; i < args.length(); i++) {
|
||||
es[i] = checkAndExchange(args.get(i));
|
||||
}
|
||||
@ -135,51 +134,51 @@ public class EnableTestableInjectTranslator extends TreeTranslator {
|
||||
return null;
|
||||
}
|
||||
|
||||
private JCTree.JCExpression checkAndExchange(JCTree.JCExpression expr) {
|
||||
private JCExpression checkAndExchange(JCExpression expr) {
|
||||
if (isNewOperation(expr)) {
|
||||
JCTree.JCNewClass newClassExpr = (JCTree.JCNewClass)expr;
|
||||
Name className = ((JCTree.JCIdent)newClassExpr.clazz).name;
|
||||
JCNewClass newClassExpr = (JCNewClass)expr;
|
||||
Name className = ((JCIdent)newClassExpr.clazz).name;
|
||||
try {
|
||||
return getGlobalNewInvocation(newClassExpr, className);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (isMemberMethodInvocation(expr)) {
|
||||
Name methodName = ((JCTree.JCIdent)((JCTree.JCMethodInvocation)expr).meth).name;
|
||||
List<JCTree.JCExpression> args = ((JCTree.JCMethodInvocation)expr).args;
|
||||
Name methodName = ((JCIdent)((JCMethodInvocation)expr).meth).name;
|
||||
List<JCExpression> args = ((JCMethodInvocation)expr).args;
|
||||
return getGlobalMemberInvocation(methodName, args);
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
private boolean isMemberMethodInvocation(JCTree.JCExpression expr) {
|
||||
return expr != null && expr.getClass().equals(JCTree.JCMethodInvocation.class) &&
|
||||
((JCTree.JCMethodInvocation)expr).meth.getClass().equals(JCTree.JCIdent.class);
|
||||
private boolean isMemberMethodInvocation(JCExpression expr) {
|
||||
return expr != null && expr.getClass().equals(JCMethodInvocation.class) &&
|
||||
((JCMethodInvocation)expr).meth.getClass().equals(JCIdent.class);
|
||||
}
|
||||
|
||||
private boolean isNewOperation(JCTree.JCExpression expr) {
|
||||
return expr != null && expr.getClass().equals(JCTree.JCNewClass.class);
|
||||
private boolean isNewOperation(JCExpression expr) {
|
||||
return expr != null && expr.getClass().equals(JCNewClass.class);
|
||||
}
|
||||
|
||||
private JCTree.JCMethodInvocation getGlobalNewInvocation(JCTree.JCNewClass newClassExpr, Name className) {
|
||||
JCTree.JCFieldAccess snClass = cx.treeMaker.Select(cx.treeMaker.Ident(cx.names.fromString(ConstPool.NE_PKG)),
|
||||
private JCMethodInvocation getGlobalNewInvocation(JCNewClass newClassExpr, Name className) {
|
||||
JCFieldAccess snClass = cx.treeMaker.Select(cx.treeMaker.Ident(cx.names.fromString(ConstPool.NE_PKG)),
|
||||
cx.names.fromString(ConstPool.NE_CLS));
|
||||
JCTree.JCFieldAccess snMethod = cx.treeMaker.Select(snClass, cx.names.fromString(ConstPool.NE_NEW));
|
||||
JCTree.JCExpression classType = cx.treeMaker.Select(cx.treeMaker.Ident(className),
|
||||
JCFieldAccess snMethod = cx.treeMaker.Select(snClass, cx.names.fromString(ConstPool.NE_NEW));
|
||||
JCExpression classType = cx.treeMaker.Select(cx.treeMaker.Ident(className),
|
||||
cx.names.fromString(ConstPool.TYPE_TO_CLASS));
|
||||
ListBuffer<JCTree.JCExpression> args = ListBuffer.of(classType);
|
||||
ListBuffer<JCExpression> args = ListBuffer.of(classType);
|
||||
args.addAll(newClassExpr.args);
|
||||
return cx.treeMaker.Apply(List.<JCTree.JCExpression>nil(), snMethod, args.toList());
|
||||
return cx.treeMaker.Apply(List.<JCExpression>nil(), snMethod, args.toList());
|
||||
}
|
||||
|
||||
private JCTree.JCMethodInvocation getGlobalMemberInvocation(Name methodName, List<JCTree.JCExpression> param) {
|
||||
JCTree.JCFieldAccess snClass = cx.treeMaker.Select(cx.treeMaker.Ident(cx.names.fromString(ConstPool.NE_PKG)),
|
||||
private JCMethodInvocation getGlobalMemberInvocation(Name methodName, List<JCExpression> param) {
|
||||
JCFieldAccess snClass = cx.treeMaker.Select(cx.treeMaker.Ident(cx.names.fromString(ConstPool.NE_PKG)),
|
||||
cx.names.fromString(ConstPool.NE_CLS));
|
||||
JCTree.JCFieldAccess snMethod = cx.treeMaker.Select(snClass, cx.names.fromString(ConstPool.NE_FUN));
|
||||
ListBuffer<JCTree.JCExpression> args = new ListBuffer();
|
||||
JCFieldAccess snMethod = cx.treeMaker.Select(snClass, cx.names.fromString(ConstPool.NE_FUN));
|
||||
ListBuffer<JCExpression> args = new ListBuffer();
|
||||
args.add(cx.treeMaker.Ident(cx.names.fromString(ConstPool.REF_THIS)));
|
||||
args.add(cx.treeMaker.Literal(methodName.toString()));
|
||||
args.addAll(param);
|
||||
return cx.treeMaker.Apply(List.<JCTree.JCExpression>nil(), snMethod, args.toList());
|
||||
return cx.treeMaker.Apply(List.<JCExpression>nil(), snMethod, args.toList());
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
package com.alibaba.testable.translator;
|
||||
|
||||
import com.alibaba.testable.generator.PrivateAccessStatementGenerator;
|
||||
import com.alibaba.testable.generator.TestSetupMethodGenerator;
|
||||
import com.alibaba.testable.model.TestLibType;
|
||||
import com.alibaba.testable.model.TestableContext;
|
||||
import com.alibaba.testable.util.ConstPool;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.TreeTranslator;
|
||||
import com.sun.tools.javac.util.*;
|
||||
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.ListBuffer;
|
||||
import com.sun.tools.javac.util.Name;
|
||||
import com.sun.tools.javac.util.Pair;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
@ -25,11 +29,13 @@ public class EnableTestableTranslator extends TreeTranslator {
|
||||
private final ListBuffer<Name> sourceClassIns = new ListBuffer<>();
|
||||
private final ListBuffer<String> stubbornFields = new ListBuffer<>();
|
||||
private final TestSetupMethodGenerator testSetupMethodGenerator;
|
||||
private final PrivateAccessStatementGenerator privateAccessStatementGenerator;
|
||||
|
||||
public EnableTestableTranslator(String pkgName, String className, TestableContext cx) {
|
||||
this.sourceClassName = className;
|
||||
this.cx = cx;
|
||||
this.testSetupMethodGenerator = new TestSetupMethodGenerator(cx);
|
||||
this.privateAccessStatementGenerator = new PrivateAccessStatementGenerator(cx);
|
||||
try {
|
||||
Class<?> cls = Class.forName(pkgName + "." + className);
|
||||
Field[] fields = cls.getDeclaredFields();
|
||||
@ -69,17 +75,13 @@ public class EnableTestableTranslator extends TreeTranslator {
|
||||
}
|
||||
|
||||
/**
|
||||
* d.privateField = val -> d.privateFieldTestableSet(val)
|
||||
* d.privateField = val -> PrivateAccessor.set(d, "privateField", val)
|
||||
*/
|
||||
@Override
|
||||
public void visitExec(JCExpressionStatement jcExpressionStatement) {
|
||||
if (jcExpressionStatement.expr.getClass().equals(JCAssign.class) &&
|
||||
isAssignStubbornField((JCAssign)jcExpressionStatement.expr)) {
|
||||
JCAssign assign = (JCAssign)jcExpressionStatement.expr;
|
||||
JCFieldAccess stubbornSetter = cx.treeMaker.Select(((JCFieldAccess)assign.lhs).selected,
|
||||
getStubbornSetterMethodName(assign));
|
||||
jcExpressionStatement.expr = cx.treeMaker.Apply(List.<JCExpression>nil(), stubbornSetter,
|
||||
com.sun.tools.javac.util.List.of(assign.rhs));
|
||||
jcExpressionStatement.expr = privateAccessStatementGenerator.fetchSetterStatement(jcExpressionStatement);
|
||||
}
|
||||
super.visitExec(jcExpressionStatement);
|
||||
}
|
||||
@ -162,11 +164,6 @@ public class EnableTestableTranslator extends TreeTranslator {
|
||||
return nb.toList();
|
||||
}
|
||||
|
||||
private Name getStubbornSetterMethodName(JCAssign assign) {
|
||||
String name = ((JCFieldAccess)assign.lhs).name.toString() + ConstPool.TESTABLE_SET_METHOD_PREFIX;
|
||||
return cx.names.fromString(name);
|
||||
}
|
||||
|
||||
private boolean isAssignStubbornField(JCAssign expr) {
|
||||
return expr.lhs.getClass().equals(JCFieldAccess.class) &&
|
||||
sourceClassIns.contains(((JCIdent)((JCFieldAccess)(expr).lhs).selected).name) &&
|
||||
|
@ -16,10 +16,9 @@ public final class ConstPool {
|
||||
public static final String NE_POOL = "n.e.p";
|
||||
public static final String NE_ADD_W = "n.e.aw";
|
||||
public static final String NE_ADD_F = "n.e.af";
|
||||
public static final String TESTABLE_GET_METHOD_PREFIX = "TestableGet";
|
||||
public static final String TESTABLE_SET_METHOD_PREFIX = "TestableSet";
|
||||
public static final String TYPE_TO_CLASS = "class";
|
||||
public static final String REF_THIS = "this";
|
||||
public static final String TESTABLE_PRIVATE_ACCESSOR = "com.alibaba.testable.accessor.PrivateAccessor";
|
||||
public static final String ANNOTATION_TESTABLE_INJECT = "com.alibaba.testable.annotation.TestableInject";
|
||||
public static final String ANNOTATION_JUNIT5_SETUP = "org.junit.jupiter.api.BeforeEach";
|
||||
public static final String ANNOTATION_JUNIT5_TEST = "org.junit.jupiter.api.Test";
|
||||
|
Loading…
Reference in New Issue
Block a user