我试图用jsr 269格式编写一个注释处理器,它使用javac的编译器树api来做一些源代码分析。我对成员选择表达式感兴趣,比如方法调用。
我可以很容易地得到所选方法(或字段等)的名称。但我想知道成员是从哪种类型中选择的,我似乎找不到一个简单的方法来完成这项工作。
Trees.getTypeMirror
收益率
null
对于我尝试调用的所有内容(javadoc没有给出任何提示)。
我想我可以详尽地分析成员select左侧的各种表达式,并通过递归分析确定表达式的静态类型:
NewClassTree
,
TypeCastTree
,
MethodInvocationTree
,
ArrayAccessTree
,以及许多其他。但是这看起来像是很多容易出错的工作,而且很明显javac已经知道表达式的静态类型,因为它需要这些信息用于很多目的。但是我怎样才能获得这种类型的信息呢?
到目前为止我所拥有的:
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreePathScanner;
import com.sun.source.util.Trees;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
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.TypeElement;
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class PublicProcessor extends AbstractProcessor {
public @Override boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element e : roundEnv.getRootElements()) {
final Trees trees = Trees.instance(processingEnv);
final TreePath root = trees.getPath(e);
new TreePathScanner() {
public @Override Void visitMethodInvocation(MethodInvocationTree node, Void p) {
System.err.println("visiting method invocation: " + node + " of kind: " + node.getMethodSelect().getKind());
TreePath expr = TreePath.getPath(root, node);
System.err.println(" of type: " + trees.getTypeMirror(expr));
return super.visitMethodInvocation(node, p);
}
public @Override Void visitMemberSelect(MemberSelectTree node, Void p) {
System.err.println("accessing member: " + node.getIdentifier());
System.err.println(" from: " + getCurrentPath().getCompilationUnit().getSourceFile().toUri());
TreePath expr = TreePath.getPath(root, node.getExpression());
System.err.println(" in expr: " + expr.getLeaf());
System.err.println(" of type: " + trees.getTypeMirror(expr));
return super.visitMemberSelect(node, p);
}
}.scan(root, null);
}
return true;
}
}
当运行在一些简单的代码上进行方法调用时,它会打印出什么:
visiting method invocation: new Class().method() of kind: MEMBER_SELECT
of type: null
accessing member: method
from: .../Whatever.java
in expr: new Class()
of type: null