mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-10 20:30:11 +08:00
move static new method to global class
This commit is contained in:
parent
066107372b
commit
3e90422cb6
@ -0,0 +1,48 @@
|
|||||||
|
package com.alibaba.testable.generator;
|
||||||
|
|
||||||
|
import com.alibaba.testable.util.ConstPool;
|
||||||
|
import com.squareup.javapoet.*;
|
||||||
|
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate global n.e class code
|
||||||
|
*
|
||||||
|
* @author flin
|
||||||
|
*/
|
||||||
|
public class StaticNewClassGenerator {
|
||||||
|
|
||||||
|
public String fetch() {
|
||||||
|
return JavaFile.builder(ConstPool.SN_PKG,
|
||||||
|
TypeSpec.classBuilder(ConstPool.SN_CLS)
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||||
|
.addMethod(buildStaticNewMethod())
|
||||||
|
.build())
|
||||||
|
.build().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MethodSpec buildStaticNewMethod() {
|
||||||
|
TypeVariableName typeVariable = TypeVariableName.get("T");
|
||||||
|
MethodSpec.Builder builder = MethodSpec.methodBuilder(ConstPool.SN_METHOD)
|
||||||
|
.addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC)
|
||||||
|
.addException(Exception.class)
|
||||||
|
.addTypeVariable(typeVariable)
|
||||||
|
.varargs(true)
|
||||||
|
.addParameter(ParameterizedTypeName.get(ClassName.get(Class.class), typeVariable), "type")
|
||||||
|
.addParameter(ArrayTypeName.of(Object.class), "args")
|
||||||
|
.returns(typeVariable);
|
||||||
|
addStaticNewMethodStatement(builder);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addStaticNewMethodStatement(MethodSpec.Builder builder) {
|
||||||
|
builder.addStatement("$T<$T> pts = new $T<>()", List.class, Class.class, ArrayList.class)
|
||||||
|
.beginControlFlow("for (Object o : args)")
|
||||||
|
.addStatement("pts.add(o.getClass())")
|
||||||
|
.endControlFlow()
|
||||||
|
.addStatement("return type.getConstructor(pts.toArray(new Class[0])).newInstance(args)");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -7,6 +7,7 @@ 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;
|
||||||
import com.sun.tools.javac.tree.JCTree;
|
import com.sun.tools.javac.tree.JCTree;
|
||||||
|
import com.sun.tools.javac.tree.TreeMaker;
|
||||||
|
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
@ -23,18 +24,19 @@ import java.util.Set;
|
|||||||
public class TestableClassGenerator {
|
public class TestableClassGenerator {
|
||||||
|
|
||||||
private final JavacTrees trees;
|
private final JavacTrees trees;
|
||||||
|
private final TreeMaker treeMaker;
|
||||||
|
|
||||||
public TestableClassGenerator(JavacTrees trees) {
|
public TestableClassGenerator(JavacTrees trees, TreeMaker treeMaker) {
|
||||||
this.trees = trees;
|
this.trees = trees;
|
||||||
|
this.treeMaker = treeMaker;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String fetch(Element clazz, String packageName, String className) {
|
public String fetch(Element clazz, String packageName, String className) {
|
||||||
JCTree tree = trees.getTree(clazz);
|
JCTree tree = trees.getTree(clazz);
|
||||||
TestableClassTranslator translator = new TestableClassTranslator();
|
TestableClassTranslator translator = new TestableClassTranslator(treeMaker);
|
||||||
tree.accept(translator);
|
tree.accept(translator);
|
||||||
|
|
||||||
List<MethodSpec> methodSpecs = new ArrayList<>();
|
List<MethodSpec> methodSpecs = new ArrayList<>();
|
||||||
methodSpecs.add(buildStaticNewMethod(clazz));
|
|
||||||
for (JCTree.JCMethodDecl method : translator.getMethods()) {
|
for (JCTree.JCMethodDecl method : translator.getMethods()) {
|
||||||
if (isNoncallableMethod(method)) {
|
if (isNoncallableMethod(method)) {
|
||||||
continue;
|
continue;
|
||||||
@ -57,28 +59,6 @@ public class TestableClassGenerator {
|
|||||||
return javaFile.toString();
|
return javaFile.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodSpec buildStaticNewMethod(Element clazz) {
|
|
||||||
TypeVariableName typeVariable = TypeVariableName.get("T");
|
|
||||||
MethodSpec.Builder builder = MethodSpec.methodBuilder("New")
|
|
||||||
.addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC)
|
|
||||||
.addException(Exception.class)
|
|
||||||
.addTypeVariable(typeVariable)
|
|
||||||
.varargs(true)
|
|
||||||
.addParameter(ParameterizedTypeName.get(ClassName.get(Class.class), typeVariable), "type")
|
|
||||||
.addParameter(ArrayTypeName.of(Object.class), "args")
|
|
||||||
.returns(typeVariable);
|
|
||||||
addStaticNewMethodStatement(builder);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addStaticNewMethodStatement(MethodSpec.Builder builder) {
|
|
||||||
builder.addStatement("$T<$T> pts = new $T<>()", List.class, Class.class, ArrayList.class)
|
|
||||||
.beginControlFlow("for (Object o : args)")
|
|
||||||
.addStatement("pts.add(o.getClass())")
|
|
||||||
.endControlFlow()
|
|
||||||
.addStatement("return type.getConstructor(pts.toArray(new Class[0])).newInstance(args)");
|
|
||||||
}
|
|
||||||
|
|
||||||
private MethodSpec buildMemberMethod(Element classElement, JCTree.JCMethodDecl method) {
|
private MethodSpec buildMemberMethod(Element classElement, JCTree.JCMethodDecl method) {
|
||||||
MethodSpec.Builder builder = MethodSpec.methodBuilder(method.name.toString())
|
MethodSpec.Builder builder = MethodSpec.methodBuilder(method.name.toString())
|
||||||
.addModifiers(toPublicFlags(method.getModifiers()))
|
.addModifiers(toPublicFlags(method.getModifiers()))
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.alibaba.testable.processor;
|
package com.alibaba.testable.processor;
|
||||||
|
|
||||||
import com.alibaba.testable.annotation.Testable;
|
import com.alibaba.testable.annotation.Testable;
|
||||||
|
import com.alibaba.testable.generator.StaticNewClassGenerator;
|
||||||
import com.alibaba.testable.generator.TestableClassGenerator;
|
import com.alibaba.testable.generator.TestableClassGenerator;
|
||||||
import com.alibaba.testable.translator.TestableFieldTranslator;
|
import com.alibaba.testable.translator.TestableFieldTranslator;
|
||||||
import com.alibaba.testable.util.ConstPool;
|
import com.alibaba.testable.util.ConstPool;
|
||||||
@ -13,11 +14,14 @@ import javax.lang.model.SourceVersion;
|
|||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.Name;
|
import javax.lang.model.element.Name;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.tools.FileObject;
|
||||||
import javax.tools.JavaFileObject;
|
import javax.tools.JavaFileObject;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static javax.tools.StandardLocation.SOURCE_OUTPUT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author flin
|
* @author flin
|
||||||
*/
|
*/
|
||||||
@ -25,9 +29,13 @@ import java.util.Set;
|
|||||||
@SupportedSourceVersion(SourceVersion.RELEASE_7)
|
@SupportedSourceVersion(SourceVersion.RELEASE_7)
|
||||||
public class TestableProcessor extends BaseProcessor {
|
public class TestableProcessor extends BaseProcessor {
|
||||||
|
|
||||||
|
private static final String JAVA_POSTFIX = ".java";
|
||||||
|
private static final String GENERATED_TEST_SOURCES = "generated-test-sources";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||||
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Testable.class);
|
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Testable.class);
|
||||||
|
createStaticNewClass();
|
||||||
for (Element element : elements) {
|
for (Element element : elements) {
|
||||||
if (element.getKind().isClass()) {
|
if (element.getKind().isClass()) {
|
||||||
processClassElement(element);
|
processClassElement(element);
|
||||||
@ -38,6 +46,17 @@ public class TestableProcessor extends BaseProcessor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createStaticNewClass() {
|
||||||
|
try {
|
||||||
|
FileObject staticNewClassFile = filter.getResource(SOURCE_OUTPUT, ConstPool.SN_PKG, ConstPool.SN_CLS + JAVA_POSTFIX);
|
||||||
|
if (!staticNewClassFile.getName().contains(GENERATED_TEST_SOURCES) && staticNewClassFile.getLastModified() == 0) {
|
||||||
|
writeSourceFile(ConstPool.SN_PKG + "." + ConstPool.SN_CLS, new StaticNewClassGenerator().fetch());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void processFieldElement(Element field) {
|
private void processFieldElement(Element field) {
|
||||||
JCTree tree = trees.getTree(field);
|
JCTree tree = trees.getTree(field);
|
||||||
tree.accept(new TestableFieldTranslator(treeMaker));
|
tree.accept(new TestableFieldTranslator(treeMaker));
|
||||||
@ -48,15 +67,20 @@ public class TestableProcessor extends BaseProcessor {
|
|||||||
String testableTypeName = getTestableClassName(clazz.getSimpleName());
|
String testableTypeName = getTestableClassName(clazz.getSimpleName());
|
||||||
String fullQualityTypeName = packageName + "." + testableTypeName;
|
String fullQualityTypeName = packageName + "." + testableTypeName;
|
||||||
try {
|
try {
|
||||||
JavaFileObject jfo = filter.createSourceFile(fullQualityTypeName);
|
writeSourceFile(fullQualityTypeName,
|
||||||
Writer writer = jfo.openWriter();
|
new TestableClassGenerator(trees, treeMaker).fetch(clazz, packageName, testableTypeName));
|
||||||
writer.write(new TestableClassGenerator(trees).fetch(clazz, packageName, testableTypeName));
|
|
||||||
writer.close();
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeSourceFile(String fullQualityTypeName, String content) throws IOException {
|
||||||
|
JavaFileObject jfo = filter.createSourceFile(fullQualityTypeName);
|
||||||
|
Writer writer = jfo.openWriter();
|
||||||
|
writer.write(content);
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
|
||||||
private String getTestableClassName(Name className) {
|
private String getTestableClassName(Name className) {
|
||||||
return className.toString().replace(".", "_") + ConstPool.TESTABLE;
|
return className.toString().replace(".", "_") + ConstPool.TESTABLE;
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,8 @@ public final class ConstPool {
|
|||||||
public static final String CONSTRUCTOR_NAME = "<init>";
|
public static final String CONSTRUCTOR_NAME = "<init>";
|
||||||
public static final String TYPE_VOID = "void";
|
public static final String TYPE_VOID = "void";
|
||||||
public static final String TESTABLE = "Testable";
|
public static final String TESTABLE = "Testable";
|
||||||
|
public static final String SN_PKG = "n";
|
||||||
|
public static final String SN_CLS = "e";
|
||||||
|
public static final String SN_METHOD = "w";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user