mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-25 11:51:15 +08:00
handling setter exchange
This commit is contained in:
parent
cbb3a62fff
commit
bc49fda272
@ -7,6 +7,7 @@ import com.alibaba.testable.generator.statement.FieldSetterStatementGenerator;
|
||||
import com.alibaba.testable.generator.statement.FieldStatementGenerator;
|
||||
import com.alibaba.testable.translator.TestableClassDevRoleTranslator;
|
||||
import com.alibaba.testable.util.ConstPool;
|
||||
import com.alibaba.testable.util.StringUtil;
|
||||
import com.squareup.javapoet.*;
|
||||
import com.sun.tools.javac.api.JavacTrees;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
@ -51,10 +52,11 @@ public class TestableClassDevRoleGenerator {
|
||||
methodSpecs.add(buildMemberMethod(clazz, method));
|
||||
}
|
||||
}
|
||||
for (JCTree.JCVariableDecl field : translator.getPrivateFields()) {
|
||||
for (JCTree.JCVariableDecl field : translator.getFields()) {
|
||||
methodSpecs.add(buildFieldGetter(clazz, field));
|
||||
methodSpecs.add(buildFieldSetter(clazz, field));
|
||||
}
|
||||
methodSpecs.add(buildStubbornFieldMethod(translator.getFields()));
|
||||
|
||||
TypeSpec.Builder builder = TypeSpec.classBuilder(className)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||
@ -67,9 +69,21 @@ public class TestableClassDevRoleGenerator {
|
||||
return javaFile.toString();
|
||||
}
|
||||
|
||||
private MethodSpec buildStubbornFieldMethod(List<JCTree.JCVariableDecl> fields) {
|
||||
List<String> fieldNames = new ArrayList<>();
|
||||
for (JCTree.JCVariableDecl f : fields) {
|
||||
fieldNames.add("\"" + f.name.toString() + "\"");
|
||||
}
|
||||
return MethodSpec.methodBuilder(ConstPool.STUBBORN_FIELD_METHOD)
|
||||
.addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC)
|
||||
.addStatement("return new $T[]{" + StringUtil.join(fieldNames, ",") + "}", String.class)
|
||||
.returns(ArrayTypeName.of(String.class))
|
||||
.build();
|
||||
}
|
||||
|
||||
private MethodSpec buildFieldGetter(Element classElement, JCTree.JCVariableDecl field) {
|
||||
return buildFieldAccessor(classElement, field, "TestableGet",
|
||||
TypeName.get(((Type.MethodType)field.type).restype), new FieldGetterStatementGenerator());
|
||||
TypeName.get(field.vartype.type), new FieldGetterStatementGenerator());
|
||||
}
|
||||
|
||||
private MethodSpec buildFieldSetter(Element classElement, JCTree.JCVariableDecl field) {
|
||||
|
@ -5,6 +5,7 @@ import com.alibaba.testable.generator.StaticNewClassGenerator;
|
||||
import com.alibaba.testable.generator.TestableClassDevRoleGenerator;
|
||||
import com.alibaba.testable.translator.TestableClassTestRoleTranslator;
|
||||
import com.alibaba.testable.util.ConstPool;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
|
||||
import javax.annotation.processing.FilerException;
|
||||
@ -40,9 +41,9 @@ public class TestableProcessor extends BaseProcessor {
|
||||
for (Element element : elements) {
|
||||
if (element.getKind().isClass()) {
|
||||
if (isTestClass(element.getSimpleName())) {
|
||||
processTestRoleClassElement(element);
|
||||
processTestRoleClassElement((Symbol.ClassSymbol)element);
|
||||
} else {
|
||||
processDevRoleClassElement(element);
|
||||
processDevRoleClassElement((Symbol.ClassSymbol)element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,7 +80,7 @@ public class TestableProcessor extends BaseProcessor {
|
||||
return staticNewClassFile.getName().contains(GENERATED_TEST_SOURCES);
|
||||
}
|
||||
|
||||
private void processDevRoleClassElement(Element clazz) {
|
||||
private void processDevRoleClassElement(Symbol.ClassSymbol clazz) {
|
||||
String packageName = elementUtils.getPackageOf(clazz).getQualifiedName().toString();
|
||||
String testableTypeName = getTestableClassName(clazz.getSimpleName());
|
||||
String fullQualityTypeName = packageName + "." + testableTypeName;
|
||||
@ -91,12 +92,16 @@ public class TestableProcessor extends BaseProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private void processTestRoleClassElement(Element clazz) {
|
||||
private void processTestRoleClassElement(Symbol.ClassSymbol clazz) {
|
||||
JCTree tree = trees.getTree(clazz);
|
||||
tree.accept(new TestableClassTestRoleTranslator(getOriginClassName(clazz), treeMaker));
|
||||
tree.accept(new TestableClassTestRoleTranslator(getPkgName(clazz), getOriginClassName(clazz), treeMaker));
|
||||
}
|
||||
|
||||
private String getOriginClassName(Element clazz) {
|
||||
private String getPkgName(Symbol.ClassSymbol clazz) {
|
||||
return ((Symbol.PackageSymbol)clazz.owner).fullname.toString();
|
||||
}
|
||||
|
||||
private String getOriginClassName(Symbol.ClassSymbol clazz) {
|
||||
String testClassName = clazz.getSimpleName().toString();
|
||||
return testClassName.substring(0, testClassName.length() - "Test".length());
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
||||
private List<JCMethodDecl> methods = List.nil();
|
||||
|
||||
/**
|
||||
* Private field to mock
|
||||
* Fields to wrap
|
||||
*/
|
||||
private List<JCTree.JCVariableDecl> fields = List.nil();
|
||||
|
||||
@ -36,7 +36,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public List<JCTree.JCVariableDecl> getPrivateFields() {
|
||||
public List<JCTree.JCVariableDecl> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
||||
}
|
||||
|
||||
/**
|
||||
* record all methods
|
||||
* Record all methods
|
||||
*/
|
||||
@Override
|
||||
public void visitMethodDef(JCMethodDecl jcMethodDecl) {
|
||||
@ -60,7 +60,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
||||
}
|
||||
|
||||
/**
|
||||
* case: new Demo()
|
||||
* Case: new Demo()
|
||||
*/
|
||||
@Override
|
||||
public void visitExec(JCTree.JCExpressionStatement jcExpressionStatement) {
|
||||
@ -69,7 +69,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
||||
}
|
||||
|
||||
/**
|
||||
* case: call(new Demo())
|
||||
* Case: call(new Demo())
|
||||
*/
|
||||
@Override
|
||||
public void visitApply(JCTree.JCMethodInvocation tree) {
|
||||
@ -78,20 +78,20 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
||||
}
|
||||
|
||||
/**
|
||||
* record all private fields
|
||||
* case: Demo d = new Demo()
|
||||
* Record all private fields
|
||||
* Case: Demo d = new Demo()
|
||||
*/
|
||||
@Override
|
||||
public void visitVarDef(JCTree.JCVariableDecl jcVariableDecl) {
|
||||
if (jcVariableDecl.mods.getFlags().contains(javax.lang.model.element.Modifier.PRIVATE)) {
|
||||
fields.append(jcVariableDecl);
|
||||
if (isStubbornField(jcVariableDecl.mods)) {
|
||||
fields = fields.append(jcVariableDecl);
|
||||
}
|
||||
jcVariableDecl.init = checkAndExchangeNewOperation(jcVariableDecl.init);
|
||||
super.visitVarDef(jcVariableDecl);
|
||||
}
|
||||
|
||||
/**
|
||||
* case: new Demo().call()
|
||||
* Case: new Demo().call()
|
||||
*/
|
||||
@Override
|
||||
public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) {
|
||||
@ -99,16 +99,27 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
||||
super.visitSelect(jcFieldAccess);
|
||||
}
|
||||
|
||||
/**
|
||||
* For break point
|
||||
*/
|
||||
@Override
|
||||
public void visitNewClass(JCTree.JCNewClass jcNewClass) {
|
||||
super.visitNewClass(jcNewClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* For break point
|
||||
*/
|
||||
@Override
|
||||
public void visitNewArray(JCTree.JCNewArray jcNewArray) {
|
||||
super.visitNewArray(jcNewArray);
|
||||
}
|
||||
|
||||
private boolean isStubbornField(JCTree.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> checkAndExchangeNewOperation(List<JCTree.JCExpression> args) {
|
||||
if (args != null) {
|
||||
JCTree.JCExpression[] es = new JCTree.JCExpression[args.length()];
|
||||
|
@ -7,6 +7,7 @@ import com.sun.tools.javac.tree.TreeTranslator;
|
||||
import com.sun.tools.javac.util.Name;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -19,10 +20,19 @@ public class TestableClassTestRoleTranslator extends TreeTranslator {
|
||||
private TreeMaker treeMaker;
|
||||
private String sourceClassName;
|
||||
private List<Name> sourceClassIns = new ArrayList<>();
|
||||
private List<String> stubbornFields = new ArrayList<>();
|
||||
|
||||
public TestableClassTestRoleTranslator(String className, TreeMaker treeMaker) {
|
||||
public TestableClassTestRoleTranslator(String pkgName, String className, TreeMaker treeMaker) {
|
||||
this.sourceClassName = className;
|
||||
this.treeMaker = treeMaker;
|
||||
try {
|
||||
stubbornFields = Arrays.asList(
|
||||
(String[])Class.forName(pkgName + "." + className + ConstPool.TESTABLE)
|
||||
.getMethod(ConstPool.STUBBORN_FIELD_METHOD)
|
||||
.invoke(null));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -42,6 +52,37 @@ public class TestableClassTestRoleTranslator extends TreeTranslator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For break point
|
||||
*/
|
||||
@Override
|
||||
public void visitAssign(JCTree.JCAssign jcAssign) {
|
||||
super.visitAssign(jcAssign);
|
||||
}
|
||||
|
||||
/**
|
||||
* For break point
|
||||
*/
|
||||
@Override
|
||||
public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) {
|
||||
super.visitSelect(jcFieldAccess);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExec(JCTree.JCExpressionStatement jcExpressionStatement) {
|
||||
if (jcExpressionStatement.expr.getClass().equals(JCTree.JCAssign.class) &&
|
||||
isAssignStubbornField((JCTree.JCAssign)jcExpressionStatement.expr)) {
|
||||
//jcExpressionStatement.expr =
|
||||
}
|
||||
super.visitExec(jcExpressionStatement);
|
||||
}
|
||||
|
||||
private boolean isAssignStubbornField(JCTree.JCAssign expr) {
|
||||
return expr.lhs.getClass().equals(JCTree.JCFieldAccess.class) &&
|
||||
sourceClassIns.contains(((JCTree.JCIdent)((JCTree.JCFieldAccess)(expr).lhs).selected).name) &&
|
||||
stubbornFields.contains(((JCTree.JCFieldAccess)(expr).lhs).name.toString());
|
||||
}
|
||||
|
||||
private JCTree.JCIdent getTestableClassIdent(JCTree.JCExpression clazz) {
|
||||
Name className = ((JCTree.JCIdent)clazz).name;
|
||||
return treeMaker.Ident(className.table.fromString(className + ConstPool.TESTABLE));
|
||||
|
@ -12,4 +12,6 @@ public final class ConstPool {
|
||||
public static final String SN_CLS = "e";
|
||||
public static final String SN_METHOD = "w";
|
||||
public static final String SN_PKG_CLS = "n.e";
|
||||
public static final String STUBBORN_FIELD_METHOD = "stubbornField";
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user