如何从javac插件中获取MemberSelectTree中表达式的类型?

Jes*_*ick 5 java javac annotation-processing

我试图用JSR 269格式编写一个注释处理器,它使用javac的Compiler Tree API来做一些源代码分析.我对成员选择表达式感兴趣,例如方法调用.

我可以很容易地获得所选方法(或字段等)的名称.但我想知道该成员的选择类型,我似乎无法找到一种直接的方法来做到这一点.Trees.getTypeMirror返回null我尝试调用的所有内容(而Javadoc没有提示).

我想我可以详尽地分析每一种表达对成员的左侧选择,并通过回归分析确定的静态类型的表达式: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<Void,Void>() {
                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;
    }
}
Run Code Online (Sandbox Code Playgroud)

以及在一些简单的代码制作方法调用上运行时打印的内容:

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
Run Code Online (Sandbox Code Playgroud)

Jes*_*ick 1

在 java 的注释处理器中发现方法调用的类

似乎正在解决一个非常相似的问题,所以我将尝试使用那里给出的建议。不幸的是,它看起来并不简单,并且com.sun.tools.javac似乎需要使用该包。