当前位置: 首页 > 面试题库 >

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

王子明
2023-03-14
问题内容

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

我正在使用编译器树API …

我想知道的是,当html" target="_blank">遍历“树”时,如何知道MethodInvocation的类/接口的类型。

我使用以下方法将TreePathScanner子类化:

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

}

我希望有一种方法可以告诉您要在其上调用方法的类(或接口)的类型。我会以错误的方式处理吗?感谢您的任何想法…


问题答案:

这里有几个问题。您可能对知道方法调用接收者的Java类型感兴趣,或者只是知道方法上的类被调用。Java信息更具信息性,因为它也为您提供了通用类型,例如,List<String>
而Elements仅向您提供类,例如List<E>

获取元素

要获取调用该方法的类的Element,可以执行以下操作:

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

角落案例:

1. invokedClass可能是接收者类型的超类。因此,继续运行摘要new ArrayList<String>.equals(null)将返回
AbstractList而不是ArrayList,因为equals()是在AbstractListnot中实现的ArrayList

2.例如new int[].clone(),在处理数组调用时,您将获得TypeElementclass 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()receiver将是一个ArrayTypeint[],这比以前的方法更多的信息。

让它运行

前面两种方法都要求编译器解析类的类型信息。在通常情况下,编译器仅解析方法声明的类型,而不解析主体。因此,前面描述的方法将null改为返回。

要使编译器解析类型信息,可以执行以下其中一种方法:

1.使用AbstractTypeProcessor刚刚添加到JDK的编译器存储库中的类。7.检查有关JSR
308
及其编译器的工作。尽管该工作主要是在带注释的类型上,但可能对您有用。编译器允许您以与Java
5向后兼容的方式使用提供的类。

这种方法使您可以编写与当前处理器一样被调用的处理器。

2.使用JavacTask代替并致电JavacTask.analyze()。查看此javac测试的主要方法,以了解如何在类上调用访问者。

这种方法使您的处理器看起来更像是一种分析工具,而不是编译器的插件,因为您需要直接调用它而不是使其成为常规过程。



 类似资料:
  • 我正在尝试实现注释处理器(AnnotationProcessor)。我遵循这个教程。 我能够调试注释处理器,调试器转到方法:、、、但它不转到方法。 我在网上找不到有用的东西。你能告诉我为什么会发生这种情况以及如何解决吗? 非常感谢。

  • 我正在使用注释处理器来处理方法参数的注释。 用于参数的注释类型有一个注释@参数 现在,当注释处理器运行时,我想检查参数注释()是否有参数注释。我通过执行以下代码来实现这一点。 由于某种原因,arg始终为空。是否有注释未返回的原因?

  • 我有下面的课程。两个注释(AnnotA和AnnotB),一个类的子类。java'(带@AnnotA)及其“父”基。java'(带有@AnnotB)。 编译子对象时。java,我的注释处理器报告AnnotA,但它不报告在Base中找到的注释(AnnotB)。JAVA 安诺塔。JAVA 阿诺特。JAVA 基础JAVA 小孩JAVA MyProc。JAVA 这是编译过程及其输出,正如您所看到的,没有关于

  • 我在编译使用我的注释处理器的代码时收到以下错误: 关于如何调试这个有什么提示吗?错误输出根本没有用处。有没有办法得到更详细的错误?

  • 我正在尝试使用注释处理器来验证注释,并且作为这项工作的一部分,我正在尝试弄清楚如何使用API来确定可执行文件的参数是否是参数化类型(例如List 除了解析ve.asType(). toString()给出的字符串之外,还有什么方法可以做到这一点吗?其中VariableElement ve是ExecutableElemente.getParameters()的一个元素?对这些类型有一个比简单的字符串

  • 我的处理器中有一个简单的注释,如下所示: 这适用于java文件,但一旦我将文件转换为kotlin,注释的导入就不再有效。为什么? 我需要改变什么才能让他的注释也在Kotlin中工作?从文档中,我可以看到kotlin与java注释100%兼容,所以我有点困惑这里有什么问题...如果处理器不工作,需要调整以与kotlin一起工作,我会理解,但我不知道为什么导入本身不工作... 我说的图书馆在这里:ht