support specify source class for private accessor

This commit is contained in:
金戟 2021-02-01 08:08:33 +08:00
parent 77b955a5ce
commit 290d0db400
4 changed files with 46 additions and 18 deletions

View File

@ -7,11 +7,13 @@ import com.alibaba.testable.processor.translator.EnablePrivateAccessTranslator;
import com.alibaba.testable.processor.util.JavacUtil;
import com.alibaba.testable.processor.util.TestableLogger;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Pair;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
@ -19,7 +21,6 @@ import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import java.util.Set;
@ -29,6 +30,8 @@ import java.util.Set;
@SupportedAnnotationTypes("com.alibaba.testable.processor.annotation.EnablePrivateAccess")
public class EnablePrivateAccessProcessor extends AbstractProcessor {
private static final String SRC_CLASS = "srcClass";
private TestableContext cx;
@Override
@ -53,8 +56,10 @@ public class EnablePrivateAccessProcessor extends AbstractProcessor {
}
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(EnablePrivateAccess.class);
for (Element element : elements) {
if (element.getKind().isClass() && isTestClass(element.getSimpleName())) {
processClassElement((Symbol.ClassSymbol)element);
if (element.getKind().isClass()) {
Symbol.ClassSymbol testClass = (Symbol.ClassSymbol)element;
String sourceClassName = getSourceClassName(testClass);
processClassElement(testClass, sourceClassName);
}
}
return true;
@ -66,6 +71,19 @@ public class EnablePrivateAccessProcessor extends AbstractProcessor {
return SourceVersion.values()[SourceVersion.values().length - 1];
}
private String getSourceClassName(Symbol.ClassSymbol testClass) {
for (Attribute.Compound annotation : testClass.getMetadata().getDeclarationAttributes()) {
if (ConstPool.ENABLE_PRIVATE_ACCESS.equals(annotation.type.tsym.toString())) {
for (Pair<Symbol.MethodSymbol, Attribute> p : annotation.values) {
if (SRC_CLASS.equals(p.fst.name.toString())) {
return p.snd.getValue().toString();
}
}
}
}
return null;
}
private JavacProcessingEnvironment getJavacProcessingEnvironment(ProcessingEnvironment processingEnv) {
try {
return JavacUtil.getJavacProcessingEnvironment(processingEnv);
@ -74,14 +92,10 @@ public class EnablePrivateAccessProcessor extends AbstractProcessor {
}
}
private boolean isTestClass(Name name) {
return name.toString().endsWith(ConstPool.TEST_POSTFIX);
}
private void processClassElement(Symbol.ClassSymbol clazz) {
private void processClassElement(Symbol.ClassSymbol testClass, String sourceClassName) {
if (cx.trees != null) {
JCTree tree = cx.trees.getTree(clazz);
tree.accept(new EnablePrivateAccessTranslator(clazz, cx));
JCTree tree = cx.trees.getTree(testClass);
tree.accept(new EnablePrivateAccessTranslator(cx, testClass, sourceClassName));
}
}

View File

@ -1,5 +1,6 @@
package com.alibaba.testable.processor.annotation;
import javax.lang.model.type.NullType;
import java.lang.annotation.*;
/**
@ -11,4 +12,11 @@ import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Documented
public @interface EnablePrivateAccess {
/**
* explicit specify the source class to be tested
* @return
*/
Class<?> srcClass() default NullType.class;
}

View File

@ -5,6 +5,7 @@ package com.alibaba.testable.processor.constant;
*/
public final class ConstPool {
public static final String ENABLE_PRIVATE_ACCESS = "com.alibaba.testable.processor.annotation.EnablePrivateAccess";
public static final String TESTABLE_PRIVATE_ACCESSOR = "com.alibaba.testable.core.accessor.PrivateAccessor";
public static final String TEST_POSTFIX = "Test";

View File

@ -1,6 +1,5 @@
package com.alibaba.testable.processor.translator;
import com.alibaba.testable.processor.constant.ConstPool;
import com.alibaba.testable.processor.generator.PrivateAccessStatementGenerator;
import com.alibaba.testable.processor.model.MemberRecord;
import com.alibaba.testable.processor.model.MemberType;
@ -22,6 +21,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static com.alibaba.testable.processor.constant.ConstPool.TEST_POSTFIX;
/**
* Travel AST
*
@ -50,14 +51,18 @@ public class EnablePrivateAccessTranslator extends BaseTranslator {
private final PrivateAccessStatementGenerator privateAccessStatementGenerator;
private final PrivateAccessChecker privateAccessChecker;
public EnablePrivateAccessTranslator(Symbol.ClassSymbol clazz, TestableContext cx) {
String pkgName = ((Symbol.PackageSymbol)clazz.owner).fullname.toString();
String testClassName = clazz.getSimpleName().toString();
String sourceClass = testClassName.substring(0, testClassName.length() - ConstPool.TEST_POSTFIX.length());
public EnablePrivateAccessTranslator(TestableContext cx, Symbol.ClassSymbol clazz, String srcClassName) {
String sourceClassFullName;
if (srcClassName == null) {
String testClassFullName = clazz.fullname.toString();
sourceClassFullName = testClassFullName.substring(0, testClassFullName.length() - TEST_POSTFIX.length());
} else {
sourceClassFullName = srcClassName;
}
String sourceClassShortName = sourceClassFullName.substring(sourceClassFullName.lastIndexOf('.') + 1);
this.privateAccessStatementGenerator = new PrivateAccessStatementGenerator(cx);
this.sourceClassName = cx.names.fromString(sourceClass);
this.sourceClassName = cx.names.fromString(sourceClassShortName);
try {
String sourceClassFullName = pkgName + "." + sourceClass;
Class<?> cls = getSourceClass(clazz, sourceClassFullName);
if (cls == null) {
cx.logger.error("Failed to load source class: " + sourceClassFullName);
@ -67,7 +72,7 @@ public class EnablePrivateAccessTranslator extends BaseTranslator {
} catch (Exception e) {
e.printStackTrace();
}
this.privateAccessChecker = new PrivateAccessChecker(cx, sourceClassName.toString(), memberRecord);
this.privateAccessChecker = new PrivateAccessChecker(cx, sourceClassShortName, memberRecord);
}
/**