Java8,如何发现visitMethodInvocation中的类和方法名?

ppr*_*dos 3 java annotations javac

对于 Java7 和 Java8,如果调用了某些方法,我想生成警告。如果用户编译时存在特定的 jar,则将打印警告。

我编写了一个注释处理器并捕获了visitMethodInvocation()。现在,我想提取将调用的类和方法名称。

有可能这样做吗?或者如何解决这个问题?

emo*_*ory 5

您可以执行以下操作:

package mystuff;

import com.sun.source.tree.*;
import com.sun.source.util.*;
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.tools.*;

@SupportedAnnotationTypes("*")
    public class Proc extends AbstractProcessor{
    @Override
        public boolean process(Set<?extends TypeElement>annotations,RoundEnvironment roundEnvironment){
        final Trees trees=Trees.instance(processingEnv);
        for(Element element:roundEnvironment.getRootElements()){
        TreePath path=trees.getPath(element);
        final CompilationUnitTree compilationUnit=path.getCompilationUnit();
        compilationUnit.accept(new TreeScanner<Object,Object>(){
            @Override
                public Object visitMethodInvocation(MethodInvocationTree tree,Object data){
                tree.getMethodSelect().accept(new SimpleTreeVisitor<Object,Object>(){
                    @Override
                    public Object visitMemberSelect(MemberSelectTree tree,Object data){
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,String.format("class:  %1$s\nmethod: %2$s",tree.getExpression(),tree.getIdentifier()));
                    return null;
                    }
                },null);
                return null;
            }
            },null);
        }
        return true;
    }
    }
Run Code Online (Sandbox Code Playgroud)

我用那个处理器来处理下面的类

package stuff;

import java.util.*;

@MyAnnotation
class MyProgram{
    public void run(){
    System.out.println("Hello World!");
    }
}
Run Code Online (Sandbox Code Playgroud)

并取得了这个结果:

class:  System.out
  method: println
Run Code Online (Sandbox Code Playgroud)

我很确定生成的方法名称正是您要查找的。我很确定“班级”并不完全是您要找的,但它是一个不错的开始。

在我的示例中,您可能希望它为类打印“java.io.PrintStream”。要获得它,您可以使用processingEnv.getElementUtils().getTypeElement("java.lang.System")获取表示系统类的 TypeElement。然后你可以使用processingEnv.getElementUtils().getAllMembers()来获取系统类的每个成员。遍历它以找到out. 使用该asType方法获取其类型。

上一段是粗略的简化。处理器不知道作为out隐式导入的一部分的类的静态成员的先验java.lang包。因此,您的代码将不得不尝试但无法找到以下类Systemjava.util.System(因为它在导入中)System.outjava.util.System.out、 和java.lang.System.out

我只处理过 MemberSelect。您将不得不处理其他可能性,包括 MethodInvocation。例如new Object().toString().hashCode()应该是class=Object,method=hashCode。