代码之家  ›  专栏  ›  技术社区  ›  Vincent

在java注释处理器中发现methodinvocation的类

  •  6
  • Vincent  · 技术社区  · 17 年前

    我正在为构建系统编写一些工具,以便对属于包含特定注释的类的方法强制执行一些严格的调用约定。

    我正在使用编译器树API。。。

    我想知道的是,当遍历“树”时,如何判断MethodInvocation的类/接口类型。

    我将TreePathScanner子类化为:

    @Override
    public Object visitMethodInvocation(MethodInvocationTree node, Trees trees) {
    
    }
    

    我希望有一种方法可以告诉您试图在其上调用方法的类(或接口)的类型。我走错方向了吗?谢谢你的建议。。。

    1 回复  |  直到 17 年前
        1
  •  11
  •   notnoop    17 年前

    这里有几个问题。你可以选择 了解方法调用接收器的Java类型,或者 信息丰富,因为它还提供了泛型类型,例如。 List<String> List<E> .

    获取元素

    以下是:

    
      MethodInvocationTree node = ...;
      Element method =
            TreeInfo.symbol((JCTree)node.getMethodSelect());
      TypeElement invokedClass = (TypeElement)method.getEnclosingElement();
    

    角落案例:

    1. new ArrayList<String>.equals(null) 会回来吗 AbstractList 而不是 ArrayList ,因为实现了equals() 在里面 摘要列表 不 .

    2. 处理数组调用时,例如。 new int[].clone() ,你会的 TypeElement 一流的 Array

    获取实际类型

    在没有明确给出接收方的内部类中 (例如,不像 OuterClass.this.toString() )。以下是一个示例实现:

    
      MethodInvocationTree node = ...;
      TypeMirror receiver;
      if (methodSel.getKind() == Tree.Kind.MEMBER_SELECT) {
        ExpressionTree receiver = ((MemberSelectTree)methodSel).getExpression();
        receiverType = ((JCTree)receiver).type;
      } else if (methodSel.getKind() == Tree.Kind.IDENTIFIER) {
        // need to resolve implicit this, which is described in
        //  JLS3 15.12.1 and 15.9.2
    
        // A bit too much work that I don't want to work on now
        // Look at source code of
        //   Attr.visitApply(JCMethodInvocation)
        //   resolveImplicitThis(DiagnosticPosition, Env, Type)
      } else
        throw new AssertionError("Unexpected type: " + methodSel.getKind());
    

    注:

    这个 receiver 类型必须是 TypeMirror 不 DeclaredType new int[5].clone() 接受者 会是 一 ArrayType 属于 int[] ,这比上一篇文章内容更丰富 方法

    让它运行

    前面的两个方法都需要编译器解析类型 课程信息。在通常情况下,编译器 只解析方法声明的类型,而不解析实体。 因此,前面描述的方法将返回 null

    要让编译器解析类型信息,可以执行以下操作之一 以下方法:

    1. 使用 AbstractTypeProcessor 刚添加到 JDK 7的编译器存储库。查看上的工作 JSR 308 和他们的编译器。 虽然这项工作主要是针对带注释的类型,但它可能对其他类型有用。 编译器允许您以反向方式使用提供的类 与Java5兼容。

    这种方法允许您编写仅被调用的处理器 就像你现在的处理器。

    2. 使用 JavacTask 取而代之的是打电话 JavacTask.analyze() . 看看 this javac test 看看如何

    这种方法使处理器看起来更像一个分析工具 而不是编译器的插件,因为您需要调用它