0

我想编写代码,如下所示。

MyClass a = new @MyAnnotation MyClass()

假设 MyClass 方法如下所示

   public class MyClass {

    int a;

    public void setValue(int a) {
        this.a = a;
    }

}

因此,当有人使用注释创建 MyClass 对象时,它应该将默认值设置为某个 x(比如 20)。

在检查器框架中,它允许我们在代码中进行如下注释。

MyClass a = new @MyAnnotation MyClass()

有谁知道我们如何在编译时将其分成两部分,如下所示?

   MyClass a = new MyClass();
   a.setValue(20);

或者如果我们能够像下面这样传递默认值也可以。

MyClass a = new @MyAnnotation(value=20) MyClass()

这可以使用注释处理器来实现吗/需要使用像 ASM 这样的字节码处理器来完成它吗?以更有意义的方式更新。

4

1 回答 1

1

您是否正在通过元注释编写自定义类型系统?也就是说,您是使用 SubtypingChecker还是创建了自己的 BaseTypeChecker 子类型?

简短的回答是,使用元注释你不能指定这种行为。长答案是,如果你有一个自定义检查器,那么有很多方法可以做到这一点。

但是请记住,编写自定义检查器比使用元注释要复杂一些。但是,如果您有自定义检查器,则可以执行以下操作之一:

选项 A:多态构造函数步骤:

  1. 创建一个 @PolyMyAnnotation 多态注释,请参阅多态限定符
  2. 为 MyClass 创建一个 PolyMorphic 构造函数,例如 @PolyMyAnnotation MyClass(@PolyMyAnnotation int a) {}
  3. 创建一个将 @MyAnnotation 添加到 int 文字类型的 TreeAnnotator。有关示例,请参见RegexTreeAnnotator.visitLiteral
  4. 将 TreeAnnotator 添加到 AnnotatedTypeFactory 使用的 TreeAnnotator 列表中。(见RegexAnnotatedTypeFactory

选项 B:使用 TreeAnnotator 步骤:

  1. 创建一个扩展 TreeAnnotator 的类
  2. 覆盖 visitNewClass
  3. 确定正在构造的对象是否是 MyClass 的实例(请参阅 ElementUtils.getQualifiedClassName 和 ElementUtils.isObjectType 以了解如何执行此操作)。
  4. 如果正在构造的类是 MyClass 的实例,如果是,则查看参数是否为 Integer 字面量。
  5. 如果项目是文字,则解析文字并将其值添加到正在构造的类型中。请注意,如果您希望它处理非文字,例如 int a = 20; 新的 MyClass(a)

然后您可以使用 ValueChecker。如果您的类型工厂扩展了 ValueAnnotatedTypeFactory,它将支持常量传播。数据流 API 还为常量传播提供了一些支持。

选项 C:自定义数据流的 CFAbstractTransfer 函数 但是,如果您有自定义检查器,则可以覆盖 CFAbstractTransfer.visitMethodInvocation 以检测何时调用 setValue 并相应地对其进行优化。您可以查看RegexTransfer的示例,或搜索扩展 CFAbstractTransfer 或实现 TransferFunction 的方法。

也就是说,数据流不能替代类型状态系统(请参阅Typestate checkers中对此的讨论)。

于 2014-09-10T22:10:38.550 回答