mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-26 20:30:29 +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.generator.statement.FieldStatementGenerator;
|
||||||
import com.alibaba.testable.translator.TestableClassDevRoleTranslator;
|
import com.alibaba.testable.translator.TestableClassDevRoleTranslator;
|
||||||
import com.alibaba.testable.util.ConstPool;
|
import com.alibaba.testable.util.ConstPool;
|
||||||
|
import com.alibaba.testable.util.StringUtil;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
import com.sun.tools.javac.api.JavacTrees;
|
import com.sun.tools.javac.api.JavacTrees;
|
||||||
import com.sun.tools.javac.code.Type;
|
import com.sun.tools.javac.code.Type;
|
||||||
@ -51,10 +52,11 @@ public class TestableClassDevRoleGenerator {
|
|||||||
methodSpecs.add(buildMemberMethod(clazz, method));
|
methodSpecs.add(buildMemberMethod(clazz, method));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (JCTree.JCVariableDecl field : translator.getPrivateFields()) {
|
for (JCTree.JCVariableDecl field : translator.getFields()) {
|
||||||
methodSpecs.add(buildFieldGetter(clazz, field));
|
methodSpecs.add(buildFieldGetter(clazz, field));
|
||||||
methodSpecs.add(buildFieldSetter(clazz, field));
|
methodSpecs.add(buildFieldSetter(clazz, field));
|
||||||
}
|
}
|
||||||
|
methodSpecs.add(buildStubbornFieldMethod(translator.getFields()));
|
||||||
|
|
||||||
TypeSpec.Builder builder = TypeSpec.classBuilder(className)
|
TypeSpec.Builder builder = TypeSpec.classBuilder(className)
|
||||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||||
@ -67,9 +69,21 @@ public class TestableClassDevRoleGenerator {
|
|||||||
return javaFile.toString();
|
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) {
|
private MethodSpec buildFieldGetter(Element classElement, JCTree.JCVariableDecl field) {
|
||||||
return buildFieldAccessor(classElement, field, "TestableGet",
|
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) {
|
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.generator.TestableClassDevRoleGenerator;
|
||||||
import com.alibaba.testable.translator.TestableClassTestRoleTranslator;
|
import com.alibaba.testable.translator.TestableClassTestRoleTranslator;
|
||||||
import com.alibaba.testable.util.ConstPool;
|
import com.alibaba.testable.util.ConstPool;
|
||||||
|
import com.sun.tools.javac.code.Symbol;
|
||||||
import com.sun.tools.javac.tree.JCTree;
|
import com.sun.tools.javac.tree.JCTree;
|
||||||
|
|
||||||
import javax.annotation.processing.FilerException;
|
import javax.annotation.processing.FilerException;
|
||||||
@ -40,9 +41,9 @@ public class TestableProcessor extends BaseProcessor {
|
|||||||
for (Element element : elements) {
|
for (Element element : elements) {
|
||||||
if (element.getKind().isClass()) {
|
if (element.getKind().isClass()) {
|
||||||
if (isTestClass(element.getSimpleName())) {
|
if (isTestClass(element.getSimpleName())) {
|
||||||
processTestRoleClassElement(element);
|
processTestRoleClassElement((Symbol.ClassSymbol)element);
|
||||||
} else {
|
} else {
|
||||||
processDevRoleClassElement(element);
|
processDevRoleClassElement((Symbol.ClassSymbol)element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,7 +80,7 @@ public class TestableProcessor extends BaseProcessor {
|
|||||||
return staticNewClassFile.getName().contains(GENERATED_TEST_SOURCES);
|
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 packageName = elementUtils.getPackageOf(clazz).getQualifiedName().toString();
|
||||||
String testableTypeName = getTestableClassName(clazz.getSimpleName());
|
String testableTypeName = getTestableClassName(clazz.getSimpleName());
|
||||||
String fullQualityTypeName = packageName + "." + testableTypeName;
|
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);
|
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();
|
String testClassName = clazz.getSimpleName().toString();
|
||||||
return testClassName.substring(0, testClassName.length() - "Test".length());
|
return testClassName.substring(0, testClassName.length() - "Test".length());
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
|||||||
private List<JCMethodDecl> methods = List.nil();
|
private List<JCMethodDecl> methods = List.nil();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private field to mock
|
* Fields to wrap
|
||||||
*/
|
*/
|
||||||
private List<JCTree.JCVariableDecl> fields = List.nil();
|
private List<JCTree.JCVariableDecl> fields = List.nil();
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
|||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<JCTree.JCVariableDecl> getPrivateFields() {
|
public List<JCTree.JCVariableDecl> getFields() {
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* record all methods
|
* Record all methods
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitMethodDef(JCMethodDecl jcMethodDecl) {
|
public void visitMethodDef(JCMethodDecl jcMethodDecl) {
|
||||||
@ -60,7 +60,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* case: new Demo()
|
* Case: new Demo()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitExec(JCTree.JCExpressionStatement jcExpressionStatement) {
|
public void visitExec(JCTree.JCExpressionStatement jcExpressionStatement) {
|
||||||
@ -69,7 +69,7 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* case: call(new Demo())
|
* Case: call(new Demo())
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitApply(JCTree.JCMethodInvocation tree) {
|
public void visitApply(JCTree.JCMethodInvocation tree) {
|
||||||
@ -78,20 +78,20 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* record all private fields
|
* Record all private fields
|
||||||
* case: Demo d = new Demo()
|
* Case: Demo d = new Demo()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitVarDef(JCTree.JCVariableDecl jcVariableDecl) {
|
public void visitVarDef(JCTree.JCVariableDecl jcVariableDecl) {
|
||||||
if (jcVariableDecl.mods.getFlags().contains(javax.lang.model.element.Modifier.PRIVATE)) {
|
if (isStubbornField(jcVariableDecl.mods)) {
|
||||||
fields.append(jcVariableDecl);
|
fields = fields.append(jcVariableDecl);
|
||||||
}
|
}
|
||||||
jcVariableDecl.init = checkAndExchangeNewOperation(jcVariableDecl.init);
|
jcVariableDecl.init = checkAndExchangeNewOperation(jcVariableDecl.init);
|
||||||
super.visitVarDef(jcVariableDecl);
|
super.visitVarDef(jcVariableDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* case: new Demo().call()
|
* Case: new Demo().call()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) {
|
public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) {
|
||||||
@ -99,16 +99,27 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
|
|||||||
super.visitSelect(jcFieldAccess);
|
super.visitSelect(jcFieldAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For break point
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitNewClass(JCTree.JCNewClass jcNewClass) {
|
public void visitNewClass(JCTree.JCNewClass jcNewClass) {
|
||||||
super.visitNewClass(jcNewClass);
|
super.visitNewClass(jcNewClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For break point
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitNewArray(JCTree.JCNewArray jcNewArray) {
|
public void visitNewArray(JCTree.JCNewArray jcNewArray) {
|
||||||
super.visitNewArray(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) {
|
private List<JCTree.JCExpression> checkAndExchangeNewOperation(List<JCTree.JCExpression> args) {
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
JCTree.JCExpression[] es = new JCTree.JCExpression[args.length()];
|
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 com.sun.tools.javac.util.Name;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,10 +20,19 @@ public class TestableClassTestRoleTranslator extends TreeTranslator {
|
|||||||
private TreeMaker treeMaker;
|
private TreeMaker treeMaker;
|
||||||
private String sourceClassName;
|
private String sourceClassName;
|
||||||
private List<Name> sourceClassIns = new ArrayList<>();
|
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.sourceClassName = className;
|
||||||
this.treeMaker = treeMaker;
|
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
|
@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) {
|
private JCTree.JCIdent getTestableClassIdent(JCTree.JCExpression clazz) {
|
||||||
Name className = ((JCTree.JCIdent)clazz).name;
|
Name className = ((JCTree.JCIdent)clazz).name;
|
||||||
return treeMaker.Ident(className.table.fromString(className + ConstPool.TESTABLE));
|
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_CLS = "e";
|
||||||
public static final String SN_METHOD = "w";
|
public static final String SN_METHOD = "w";
|
||||||
public static final String SN_PKG_CLS = "n.e";
|
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