add private field access generators

This commit is contained in:
金戟 2020-05-16 21:13:41 +08:00
parent 12ddb9398c
commit cbb3a62fff
9 changed files with 141 additions and 12 deletions

View File

@ -1,6 +1,10 @@
package com.alibaba.testable.generator;
import com.alibaba.testable.generator.model.Statement;
import com.alibaba.testable.generator.statement.CallSuperMethodStatementGenerator;
import com.alibaba.testable.generator.statement.FieldGetterStatementGenerator;
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.squareup.javapoet.*;
@ -47,6 +51,10 @@ public class TestableClassDevRoleGenerator {
methodSpecs.add(buildMemberMethod(clazz, method));
}
}
for (JCTree.JCVariableDecl field : translator.getPrivateFields()) {
methodSpecs.add(buildFieldGetter(clazz, field));
methodSpecs.add(buildFieldSetter(clazz, field));
}
TypeSpec.Builder builder = TypeSpec.classBuilder(className)
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
@ -59,6 +67,29 @@ public class TestableClassDevRoleGenerator {
return javaFile.toString();
}
private MethodSpec buildFieldGetter(Element classElement, JCTree.JCVariableDecl field) {
return buildFieldAccessor(classElement, field, "TestableGet",
TypeName.get(((Type.MethodType)field.type).restype), new FieldGetterStatementGenerator());
}
private MethodSpec buildFieldSetter(Element classElement, JCTree.JCVariableDecl field) {
return buildFieldAccessor(classElement, field, "TestableSet",
TypeName.VOID, new FieldSetterStatementGenerator());
}
private MethodSpec buildFieldAccessor(Element classElement, JCTree.JCVariableDecl field, String prefix,
TypeName returnType, FieldStatementGenerator generator) {
MethodSpec.Builder builder = MethodSpec.methodBuilder(field.name.toString() + prefix)
.addModifiers(Modifier.PUBLIC)
.returns(returnType);
String className = classElement.getSimpleName().toString();
Statement[] statements = generator.fetch(className, field);
for (Statement s : statements) {
builder.addStatement(s.getLine(), s.getParams());
}
return builder.build();
}
private MethodSpec buildMemberMethod(Element classElement, JCTree.JCMethodDecl method) {
MethodSpec.Builder builder = MethodSpec.methodBuilder(method.name.toString())
.addModifiers(toPublicFlags(method.getModifiers()))
@ -79,8 +110,7 @@ public class TestableClassDevRoleGenerator {
}
private MethodSpec buildConstructorMethod(Element classElement, JCTree.JCMethodDecl method) {
MethodSpec.Builder builder = MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder builder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
for (JCTree.JCVariableDecl p : method.getParameters()) {
builder.addParameter(getParameterSpec(p));
}

View File

@ -1,4 +1,4 @@
package com.alibaba.testable.generator;
package com.alibaba.testable.generator.statement;
import com.alibaba.testable.generator.model.Statement;
import com.alibaba.testable.util.ConstPool;

View File

@ -0,0 +1,25 @@
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 javax.lang.model.element.Modifier;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* Generate field getter method statement
*
* @author flin
*/
public class FieldGetterStatementGenerator implements FieldStatementGenerator {
@Override
public Statement[] fetch(String className, JCTree.JCVariableDecl field) {
return new Statement[] {new Statement("return null", new Object[] {})};
}
}

View File

@ -0,0 +1,25 @@
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 javax.lang.model.element.Modifier;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* Generate field setter method statement
*
* @author flin
*/
public class FieldSetterStatementGenerator implements FieldStatementGenerator {
@Override
public Statement[] fetch(String className, JCTree.JCVariableDecl field) {
return new Statement[]{};
}
}

View File

@ -0,0 +1,14 @@
package com.alibaba.testable.generator.statement;
import com.alibaba.testable.generator.model.Statement;
import com.sun.tools.javac.tree.JCTree;
/**
* @author flin
*/
public interface FieldStatementGenerator {
/**
* Generate field access code statement
*/
Statement[] fetch(String className, JCTree.JCVariableDecl field);
}

View File

@ -91,9 +91,14 @@ public class TestableProcessor extends BaseProcessor {
}
}
private void processTestRoleClassElement(Element field) {
JCTree tree = trees.getTree(field);
tree.accept(new TestableClassTestRoleTranslator(treeMaker));
private void processTestRoleClassElement(Element clazz) {
JCTree tree = trees.getTree(clazz);
tree.accept(new TestableClassTestRoleTranslator(getOriginClassName(clazz), treeMaker));
}
private String getOriginClassName(Element clazz) {
String testClassName = clazz.getSimpleName().toString();
return testClassName.substring(0, testClassName.length() - "Test".length());
}
private void writeSourceFile(String fullQualityTypeName, String content) throws IOException {

View File

@ -27,10 +27,19 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
*/
private List<JCMethodDecl> methods = List.nil();
/**
* Private field to mock
*/
private List<JCTree.JCVariableDecl> fields = List.nil();
public List<JCMethodDecl> getMethods() {
return methods;
}
public List<JCTree.JCVariableDecl> getPrivateFields() {
return fields;
}
public TestableClassDevRoleTranslator(TreeMaker treeMaker) {
this.treeMaker = treeMaker;
}
@ -69,10 +78,14 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
}
/**
* 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);
}
jcVariableDecl.init = checkAndExchangeNewOperation(jcVariableDecl.init);
super.visitVarDef(jcVariableDecl);
}
@ -91,6 +104,11 @@ public class TestableClassDevRoleTranslator extends TreeTranslator {
super.visitNewClass(jcNewClass);
}
@Override
public void visitNewArray(JCTree.JCNewArray jcNewArray) {
super.visitNewArray(jcNewArray);
}
private List<JCTree.JCExpression> checkAndExchangeNewOperation(List<JCTree.JCExpression> args) {
if (args != null) {
JCTree.JCExpression[] es = new JCTree.JCExpression[args.length()];

View File

@ -6,6 +6,9 @@ import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.Name;
import java.util.ArrayList;
import java.util.List;
/**
* Travel AST
*
@ -14,19 +17,29 @@ import com.sun.tools.javac.util.Name;
public class TestableClassTestRoleTranslator extends TreeTranslator {
private TreeMaker treeMaker;
private String sourceClassName;
private List<Name> sourceClassIns = new ArrayList<>();
public TestableClassTestRoleTranslator(TreeMaker treeMaker) {this.treeMaker = treeMaker;}
public TestableClassTestRoleTranslator(String className, TreeMaker treeMaker) {
this.sourceClassName = className;
this.treeMaker = treeMaker;
}
@Override
public void visitVarDef(JCTree.JCVariableDecl decl) {
super.visitVarDef(decl);
decl.vartype = getTestableClassIdent(decl.vartype);
public void visitVarDef(JCTree.JCVariableDecl jcVariableDecl) {
super.visitVarDef(jcVariableDecl);
if (((JCTree.JCIdent)jcVariableDecl.vartype).name.toString().equals(sourceClassName)) {
jcVariableDecl.vartype = getTestableClassIdent(jcVariableDecl.vartype);
sourceClassIns.add(jcVariableDecl.name);
}
}
@Override
public void visitNewClass(JCTree.JCNewClass jcNewClass) {
super.visitNewClass(jcNewClass);
jcNewClass.clazz = getTestableClassIdent(jcNewClass.clazz);
if (((JCTree.JCIdent)jcNewClass.clazz).name.toString().equals(sourceClassName)) {
jcNewClass.clazz = getTestableClassIdent(jcNewClass.clazz);
}
}
private JCTree.JCIdent getTestableClassIdent(JCTree.JCExpression clazz) {

View File

@ -1,2 +1 @@
com.alibaba.testable.processor.TestableProcessor
com.alibaba.testable.processor.TestableInjectProcessor