mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-10 20:30:11 +08:00
testable class is not needed any more
This commit is contained in:
parent
c905acf44f
commit
df0e6766aa
@ -1,121 +0,0 @@
|
||||
package com.alibaba.testable.generator;
|
||||
|
||||
import com.alibaba.testable.generator.model.Statement;
|
||||
import com.alibaba.testable.generator.statement.CallSuperMethodStatementGenerator;
|
||||
import com.alibaba.testable.model.TestableContext;
|
||||
import com.alibaba.testable.translator.EnableTestableInjectTranslator;
|
||||
import com.alibaba.testable.util.ConstPool;
|
||||
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.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Generate testable class code
|
||||
*
|
||||
* @author flin
|
||||
*/
|
||||
public class TestableClassGenerator {
|
||||
|
||||
private final TestableContext cx;
|
||||
|
||||
public TestableClassGenerator(TestableContext cx) {
|
||||
this.cx = cx;
|
||||
}
|
||||
|
||||
public String fetch(Symbol.ClassSymbol clazz, String packageName, String className) {
|
||||
JCTree tree = cx.trees.getTree(clazz);
|
||||
EnableTestableInjectTranslator translator = new EnableTestableInjectTranslator(cx);
|
||||
tree.accept(translator);
|
||||
|
||||
List<MethodSpec> methodSpecs = new ArrayList<>();
|
||||
for (JCMethodDecl method : translator.getMethods()) {
|
||||
if (isNoncallableMethod(method)) {
|
||||
continue;
|
||||
}
|
||||
if (isConstructorMethod(method)) {
|
||||
methodSpecs.add(buildConstructorMethod(clazz, method));
|
||||
} else {
|
||||
methodSpecs.add(buildMemberMethod(clazz, method));
|
||||
}
|
||||
}
|
||||
|
||||
TypeSpec.Builder builder = TypeSpec.classBuilder(className)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||
.superclass(clazz.asType());
|
||||
for (MethodSpec m : methodSpecs) {
|
||||
builder.addMethod(m);
|
||||
}
|
||||
TypeSpec testableClass = builder.build();
|
||||
JavaFile javaFile = JavaFile.builder(packageName, testableClass).build();
|
||||
return javaFile.toString();
|
||||
}
|
||||
|
||||
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 (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 (JCExpression exception : method.getThrows()) {
|
||||
builder.addException(TypeName.get(exception.type));
|
||||
}
|
||||
}
|
||||
addCallSuperStatements(builder, classElement, method);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private MethodSpec buildConstructorMethod(Element classElement, JCMethodDecl method) {
|
||||
MethodSpec.Builder builder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
|
||||
for (JCVariableDecl p : method.getParameters()) {
|
||||
builder.addParameter(getParameterSpec(p));
|
||||
}
|
||||
addCallSuperStatements(builder, classElement, method);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
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) {
|
||||
builder.addStatement(s.getLine(), s.getParams());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isConstructorMethod(JCMethodDecl method) {
|
||||
return method.name.toString().equals(ConstPool.CONSTRUCTOR_NAME);
|
||||
}
|
||||
|
||||
private boolean isNoncallableMethod(JCMethodDecl method) {
|
||||
return method.getModifiers().getFlags().contains(Modifier.ABSTRACT);
|
||||
}
|
||||
|
||||
private Set<Modifier> toPublicFlags(JCModifiers modifiers) {
|
||||
Set<Modifier> flags = new HashSet<>(modifiers.getFlags());
|
||||
flags.remove(Modifier.PRIVATE);
|
||||
flags.remove(Modifier.PROTECTED);
|
||||
flags.add(Modifier.PUBLIC);
|
||||
return flags;
|
||||
}
|
||||
|
||||
private ParameterSpec getParameterSpec(JCVariableDecl type) {
|
||||
return ParameterSpec.builder(TypeName.get(type.sym.type), type.name.toString()).build();
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package com.alibaba.testable.generator.model;
|
||||
|
||||
public class Statement {
|
||||
|
||||
private String line;
|
||||
private Object[] params;
|
||||
|
||||
public String getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public void setLine(String line) {
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public Object[] getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(Object[] params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public Statement(String line, Object[] params) {
|
||||
this.line = line;
|
||||
this.params = params;
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
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 java.lang.reflect.Method;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Generate call super method statement
|
||||
*
|
||||
* @author flin
|
||||
*/
|
||||
public class CallSuperMethodStatementGenerator {
|
||||
|
||||
public Statement[] fetch(String className, JCMethodDecl method) {
|
||||
if (method.getModifiers().getFlags().contains(Modifier.PRIVATE)) {
|
||||
return reflectCall(className, method);
|
||||
} else {
|
||||
return commonCall(method);
|
||||
}
|
||||
}
|
||||
|
||||
private Statement[] commonCall(JCMethodDecl method) {
|
||||
List<Object> args = new ArrayList<>();
|
||||
StringBuilder code = new StringBuilder();
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
for (JCVariableDecl p : method.params) {
|
||||
args.add(p.name.toString());
|
||||
placeholders.add("$N");
|
||||
}
|
||||
code.append("super");
|
||||
if (!method.name.toString().equals(ConstPool.CONSTRUCTOR_NAME)) {
|
||||
code.append(".").append(method.name);
|
||||
}
|
||||
code.append("(").append(StringUtil.join(placeholders, ", ")).append(")");
|
||||
return new Statement[] { returnStatement(method, new Statement(code.toString(), args.toArray())) };
|
||||
}
|
||||
|
||||
private Statement[] reflectCall(String className, JCMethodDecl method) {
|
||||
List<Statement> statements = new ArrayList<>();
|
||||
statements.add(getMethodStatement(className, method));
|
||||
statements.add(setAccessibleStatement());
|
||||
statements.add(returnStatement(method, invokeStatement(method)));
|
||||
return statements.toArray(new Statement[0]);
|
||||
}
|
||||
|
||||
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, 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 (JCVariableDecl p : method.params) {
|
||||
code.append(", $T.class");
|
||||
args.add(p.sym.type);
|
||||
}
|
||||
code.append(")");
|
||||
return new Statement(code.toString(), args.toArray());
|
||||
}
|
||||
|
||||
private Statement setAccessibleStatement() {
|
||||
return new Statement("m.setAccessible(true)", new Object[0]);
|
||||
}
|
||||
|
||||
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 (JCVariableDecl p : method.params) {
|
||||
code.append(", ").append(p.name);
|
||||
}
|
||||
code.append(")");
|
||||
return new Statement(code.toString(), new Object[0]);
|
||||
}
|
||||
}
|
@ -2,9 +2,10 @@ package com.alibaba.testable.processor;
|
||||
|
||||
import com.alibaba.testable.annotation.EnableTestableInject;
|
||||
import com.alibaba.testable.generator.StaticNewClassGenerator;
|
||||
import com.alibaba.testable.generator.TestableClassGenerator;
|
||||
import com.alibaba.testable.translator.EnableTestableInjectTranslator;
|
||||
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;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
@ -12,7 +13,6 @@ import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedSourceVersion;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.JavaFileObject;
|
||||
@ -71,15 +71,9 @@ public class EnableTestableInjectProcessor extends BaseProcessor {
|
||||
}
|
||||
|
||||
private void processClassElement(Symbol.ClassSymbol clazz) {
|
||||
String packageName = cx.elementUtils.getPackageOf(clazz).getQualifiedName().toString();
|
||||
String testableTypeName = getTestableClassName(clazz.getSimpleName());
|
||||
String fullQualityTypeName = packageName + "." + testableTypeName;
|
||||
try {
|
||||
writeSourceFile(fullQualityTypeName,
|
||||
new TestableClassGenerator(cx).fetch(clazz, packageName, testableTypeName));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
JCTree tree = cx.trees.getTree(clazz);
|
||||
EnableTestableInjectTranslator translator = new EnableTestableInjectTranslator(cx);
|
||||
tree.accept(translator);
|
||||
}
|
||||
|
||||
private void writeSourceFile(String fullQualityTypeName, String content) throws IOException {
|
||||
@ -89,8 +83,4 @@ public class EnableTestableInjectProcessor extends BaseProcessor {
|
||||
writer.close();
|
||||
}
|
||||
|
||||
private String getTestableClassName(Name className) {
|
||||
return className.toString().replace(".", "_") + ConstPool.TESTABLE;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user