diff --git a/src/main/java/com/alibaba/testable/generator/TestableClassDevRoleGenerator.java b/src/main/java/com/alibaba/testable/generator/TestableClassDevRoleGenerator.java index 30133ec..26bc54a 100644 --- a/src/main/java/com/alibaba/testable/generator/TestableClassDevRoleGenerator.java +++ b/src/main/java/com/alibaba/testable/generator/TestableClassDevRoleGenerator.java @@ -2,16 +2,14 @@ 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.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.Symbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeMaker; -import com.sun.tools.javac.util.Names; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; @@ -28,19 +26,15 @@ import java.util.Set; */ public class TestableClassDevRoleGenerator { - private final JavacTrees trees; - private final TreeMaker treeMaker; - private final Names names; + private final TestableContext cx; - public TestableClassDevRoleGenerator(JavacTrees trees, TreeMaker treeMaker, Names names) { - this.trees = trees; - this.treeMaker = treeMaker; - this.names = names; + public TestableClassDevRoleGenerator(TestableContext cx) { + this.cx = cx; } public String fetch(Symbol.ClassSymbol clazz, String packageName, String className) { - JCTree tree = trees.getTree(clazz); - TestableClassDevRoleTranslator translator = new TestableClassDevRoleTranslator(treeMaker, names); + JCTree tree = cx.trees.getTree(clazz); + TestableClassDevRoleTranslator translator = new TestableClassDevRoleTranslator(cx); tree.accept(translator); List methodSpecs = new ArrayList<>(); diff --git a/src/main/java/com/alibaba/testable/model/TestableContext.java b/src/main/java/com/alibaba/testable/model/TestableContext.java new file mode 100644 index 0000000..1559ef0 --- /dev/null +++ b/src/main/java/com/alibaba/testable/model/TestableContext.java @@ -0,0 +1,63 @@ +package com.alibaba.testable.model; + +import com.alibaba.testable.util.TestableLogger; +import com.sun.tools.javac.api.JavacTrees; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.util.Names; + +import javax.annotation.processing.Filer; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; + +/** + * @author flin + */ +public class TestableContext { + + /** + * TestableLogger used for printing log during compilation + */ + public final TestableLogger logger; + + /** + * Filer used for generate source file + */ + public final Filer filter; + + /** + * Elements used for operator element + */ + public final Elements elementUtils; + + /** + * Types used for operator type + */ + public final Types typeUtils; + + /** + * JavacTrees provide the source AST + */ + public final JavacTrees trees; + + /** + * TreeMaker used for creating AST node + */ + public final TreeMaker treeMaker; + + /** + * Names used for creating resource name + */ + public final Names names; + + public TestableContext(TestableLogger logger, Filer filter, Elements elementUtils, + Types typeUtils, JavacTrees trees, TreeMaker treeMaker, Names names) { + this.logger = logger; + this.filter = filter; + this.elementUtils = elementUtils; + this.typeUtils = typeUtils; + this.trees = trees; + this.treeMaker = treeMaker; + this.names = names; + } + +} diff --git a/src/main/java/com/alibaba/testable/processor/BaseProcessor.java b/src/main/java/com/alibaba/testable/processor/BaseProcessor.java index 24f80ba..bce23aa 100644 --- a/src/main/java/com/alibaba/testable/processor/BaseProcessor.java +++ b/src/main/java/com/alibaba/testable/processor/BaseProcessor.java @@ -1,5 +1,7 @@ package com.alibaba.testable.processor; +import com.alibaba.testable.model.TestableContext; +import com.alibaba.testable.util.TestableLogger; import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import com.sun.tools.javac.tree.TreeMaker; @@ -7,75 +9,22 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Names; import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; -import javax.tools.Diagnostic; /** * @author flin */ public abstract class BaseProcessor extends AbstractProcessor { - /** - * Messager used for printing log during compilation - */ - private Messager messager; - - /** - * Filer used for generate source file - */ - protected Filer filter; - - /** - * Elements used for operator element - */ - protected Elements elementUtils; - - /** - * Types used for operator type - */ - protected Types typeUtils; - - /** - * JavacTrees provide the source AST - */ - protected JavacTrees trees; - - /** - * TreeMaker used for creating AST node - */ - protected TreeMaker treeMaker; - - /** - * Names used for creating resource name - */ - protected Names names; + protected TestableContext cx; @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); Context context = ((JavacProcessingEnvironment)processingEnv).getContext(); - messager = processingEnv.getMessager(); - filter = processingEnv.getFiler(); - elementUtils = processingEnv.getElementUtils(); - typeUtils = processingEnv.getTypeUtils(); - trees = JavacTrees.instance(processingEnv); - treeMaker = TreeMaker.instance(context); - names = Names.instance(context); + cx = new TestableContext(new TestableLogger(processingEnv.getMessager()), processingEnv.getFiler(), + processingEnv.getElementUtils(), processingEnv.getTypeUtils(), JavacTrees.instance(processingEnv), + TreeMaker.instance(context), Names.instance(context)); } - protected void info(String msg) { - System.out.println("[INFO] " + msg); - } - - protected void warn(String msg) { - messager.printMessage(Diagnostic.Kind.MANDATORY_WARNING, msg); - } - - protected void error(String msg) { - messager.printMessage(Diagnostic.Kind.ERROR, msg); - } } diff --git a/src/main/java/com/alibaba/testable/processor/TestableProcessor.java b/src/main/java/com/alibaba/testable/processor/TestableProcessor.java index 0fd2f4e..0c910db 100644 --- a/src/main/java/com/alibaba/testable/processor/TestableProcessor.java +++ b/src/main/java/com/alibaba/testable/processor/TestableProcessor.java @@ -53,7 +53,7 @@ public class TestableProcessor extends BaseProcessor { private void createStaticNewClass() { if (!isStaticNewClassExist()) { try { - writeSourceFile(ConstPool.SN_PKG_CLS, new StaticNewClassGenerator().fetch()); + writeSourceFile(ConstPool.SN_PKG_CLS, new StaticNewClassGenerator(cx).fetch()); } catch (IOException e) { e.printStackTrace(); } @@ -62,7 +62,7 @@ public class TestableProcessor extends BaseProcessor { private boolean isStaticNewClassExist() { try { - FileObject staticNewClassFile = filter.getResource(SOURCE_OUTPUT, ConstPool.SN_PKG, + FileObject staticNewClassFile = cx.filter.getResource(SOURCE_OUTPUT, ConstPool.SN_PKG, ConstPool.SN_CLS + JAVA_POSTFIX); return isCompilingTestClass(staticNewClassFile) || staticNewClassFile.getLastModified() > 0; } catch (FilerException e) { @@ -81,20 +81,20 @@ public class TestableProcessor extends BaseProcessor { } private void processDevRoleClassElement(Symbol.ClassSymbol clazz) { - String packageName = elementUtils.getPackageOf(clazz).getQualifiedName().toString(); + String packageName = cx.elementUtils.getPackageOf(clazz).getQualifiedName().toString(); String testableTypeName = getTestableClassName(clazz.getSimpleName()); String fullQualityTypeName = packageName + "." + testableTypeName; try { writeSourceFile(fullQualityTypeName, - new TestableClassDevRoleGenerator(trees, treeMaker, names).fetch(clazz, packageName, testableTypeName)); + new TestableClassDevRoleGenerator(cx).fetch(clazz, packageName, testableTypeName)); } catch (IOException e) { e.printStackTrace(); } } private void processTestRoleClassElement(Symbol.ClassSymbol clazz) { - JCTree tree = trees.getTree(clazz); - tree.accept(new TestableClassTestRoleTranslator(getPkgName(clazz), getOriginClassName(clazz), treeMaker, names)); + JCTree tree = cx.trees.getTree(clazz); + tree.accept(new TestableClassTestRoleTranslator(getPkgName(clazz), getOriginClassName(clazz), cx)); } private String getPkgName(Symbol.ClassSymbol clazz) { @@ -107,7 +107,7 @@ public class TestableProcessor extends BaseProcessor { } private void writeSourceFile(String fullQualityTypeName, String content) throws IOException { - JavaFileObject jfo = filter.createSourceFile(fullQualityTypeName); + JavaFileObject jfo = cx.filter.createSourceFile(fullQualityTypeName); Writer writer = jfo.openWriter(); writer.write(content); writer.close(); diff --git a/src/main/java/com/alibaba/testable/translator/TestableClassDevRoleTranslator.java b/src/main/java/com/alibaba/testable/translator/TestableClassDevRoleTranslator.java index 8c476b0..b8b9d9c 100644 --- a/src/main/java/com/alibaba/testable/translator/TestableClassDevRoleTranslator.java +++ b/src/main/java/com/alibaba/testable/translator/TestableClassDevRoleTranslator.java @@ -1,16 +1,15 @@ package com.alibaba.testable.translator; +import com.alibaba.testable.model.TestableContext; import com.alibaba.testable.translator.tree.TestableFieldAccess; import com.alibaba.testable.translator.tree.TestableMethodInvocation; import com.alibaba.testable.util.ConstPool; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.TreeTranslator; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; -import com.sun.tools.javac.util.Names; import java.lang.reflect.Modifier; @@ -21,8 +20,7 @@ import java.lang.reflect.Modifier; */ public class TestableClassDevRoleTranslator extends TreeTranslator { - private final TreeMaker treeMaker; - private final Names names; + private final TestableContext cx; /** * Methods to inject @@ -42,9 +40,8 @@ public class TestableClassDevRoleTranslator extends TreeTranslator { return fields; } - public TestableClassDevRoleTranslator(TreeMaker treeMaker, Names names) { - this.treeMaker = treeMaker; - this.names = names; + public TestableClassDevRoleTranslator(TestableContext cx) { + this.cx = cx; } @Override @@ -152,12 +149,12 @@ public class TestableClassDevRoleTranslator extends TreeTranslator { } private TestableMethodInvocation getStaticNewCall(JCTree.JCNewClass newClassExpr, Name className) { - TestableFieldAccess snClass = new TestableFieldAccess(treeMaker.Ident(names.fromString(ConstPool.SN_PKG)), - names.fromString(ConstPool.SN_CLS), null); + TestableFieldAccess snClass = new TestableFieldAccess(cx.treeMaker.Ident(cx.names.fromString(ConstPool.SN_PKG)), + cx.names.fromString(ConstPool.SN_CLS), null); TestableFieldAccess snMethod = new TestableFieldAccess(snClass, - names.fromString(ConstPool.SN_METHOD), null); - JCTree.JCExpression classType = new TestableFieldAccess(treeMaker.Ident(className), - names.fromString("class"), null); + cx.names.fromString(ConstPool.SN_METHOD), null); + JCTree.JCExpression classType = new TestableFieldAccess(cx.treeMaker.Ident(className), + cx.names.fromString("class"), null); ListBuffer args = ListBuffer.of(classType); args.addAll(newClassExpr.args); return new TestableMethodInvocation(null, snMethod, args.toList()); diff --git a/src/main/java/com/alibaba/testable/translator/TestableClassTestRoleTranslator.java b/src/main/java/com/alibaba/testable/translator/TestableClassTestRoleTranslator.java index b7babb4..5a34b24 100644 --- a/src/main/java/com/alibaba/testable/translator/TestableClassTestRoleTranslator.java +++ b/src/main/java/com/alibaba/testable/translator/TestableClassTestRoleTranslator.java @@ -1,12 +1,12 @@ package com.alibaba.testable.translator; import com.alibaba.testable.model.TestLibType; +import com.alibaba.testable.model.TestableContext; import com.alibaba.testable.translator.tree.TestableFieldAccess; import com.alibaba.testable.translator.tree.TestableMethodInvocation; import com.alibaba.testable.util.ConstPool; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.TreeTranslator; import com.sun.tools.javac.util.*; @@ -22,8 +22,7 @@ public class TestableClassTestRoleTranslator extends TreeTranslator { private static final String ANNOTATION_TESTABLE_INJECT = "com.alibaba.testable.annotation.TestableInject"; private static final String ANNOTATION_JUNIT5_SETUP = "org.junit.jupiter.api.BeforeEach"; private static final String ANNOTATION_JUNIT5_TEST = "org.junit.jupiter.api.Test"; - private TreeMaker treeMaker; - private Names names; + private final TestableContext cx; private String sourceClassName; private ListBuffer sourceClassIns = new ListBuffer(); private List stubbornFields = List.nil(); @@ -31,10 +30,9 @@ public class TestableClassTestRoleTranslator extends TreeTranslator { private String testSetupMethodName; private TestLibType testLibType = TestLibType.JUnit4; - public TestableClassTestRoleTranslator(String pkgName, String className, TreeMaker treeMaker, Names names) { + public TestableClassTestRoleTranslator(String pkgName, String className, TestableContext cx) { this.sourceClassName = className; - this.treeMaker = treeMaker; - this.names = names; + this.cx = cx; try { stubbornFields = List.from( (String[])Class.forName(pkgName + "." + className + ConstPool.TESTABLE) @@ -105,24 +103,24 @@ public class TestableClassTestRoleTranslator extends TreeTranslator { super.visitClassDef(jcClassDecl); ListBuffer ndefs = new ListBuffer<>(); ndefs.addAll(jcClassDecl.defs); - JCTree.JCModifiers mods = treeMaker.Modifiers(Modifier.PUBLIC, makeAnnotations()); - ndefs.add(treeMaker.MethodDef(mods, names.fromString("testableSetup"), treeMaker.Type(new Type.JCVoidType()), - List.nil(), List.nil(), List.nil(), - testableSetupBlock(), null)); + JCTree.JCModifiers mods = cx.treeMaker.Modifiers(Modifier.PUBLIC, makeAnnotations()); + ndefs.add(cx.treeMaker.MethodDef(mods, cx.names.fromString("testableSetup"), + cx.treeMaker.Type(new Type.JCVoidType()), List.nil(), + List.nil(), List.nil(), testableSetupBlock(), null)); jcClassDecl.defs = ndefs.toList(); } private List makeAnnotations() { String[] elems = ANNOTATION_JUNIT5_TEST.split("\\."); - JCTree.JCExpression e = treeMaker.Ident(names.fromString(elems[0])); + JCTree.JCExpression e = cx.treeMaker.Ident(cx.names.fromString(elems[0])); for (int i = 1 ; i < elems.length ; i++) { - e = treeMaker.Select(e, names.fromString(elems[i])); + e = cx.treeMaker.Select(e, cx.names.fromString(elems[i])); } - return List.of(treeMaker.Annotation(e, List.nil())); + return List.of(cx.treeMaker.Annotation(e, List.nil())); } private JCTree.JCBlock testableSetupBlock() { - return treeMaker.Block(0, List.nil()); + return cx.treeMaker.Block(0, List.nil()); } /** @@ -154,7 +152,7 @@ public class TestableClassTestRoleTranslator extends TreeTranslator { private Name getStubbornSetterMethodName(JCTree.JCAssign assign) { String name = ((JCTree.JCFieldAccess)assign.lhs).name.toString() + ConstPool.TESTABLE_SET_METHOD_PREFIX; - return names.fromString(name); + return cx.names.fromString(name); } private boolean isAssignStubbornField(JCTree.JCAssign expr) { @@ -165,7 +163,7 @@ public class TestableClassTestRoleTranslator extends TreeTranslator { private JCTree.JCIdent getTestableClassIdent(JCTree.JCExpression clazz) { Name className = ((JCTree.JCIdent)clazz).name; - return treeMaker.Ident(names.fromString(className + ConstPool.TESTABLE)); + return cx.treeMaker.Ident(cx.names.fromString(className + ConstPool.TESTABLE)); } } diff --git a/src/main/java/com/alibaba/testable/util/TestableLogger.java b/src/main/java/com/alibaba/testable/util/TestableLogger.java new file mode 100644 index 0000000..aab042e --- /dev/null +++ b/src/main/java/com/alibaba/testable/util/TestableLogger.java @@ -0,0 +1,30 @@ +package com.alibaba.testable.util; + +import javax.annotation.processing.Messager; +import javax.tools.Diagnostic; + +/** + * practical logger + * + * @author flin + */ +public class TestableLogger { + + private Messager messager; + + public TestableLogger(Messager messager) { + this.messager = messager; + } + + public void info(String msg) { + System.out.println("[INFO] " + msg); + } + + public void warn(String msg) { + messager.printMessage(Diagnostic.Kind.MANDATORY_WARNING, msg); + } + + public void error(String msg) { + messager.printMessage(Diagnostic.Kind.ERROR, msg); + } +}