我正在使用jdk.compiler模块和启用了预览功能的Java15编写一个java编译器插件。根据oracle的说法,java9中引入的jdk.compiler模块包含了java8的tools.jar中的所有api,除了com.sun.tools.javac.tree包。我要做的是找到所有用注解注解的类,并获得value()属性,在这里是class<?>类型。
插件代码:
public class ExtensionMethodPlugin implements Plugin{
@Override
public String getName() {
return "ExtensionMethodPlugin";
}
@Override
public void init(JavacTask task, String... args) {
task.addTaskListener(new TaskListener() {
@Override
public void started(TaskEvent event) {
}
@Override
public void finished(TaskEvent event) {
if (event.getKind() != TaskEvent.Kind.PARSE) {
return;
}
event.getCompilationUnit().accept(new TreeScanner<Void, Void>() {
@Override
public Void visitClass(ClassTree node, Void aVoid) {
var trees = Trees.instance(task);
var targetClass = InstrumentationUtils.findExtensionTargetForClass(node, trees, event.getCompilationUnit());
if (targetClass.isEmpty()) {
return super.visitClass(node, aVoid);
}
var methods = node
.getMembers()
.stream()
.filter(e -> e instanceof MethodTree)
.map(e -> (MethodTree) e)
.filter(tree -> tree.getReturnType() != null)
.filter(e -> InstrumentationUtils.shouldInstrumentMethod(e, targetClass.get()))
.collect(Collectors.toList());
throw new RuntimeException("Not implemented");
}
}, null);
}
});
}
}
Jmeter 实用程序代码:
@UtilityClass
public class InstrumentationUtils {
public Optional<Class<?>> findExtensionTargetForClass(ClassTree node, Trees trees, CompilationUnitTree tree) {
return node
.getModifiers()
.getAnnotations()
.stream()
.filter(a -> Extension.class.getSimpleName().equals(a.getAnnotationType().toString()))
.findFirst()
.map(e -> InstrumentationUtils.findConstantTargetClassInAnnotationTree(e, trees, tree));
}
private Class<?> findConstantTargetClassInAnnotationTree(AnnotationTree tree, Trees trees, CompilationUnitTree compilationUnitTree) {
return tree
.getArguments()
.stream()
.filter(entry -> entry.getKind() == Tree.Kind.ASSIGNMENT)
.findFirst()
.map(e -> (AssignmentTree) e)
.map(e -> classForName(e, trees, compilationUnitTree))
.orElseThrow(() -> new RuntimeException("Cannot compile: Missing constant class target in annotation!"));
}
private Class<?> classForName(AssignmentTree tree, Trees trees, CompilationUnitTree compilationUnitTree){
//Don't know how to move from here
}
}
注解代码:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Extension {
Class<?> value();
}
我发现的唯一解决方案涉及到使用jctree类,但正如我前面所说的,这些类不再可用。我知道我可以很容易地在jdk.compiler模块中强制导出该包,但我更愿意找到更好的方法。我试过用树形扫描仪,但结果一无所获:
tree.accept(new TreeScanner<Class<?>, Void>() {
// b.class
@Override
public Class<?> visitAssignment(AssignmentTree node, Void unused) {
return node.getExpression().accept(new TreeScanner<Class<?>, Void>(){
//.class
@Override
public Class<?> visitMemberSelect(MemberSelectTree node, Void unused) {
return node.getExpression().accept(new TreeScanner<Class<?>, Void>(){
// class ???
@Override
public Class<?> visitIdentifier(IdentifierTree node, Void unused) {
trees.printMessage(Diagnostic.Kind.WARNING, node.getName(), tree, compilationUnitTree);
return super.visitIdentifier(node, unused);
}
}, null);
}
}, null);
}
}, null);
提前谢谢!
1条答案
按热度按时间cotxawn71#
当您需要做的只是“查找所有使用我的注解进行注解的类并获取value()属性”时,就不需要
jdk.compiler
模块中包含的注解处理器apijava.compiler
模块就足够了,处理起来也简单得多。下面是一个独立的示例:
这个指纹
当然,此功能可以与
jdk.compiler
需要时延长。